feat: add basic support for SVG generator.
Add heat map example.
This commit is contained in:
@@ -17,7 +17,7 @@ indent_size = 2
|
|||||||
|
|
||||||
# C# and Visual Basic files
|
# C# and Visual Basic files
|
||||||
[*.{cs,vb}]
|
[*.{cs,vb}]
|
||||||
charset = utf-8-bom
|
charset = utf-8
|
||||||
|
|
||||||
# Analyzers
|
# Analyzers
|
||||||
dotnet_analyzer_diagnostic.category-Security.severity = error
|
dotnet_analyzer_diagnostic.category-Security.severity = error
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
<Solution>
|
<Solution>
|
||||||
|
<Folder Name="/samples/">
|
||||||
|
<Project Path="samples\HeatMap\HeatMap.csproj" />
|
||||||
|
</Folder>
|
||||||
<Folder Name="/src/">
|
<Folder Name="/src/">
|
||||||
<Project Path="src/BlazorSvgComponents/BlazorSvgComponents.csproj" />
|
<Project Path="src/BlazorSvgComponents/BlazorSvgComponents.csproj" />
|
||||||
</Folder>
|
</Folder>
|
||||||
|
|||||||
22
samples/HeatMap/Components/App.razor
Normal file
22
samples/HeatMap/Components/App.razor
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<base href="/" />
|
||||||
|
<ResourcePreloader />
|
||||||
|
<link rel="stylesheet" href="@Assets["app.css"]" />
|
||||||
|
<link rel="stylesheet" href="@Assets["HeatMap.styles.css"]" />
|
||||||
|
<link rel="stylesheet" href="@Assets["tailwind.g.css"]" />
|
||||||
|
<ImportMap />
|
||||||
|
<HeadOutlet />
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<Routes />
|
||||||
|
<ReconnectModal />
|
||||||
|
<script src="@Assets["_framework/blazor.web.js"]"></script>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
||||||
9
samples/HeatMap/Components/Layout/MainLayout.razor
Normal file
9
samples/HeatMap/Components/Layout/MainLayout.razor
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
@inherits LayoutComponentBase
|
||||||
|
|
||||||
|
@Body
|
||||||
|
|
||||||
|
<div id="blazor-error-ui" data-nosnippet>
|
||||||
|
An unhandled error has occurred.
|
||||||
|
<a href="." class="reload">Reload</a>
|
||||||
|
<span class="dismiss">🗙</span>
|
||||||
|
</div>
|
||||||
20
samples/HeatMap/Components/Layout/MainLayout.razor.css
Normal file
20
samples/HeatMap/Components/Layout/MainLayout.razor.css
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
#blazor-error-ui {
|
||||||
|
color-scheme: light only;
|
||||||
|
background: lightyellow;
|
||||||
|
bottom: 0;
|
||||||
|
box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.2);
|
||||||
|
box-sizing: border-box;
|
||||||
|
display: none;
|
||||||
|
left: 0;
|
||||||
|
padding: 0.6rem 1.25rem 0.7rem 1.25rem;
|
||||||
|
position: fixed;
|
||||||
|
width: 100%;
|
||||||
|
z-index: 1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
#blazor-error-ui .dismiss {
|
||||||
|
cursor: pointer;
|
||||||
|
position: absolute;
|
||||||
|
right: 0.75rem;
|
||||||
|
top: 0.5rem;
|
||||||
|
}
|
||||||
31
samples/HeatMap/Components/Layout/ReconnectModal.razor
Normal file
31
samples/HeatMap/Components/Layout/ReconnectModal.razor
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
<script type="module" src="@Assets["Components/Layout/ReconnectModal.razor.js"]"></script>
|
||||||
|
|
||||||
|
<dialog id="components-reconnect-modal" data-nosnippet>
|
||||||
|
<div class="components-reconnect-container">
|
||||||
|
<div class="components-rejoining-animation" aria-hidden="true">
|
||||||
|
<div></div>
|
||||||
|
<div></div>
|
||||||
|
</div>
|
||||||
|
<p class="components-reconnect-first-attempt-visible">
|
||||||
|
Rejoining the server...
|
||||||
|
</p>
|
||||||
|
<p class="components-reconnect-repeated-attempt-visible">
|
||||||
|
Rejoin failed... trying again in <span id="components-seconds-to-next-attempt"></span> seconds.
|
||||||
|
</p>
|
||||||
|
<p class="components-reconnect-failed-visible">
|
||||||
|
Failed to rejoin.<br />Please retry or reload the page.
|
||||||
|
</p>
|
||||||
|
<button id="components-reconnect-button" class="components-reconnect-failed-visible">
|
||||||
|
Retry
|
||||||
|
</button>
|
||||||
|
<p class="components-pause-visible">
|
||||||
|
The session has been paused by the server.
|
||||||
|
</p>
|
||||||
|
<button id="components-resume-button" class="components-pause-visible">
|
||||||
|
Resume
|
||||||
|
</button>
|
||||||
|
<p class="components-resume-failed-visible">
|
||||||
|
Failed to resume the session.<br />Please reload the page.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</dialog>
|
||||||
157
samples/HeatMap/Components/Layout/ReconnectModal.razor.css
Normal file
157
samples/HeatMap/Components/Layout/ReconnectModal.razor.css
Normal file
@@ -0,0 +1,157 @@
|
|||||||
|
.components-reconnect-first-attempt-visible,
|
||||||
|
.components-reconnect-repeated-attempt-visible,
|
||||||
|
.components-reconnect-failed-visible,
|
||||||
|
.components-pause-visible,
|
||||||
|
.components-resume-failed-visible,
|
||||||
|
.components-rejoining-animation {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#components-reconnect-modal.components-reconnect-show .components-reconnect-first-attempt-visible,
|
||||||
|
#components-reconnect-modal.components-reconnect-show .components-rejoining-animation,
|
||||||
|
#components-reconnect-modal.components-reconnect-paused .components-pause-visible,
|
||||||
|
#components-reconnect-modal.components-reconnect-resume-failed .components-resume-failed-visible,
|
||||||
|
#components-reconnect-modal.components-reconnect-retrying,
|
||||||
|
#components-reconnect-modal.components-reconnect-retrying .components-reconnect-repeated-attempt-visible,
|
||||||
|
#components-reconnect-modal.components-reconnect-retrying .components-rejoining-animation,
|
||||||
|
#components-reconnect-modal.components-reconnect-failed,
|
||||||
|
#components-reconnect-modal.components-reconnect-failed .components-reconnect-failed-visible {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#components-reconnect-modal {
|
||||||
|
background-color: white;
|
||||||
|
width: 20rem;
|
||||||
|
margin: 20vh auto;
|
||||||
|
padding: 2rem;
|
||||||
|
border: 0;
|
||||||
|
border-radius: 0.5rem;
|
||||||
|
box-shadow: 0 3px 6px 2px rgba(0, 0, 0, 0.3);
|
||||||
|
opacity: 0;
|
||||||
|
transition: display 0.5s allow-discrete, overlay 0.5s allow-discrete;
|
||||||
|
animation: components-reconnect-modal-fadeOutOpacity 0.5s both;
|
||||||
|
&[open]
|
||||||
|
|
||||||
|
{
|
||||||
|
animation: components-reconnect-modal-slideUp 1.5s cubic-bezier(.05, .89, .25, 1.02) 0.3s, components-reconnect-modal-fadeInOpacity 0.5s ease-in-out 0.3s;
|
||||||
|
animation-fill-mode: both;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#components-reconnect-modal::backdrop {
|
||||||
|
background-color: rgba(0, 0, 0, 0.4);
|
||||||
|
animation: components-reconnect-modal-fadeInOpacity 0.5s ease-in-out;
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes components-reconnect-modal-slideUp {
|
||||||
|
0% {
|
||||||
|
transform: translateY(30px) scale(0.95);
|
||||||
|
}
|
||||||
|
|
||||||
|
100% {
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes components-reconnect-modal-fadeInOpacity {
|
||||||
|
0% {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
100% {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes components-reconnect-modal-fadeOutOpacity {
|
||||||
|
0% {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
100% {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.components-reconnect-container {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
gap: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
#components-reconnect-modal p {
|
||||||
|
margin: 0;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
#components-reconnect-modal button {
|
||||||
|
border: 0;
|
||||||
|
background-color: #6b9ed2;
|
||||||
|
color: white;
|
||||||
|
padding: 4px 24px;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#components-reconnect-modal button:hover {
|
||||||
|
background-color: #3b6ea2;
|
||||||
|
}
|
||||||
|
|
||||||
|
#components-reconnect-modal button:active {
|
||||||
|
background-color: #6b9ed2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.components-rejoining-animation {
|
||||||
|
position: relative;
|
||||||
|
width: 80px;
|
||||||
|
height: 80px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.components-rejoining-animation div {
|
||||||
|
position: absolute;
|
||||||
|
border: 3px solid #0087ff;
|
||||||
|
opacity: 1;
|
||||||
|
border-radius: 50%;
|
||||||
|
animation: components-rejoining-animation 1.5s cubic-bezier(0, 0.2, 0.8, 1) infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
.components-rejoining-animation div:nth-child(2) {
|
||||||
|
animation-delay: -0.5s;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes components-rejoining-animation {
|
||||||
|
0% {
|
||||||
|
top: 40px;
|
||||||
|
left: 40px;
|
||||||
|
width: 0;
|
||||||
|
height: 0;
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
4.9% {
|
||||||
|
top: 40px;
|
||||||
|
left: 40px;
|
||||||
|
width: 0;
|
||||||
|
height: 0;
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
5% {
|
||||||
|
top: 40px;
|
||||||
|
left: 40px;
|
||||||
|
width: 0;
|
||||||
|
height: 0;
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
100% {
|
||||||
|
top: 0px;
|
||||||
|
left: 0px;
|
||||||
|
width: 80px;
|
||||||
|
height: 80px;
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
63
samples/HeatMap/Components/Layout/ReconnectModal.razor.js
Normal file
63
samples/HeatMap/Components/Layout/ReconnectModal.razor.js
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
// Set up event handlers
|
||||||
|
const reconnectModal = document.getElementById("components-reconnect-modal");
|
||||||
|
reconnectModal.addEventListener("components-reconnect-state-changed", handleReconnectStateChanged);
|
||||||
|
|
||||||
|
const retryButton = document.getElementById("components-reconnect-button");
|
||||||
|
retryButton.addEventListener("click", retry);
|
||||||
|
|
||||||
|
const resumeButton = document.getElementById("components-resume-button");
|
||||||
|
resumeButton.addEventListener("click", resume);
|
||||||
|
|
||||||
|
function handleReconnectStateChanged(event) {
|
||||||
|
if (event.detail.state === "show") {
|
||||||
|
reconnectModal.showModal();
|
||||||
|
} else if (event.detail.state === "hide") {
|
||||||
|
reconnectModal.close();
|
||||||
|
} else if (event.detail.state === "failed") {
|
||||||
|
document.addEventListener("visibilitychange", retryWhenDocumentBecomesVisible);
|
||||||
|
} else if (event.detail.state === "rejected") {
|
||||||
|
location.reload();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function retry() {
|
||||||
|
document.removeEventListener("visibilitychange", retryWhenDocumentBecomesVisible);
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Reconnect will asynchronously return:
|
||||||
|
// - true to mean success
|
||||||
|
// - false to mean we reached the server, but it rejected the connection (e.g., unknown circuit ID)
|
||||||
|
// - exception to mean we didn't reach the server (this can be sync or async)
|
||||||
|
const successful = await Blazor.reconnect();
|
||||||
|
if (!successful) {
|
||||||
|
// We have been able to reach the server, but the circuit is no longer available.
|
||||||
|
// We'll reload the page so the user can continue using the app as quickly as possible.
|
||||||
|
const resumeSuccessful = await Blazor.resumeCircuit();
|
||||||
|
if (!resumeSuccessful) {
|
||||||
|
location.reload();
|
||||||
|
} else {
|
||||||
|
reconnectModal.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
// We got an exception, server is currently unavailable
|
||||||
|
document.addEventListener("visibilitychange", retryWhenDocumentBecomesVisible);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function resume() {
|
||||||
|
try {
|
||||||
|
const successful = await Blazor.resumeCircuit();
|
||||||
|
if (!successful) {
|
||||||
|
location.reload();
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
location.reload();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function retryWhenDocumentBecomesVisible() {
|
||||||
|
if (document.visibilityState === "visible") {
|
||||||
|
await retry();
|
||||||
|
}
|
||||||
|
}
|
||||||
36
samples/HeatMap/Components/Pages/Error.razor
Normal file
36
samples/HeatMap/Components/Pages/Error.razor
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
@page "/Error"
|
||||||
|
@using System.Diagnostics
|
||||||
|
|
||||||
|
<PageTitle>Error</PageTitle>
|
||||||
|
|
||||||
|
<h1 class="text-danger">Error.</h1>
|
||||||
|
<h2 class="text-danger">An error occurred while processing your request.</h2>
|
||||||
|
|
||||||
|
@if (ShowRequestId)
|
||||||
|
{
|
||||||
|
<p>
|
||||||
|
<strong>Request ID:</strong> <code>@RequestId</code>
|
||||||
|
</p>
|
||||||
|
}
|
||||||
|
|
||||||
|
<h3>Development Mode</h3>
|
||||||
|
<p>
|
||||||
|
Swapping to <strong>Development</strong> environment will display more detailed information about the error that occurred.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<strong>The Development environment shouldn't be enabled for deployed applications.</strong>
|
||||||
|
It can result in displaying sensitive information from exceptions to end users.
|
||||||
|
For local debugging, enable the <strong>Development</strong> environment by setting the <strong>ASPNETCORE_ENVIRONMENT</strong> environment variable to <strong>Development</strong>
|
||||||
|
and restarting the app.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
@code{
|
||||||
|
[CascadingParameter]
|
||||||
|
private HttpContext? HttpContext { get; set; }
|
||||||
|
|
||||||
|
private string? RequestId { get; set; }
|
||||||
|
private bool ShowRequestId => !string.IsNullOrEmpty(RequestId);
|
||||||
|
|
||||||
|
protected override void OnInitialized() =>
|
||||||
|
RequestId = Activity.Current?.Id ?? HttpContext?.TraceIdentifier;
|
||||||
|
}
|
||||||
125
samples/HeatMap/Components/Pages/Home.razor
Normal file
125
samples/HeatMap/Components/Pages/Home.razor
Normal file
@@ -0,0 +1,125 @@
|
|||||||
|
@page "/"
|
||||||
|
@using BlazorSvgComponents.Models
|
||||||
|
@using HotMap.Services
|
||||||
|
@using HotMap.Utils
|
||||||
|
@inject HeatMapService HeatMapInstance
|
||||||
|
|
||||||
|
<PageTitle>Heat Map!</PageTitle>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="w-full">
|
||||||
|
<p class="text-2xl">
|
||||||
|
Heat map below:
|
||||||
|
</p>
|
||||||
|
<div>
|
||||||
|
<SvgContainer Width="800" Height="400" ViewBox="@GetHeatMapViewBox()">
|
||||||
|
<SvgGroup Transform="@(SvgTransform.CreateBuilder().Translate(23, 10).Build())">
|
||||||
|
@foreach ((int i, string text) in _monthIndexes)
|
||||||
|
{
|
||||||
|
<SvgText Content="@text" Transform="@MonthTextTransform(i)" Class="text-[10px]"/>
|
||||||
|
}
|
||||||
|
</SvgGroup>
|
||||||
|
<SvgGroup Transform="@(SvgTransform.CreateBuilder().Translate(2, 24).Build())">
|
||||||
|
@foreach ((string text, int i) in Weekdays.Select((s, i) => (s, i)))
|
||||||
|
{
|
||||||
|
<SvgText Content="@text" Transform="@(DayTextTransform(i))" Class="text-[10px]"/>
|
||||||
|
}
|
||||||
|
</SvgGroup>
|
||||||
|
<SvgGroup Transform="@(SvgTransform.CreateBuilder().Translate(25, 15).Build())">
|
||||||
|
@foreach ((HeatMapGroupByWeek itemsByItem, int i) in _groupsByWeek.WithIndex())
|
||||||
|
{
|
||||||
|
<SvgGroup Transform="@(WeekGridTransform(i))">
|
||||||
|
@foreach ((HeatMapItem item, int j) in itemsByItem.Items.WithIndex())
|
||||||
|
{
|
||||||
|
<Rectangle Width="@Width" Height="@Width" Transform="@(WeekdayGridTransform(j))"
|
||||||
|
Class="@(GetColorByContribution(item.Contributions))"/>
|
||||||
|
}
|
||||||
|
</SvgGroup>
|
||||||
|
}
|
||||||
|
</SvgGroup>
|
||||||
|
</SvgContainer>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
@code {
|
||||||
|
private const int Width = 10;
|
||||||
|
private const int Spacing = 2;
|
||||||
|
|
||||||
|
private readonly record struct MonthIndex(int Pos, string Month);
|
||||||
|
|
||||||
|
private readonly List<MonthIndex> _monthIndexes = [];
|
||||||
|
private readonly List<HeatMapGroupByWeek> _groupsByWeek = [];
|
||||||
|
|
||||||
|
protected override void OnInitialized()
|
||||||
|
{
|
||||||
|
base.OnInitialized();
|
||||||
|
|
||||||
|
_groupsByWeek.AddRange(HeatMapInstance.GetItemsByWeek());
|
||||||
|
|
||||||
|
// To get the last item, we skip the first item.
|
||||||
|
// So index of current item is i + 1, and index of last item is i.
|
||||||
|
foreach ((HeatMapGroupByWeek group, int i) in _groupsByWeek.Skip(1).WithIndex())
|
||||||
|
{
|
||||||
|
if (group.Monday.Month == _groupsByWeek[i].Monday.Month)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If current week item is not in the same month as the last week item.
|
||||||
|
_monthIndexes.Add(new MonthIndex(i + 1, Months[group.Monday.Month - 1]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private SvgViewBox GetHeatMapViewBox()
|
||||||
|
{
|
||||||
|
int width = 25 + Width * _groupsByWeek.Count + Spacing * (_groupsByWeek.Count - 1);
|
||||||
|
int height = 15 + Width * 7 + Spacing * 6;
|
||||||
|
|
||||||
|
// Add an extra 10 pixels to make sure nothing is hidden.
|
||||||
|
return new SvgViewBox(0, 0, width + 10, height + 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static readonly List<string> Months =
|
||||||
|
[
|
||||||
|
"1月", "2月", "3月", "4月", "5月", "6月",
|
||||||
|
"7月", "8月", "9月", "10月", "11月", "12月"
|
||||||
|
];
|
||||||
|
|
||||||
|
// private static readonly List<string> Weekdays = ["周一", "周二", "周三", "周四", "周五", "周六", "周日"];
|
||||||
|
private static readonly List<string> Weekdays = ["周一", "周三", "周五"];
|
||||||
|
|
||||||
|
private static SvgTransform WeekdayGridTransform(int y)
|
||||||
|
{
|
||||||
|
return SvgTransform.CreateBuilder().Translate(0, y * (Width + Spacing)).Build();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static SvgTransform WeekGridTransform(int x)
|
||||||
|
{
|
||||||
|
return SvgTransform.CreateBuilder().Translate(x * (Width + Spacing)).Build();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static SvgTransform MonthTextTransform(int x)
|
||||||
|
{
|
||||||
|
return SvgTransform.CreateBuilder().Translate(x * (Width + Spacing)).Build();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static SvgTransform DayTextTransform(int y)
|
||||||
|
{
|
||||||
|
// We only show Monday, Wednesday and Friday, so there are two days between texts.
|
||||||
|
return SvgTransform.CreateBuilder().Translate(0, y * 2 * (Width + Spacing)).Build();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string GetColorByContribution(int contribution)
|
||||||
|
{
|
||||||
|
return contribution switch
|
||||||
|
{
|
||||||
|
0 => "fill-gray-200",
|
||||||
|
1 or 2 => "fill-blue-100",
|
||||||
|
3 or 4 => "fill-blue-300",
|
||||||
|
5 or 6 => "fill-blue-500",
|
||||||
|
7 or 8 => "fill-blue-700",
|
||||||
|
_ => "fill-blue-800"
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
5
samples/HeatMap/Components/Pages/NotFound.razor
Normal file
5
samples/HeatMap/Components/Pages/NotFound.razor
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
@page "/not-found"
|
||||||
|
@layout MainLayout
|
||||||
|
|
||||||
|
<h3>Not Found</h3>
|
||||||
|
<p>Sorry, the content you are looking for does not exist.</p>
|
||||||
6
samples/HeatMap/Components/Routes.razor
Normal file
6
samples/HeatMap/Components/Routes.razor
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<Router AppAssembly="typeof(Program).Assembly" NotFoundPage="typeof(Pages.NotFound)">
|
||||||
|
<Found Context="routeData">
|
||||||
|
<RouteView RouteData="routeData" DefaultLayout="typeof(Layout.MainLayout)" />
|
||||||
|
<FocusOnNavigate RouteData="routeData" Selector="h1" />
|
||||||
|
</Found>
|
||||||
|
</Router>
|
||||||
12
samples/HeatMap/Components/_Imports.razor
Normal file
12
samples/HeatMap/Components/_Imports.razor
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
@using System.Net.Http
|
||||||
|
@using System.Net.Http.Json
|
||||||
|
@using Microsoft.AspNetCore.Components.Forms
|
||||||
|
@using Microsoft.AspNetCore.Components.Routing
|
||||||
|
@using Microsoft.AspNetCore.Components.Web
|
||||||
|
@using static Microsoft.AspNetCore.Components.Web.RenderMode
|
||||||
|
@using Microsoft.AspNetCore.Components.Web.Virtualization
|
||||||
|
@using Microsoft.JSInterop
|
||||||
|
@using HotMap
|
||||||
|
@using HotMap.Components
|
||||||
|
@using HotMap.Components.Layout
|
||||||
|
@using BlazorSvgComponents
|
||||||
53
samples/HeatMap/Directory.Build.targets
Normal file
53
samples/HeatMap/Directory.Build.targets
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
<Project>
|
||||||
|
<PropertyGroup>
|
||||||
|
<ClientAssetsRestoreCommand Condition="'$(ClientAssesRestoreCommand)' == ''">pnpm install</ClientAssetsRestoreCommand>
|
||||||
|
<ClientAssetsBuildCommand Condition="'$(ClientAssetsBuildCommand)' == ''">pnpm run build</ClientAssetsBuildCommand>
|
||||||
|
<ClientAssetsBuildOutputParameter Condition="'$(ClientAssetsBuildOutputParameter)' == ''">--output</ClientAssetsBuildOutputParameter>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<_RestoreClientAssetsBeforeTargets Condition="'$(TargetFramework)' == ''">DispatchToInnerBuilds</_RestoreClientAssetsBeforeTargets>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<Target Name="RestoreClientAssets" BeforeTargets="$(_RestoreClientAssetsBeforeTargets)">
|
||||||
|
<Message Importance="high" Text="Running $(ClientAssetsRestoreCommand)"/>
|
||||||
|
<Exec Command="$(ClientAssetsRestoreCommand)"/>
|
||||||
|
</Target>
|
||||||
|
|
||||||
|
<Target Name="BuildClientAssets" DependsOnTargets="RestoreClientAssets" BeforeTargets="AssignTargetPaths">
|
||||||
|
<PropertyGroup>
|
||||||
|
<_ClientAssetsOutputFullPath>$([System.IO.Path]::GetFullPath('$(IntermediateOutputPath)ClientAssets'))</_ClientAssetsOutputFullPath>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<MakeDir Directories="$(_ClientAssetsOutputFullPath)"/>
|
||||||
|
<Exec Command="$(ClientAssetsBuildCommand) $(ClientAssetsBuildOutputParameter) $(_ClientAssetsOutputFullPath)"/>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<_ClientAssetsBuildOutput Include="$(IntermediateOutputPath)ClientAssets\**"/>
|
||||||
|
</ItemGroup>
|
||||||
|
</Target>
|
||||||
|
|
||||||
|
<Target Name="DefineClientAssets" AfterTargets="BuildClientAssets" DependsOnTargets="ResolveStaticWebAssetsConfiguration">
|
||||||
|
<ItemGroup>
|
||||||
|
<FileWrites Include="@(_ClientAssetsBuildOutput)"/>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<DefineStaticWebAssets
|
||||||
|
CandidateAssets="@(_ClientAssetsBuildOutput)"
|
||||||
|
SourceId="$(PackageId)"
|
||||||
|
SourceType="Computed"
|
||||||
|
ContentRoot="$(_ClientAssetsOutputFullPath)"
|
||||||
|
BasePath="$(StaticWebAssetBasePath)"
|
||||||
|
>
|
||||||
|
<Output TaskParameter="Assets" ItemName="StaticWebAsset"/>
|
||||||
|
<Output TaskParameter="Assets" ItemName="_ClientAssetsStaticWebAsset"/>
|
||||||
|
</DefineStaticWebAssets>
|
||||||
|
|
||||||
|
<DefineStaticWebAssetEndpoints
|
||||||
|
CandidateAssets="@(_ClientAssetsStaticWebAsset)"
|
||||||
|
ContentTypeMappings="@(StaticWebAssetContentTypeMapping)"
|
||||||
|
>
|
||||||
|
<Output TaskParameter="Endpoints" ItemName="StaticWebAssetEndpoint" />
|
||||||
|
</DefineStaticWebAssetEndpoints>
|
||||||
|
</Target>
|
||||||
|
</Project>
|
||||||
19
samples/HeatMap/HeatMap.csproj
Normal file
19
samples/HeatMap/HeatMap.csproj
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net10.0</TargetFramework>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<BlazorDisableThrowNavigationException>true</BlazorDisableThrowNavigationException>
|
||||||
|
<RootNamespace>HotMap</RootNamespace>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\..\src\BlazorSvgComponents\BlazorSvgComponents.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<ClientAssetsRestoreCommand>pnpm install</ClientAssetsRestoreCommand>
|
||||||
|
<ClientAssetsBuildCommand>pwsh build.ps1</ClientAssetsBuildCommand>
|
||||||
|
</PropertyGroup>
|
||||||
|
</Project>
|
||||||
28
samples/HeatMap/Program.cs
Normal file
28
samples/HeatMap/Program.cs
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
using HotMap.Components;
|
||||||
|
using HotMap.Services;
|
||||||
|
|
||||||
|
var builder = WebApplication.CreateBuilder(args);
|
||||||
|
|
||||||
|
// Add services to the container.
|
||||||
|
builder.Services.AddRazorComponents()
|
||||||
|
.AddInteractiveServerComponents();
|
||||||
|
builder.Services.AddSingleton<HeatMapService>();
|
||||||
|
|
||||||
|
var app = builder.Build();
|
||||||
|
|
||||||
|
// Configure the HTTP request pipeline.
|
||||||
|
if (!app.Environment.IsDevelopment())
|
||||||
|
{
|
||||||
|
app.UseExceptionHandler("/Error", createScopeForErrors: true);
|
||||||
|
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
|
||||||
|
app.UseHsts();
|
||||||
|
}
|
||||||
|
app.UseStatusCodePagesWithReExecute("/not-found", createScopeForStatusCodePages: true);
|
||||||
|
|
||||||
|
app.UseAntiforgery();
|
||||||
|
|
||||||
|
app.MapStaticAssets();
|
||||||
|
app.MapRazorComponents<App>()
|
||||||
|
.AddInteractiveServerRenderMode();
|
||||||
|
|
||||||
|
app.Run();
|
||||||
14
samples/HeatMap/Properties/launchSettings.json
Normal file
14
samples/HeatMap/Properties/launchSettings.json
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
"$schema": "https://json.schemastore.org/launchsettings.json",
|
||||||
|
"profiles": {
|
||||||
|
"http": {
|
||||||
|
"commandName": "Project",
|
||||||
|
"dotnetRunMessages": true,
|
||||||
|
"launchBrowser": false,
|
||||||
|
"applicationUrl": "http://localhost:5184",
|
||||||
|
"environmentVariables": {
|
||||||
|
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
1485
samples/HeatMap/Services/HeatMapService.cs
Normal file
1485
samples/HeatMap/Services/HeatMapService.cs
Normal file
File diff suppressed because it is too large
Load Diff
25
samples/HeatMap/Utils/UtilsExtensions.cs
Normal file
25
samples/HeatMap/Utils/UtilsExtensions.cs
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
namespace HotMap.Utils;
|
||||||
|
|
||||||
|
public static class UtilsExtensions
|
||||||
|
{
|
||||||
|
extension(DateOnly date)
|
||||||
|
{
|
||||||
|
public DateOnly GetMonday()
|
||||||
|
{
|
||||||
|
return date.DayOfWeek switch
|
||||||
|
{
|
||||||
|
DayOfWeek.Monday => date,
|
||||||
|
DayOfWeek.Sunday => date.AddDays(-6),
|
||||||
|
_ => date.AddDays(1 - (int)date.DayOfWeek)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension<T>(IEnumerable<T> enumerable)
|
||||||
|
{
|
||||||
|
public IEnumerable<(T, int)> WithIndex()
|
||||||
|
{
|
||||||
|
return enumerable.Select((v, i) => (v, i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
8
samples/HeatMap/appsettings.Development.json
Normal file
8
samples/HeatMap/appsettings.Development.json
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"Logging": {
|
||||||
|
"LogLevel": {
|
||||||
|
"Default": "Information",
|
||||||
|
"Microsoft.AspNetCore": "Warning"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
9
samples/HeatMap/appsettings.json
Normal file
9
samples/HeatMap/appsettings.json
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"Logging": {
|
||||||
|
"LogLevel": {
|
||||||
|
"Default": "Information",
|
||||||
|
"Microsoft.AspNetCore": "Warning"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"AllowedHosts": "*"
|
||||||
|
}
|
||||||
11
samples/HeatMap/build.ps1
Normal file
11
samples/HeatMap/build.ps1
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
[cmdletbinding()]
|
||||||
|
param(
|
||||||
|
[string]$output = "wwwroot"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
$PSNativeCommandUseErrorActionPreference = $true
|
||||||
|
$ErrorActionPreference = "Stop"
|
||||||
|
|
||||||
|
Write-Output "Output directory: $output"
|
||||||
|
pnpm tailwindcss -i wwwroot/tailwind.css -o $output/tailwind.g.css
|
||||||
17
samples/HeatMap/package.json
Normal file
17
samples/HeatMap/package.json
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
"name": "HotMap",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "",
|
||||||
|
"main": "index.js",
|
||||||
|
"scripts": {
|
||||||
|
"test": "echo \"Error: no test specified\" && exit 1"
|
||||||
|
},
|
||||||
|
"keywords": [],
|
||||||
|
"author": "",
|
||||||
|
"license": "ISC",
|
||||||
|
"packageManager": "pnpm@10.26.2",
|
||||||
|
"dependencies": {
|
||||||
|
"@tailwindcss/cli": "^4.1.18",
|
||||||
|
"tailwindcss": "^4.1.18"
|
||||||
|
}
|
||||||
|
}
|
||||||
622
samples/HeatMap/pnpm-lock.yaml
generated
Normal file
622
samples/HeatMap/pnpm-lock.yaml
generated
Normal file
@@ -0,0 +1,622 @@
|
|||||||
|
lockfileVersion: '9.0'
|
||||||
|
|
||||||
|
settings:
|
||||||
|
autoInstallPeers: true
|
||||||
|
excludeLinksFromLockfile: false
|
||||||
|
|
||||||
|
importers:
|
||||||
|
|
||||||
|
.:
|
||||||
|
dependencies:
|
||||||
|
'@tailwindcss/cli':
|
||||||
|
specifier: ^4.1.18
|
||||||
|
version: 4.1.18
|
||||||
|
tailwindcss:
|
||||||
|
specifier: ^4.1.18
|
||||||
|
version: 4.1.18
|
||||||
|
|
||||||
|
packages:
|
||||||
|
|
||||||
|
'@jridgewell/gen-mapping@0.3.13':
|
||||||
|
resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==}
|
||||||
|
|
||||||
|
'@jridgewell/remapping@2.3.5':
|
||||||
|
resolution: {integrity: sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==}
|
||||||
|
|
||||||
|
'@jridgewell/resolve-uri@3.1.2':
|
||||||
|
resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==}
|
||||||
|
engines: {node: '>=6.0.0'}
|
||||||
|
|
||||||
|
'@jridgewell/sourcemap-codec@1.5.5':
|
||||||
|
resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==}
|
||||||
|
|
||||||
|
'@jridgewell/trace-mapping@0.3.31':
|
||||||
|
resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==}
|
||||||
|
|
||||||
|
'@parcel/watcher-android-arm64@2.5.1':
|
||||||
|
resolution: {integrity: sha512-KF8+j9nNbUN8vzOFDpRMsaKBHZ/mcjEjMToVMJOhTozkDonQFFrRcfdLWn6yWKCmJKmdVxSgHiYvTCef4/qcBA==}
|
||||||
|
engines: {node: '>= 10.0.0'}
|
||||||
|
cpu: [arm64]
|
||||||
|
os: [android]
|
||||||
|
|
||||||
|
'@parcel/watcher-darwin-arm64@2.5.1':
|
||||||
|
resolution: {integrity: sha512-eAzPv5osDmZyBhou8PoF4i6RQXAfeKL9tjb3QzYuccXFMQU0ruIc/POh30ePnaOyD1UXdlKguHBmsTs53tVoPw==}
|
||||||
|
engines: {node: '>= 10.0.0'}
|
||||||
|
cpu: [arm64]
|
||||||
|
os: [darwin]
|
||||||
|
|
||||||
|
'@parcel/watcher-darwin-x64@2.5.1':
|
||||||
|
resolution: {integrity: sha512-1ZXDthrnNmwv10A0/3AJNZ9JGlzrF82i3gNQcWOzd7nJ8aj+ILyW1MTxVk35Db0u91oD5Nlk9MBiujMlwmeXZg==}
|
||||||
|
engines: {node: '>= 10.0.0'}
|
||||||
|
cpu: [x64]
|
||||||
|
os: [darwin]
|
||||||
|
|
||||||
|
'@parcel/watcher-freebsd-x64@2.5.1':
|
||||||
|
resolution: {integrity: sha512-SI4eljM7Flp9yPuKi8W0ird8TI/JK6CSxju3NojVI6BjHsTyK7zxA9urjVjEKJ5MBYC+bLmMcbAWlZ+rFkLpJQ==}
|
||||||
|
engines: {node: '>= 10.0.0'}
|
||||||
|
cpu: [x64]
|
||||||
|
os: [freebsd]
|
||||||
|
|
||||||
|
'@parcel/watcher-linux-arm-glibc@2.5.1':
|
||||||
|
resolution: {integrity: sha512-RCdZlEyTs8geyBkkcnPWvtXLY44BCeZKmGYRtSgtwwnHR4dxfHRG3gR99XdMEdQ7KeiDdasJwwvNSF5jKtDwdA==}
|
||||||
|
engines: {node: '>= 10.0.0'}
|
||||||
|
cpu: [arm]
|
||||||
|
os: [linux]
|
||||||
|
libc: [glibc]
|
||||||
|
|
||||||
|
'@parcel/watcher-linux-arm-musl@2.5.1':
|
||||||
|
resolution: {integrity: sha512-6E+m/Mm1t1yhB8X412stiKFG3XykmgdIOqhjWj+VL8oHkKABfu/gjFj8DvLrYVHSBNC+/u5PeNrujiSQ1zwd1Q==}
|
||||||
|
engines: {node: '>= 10.0.0'}
|
||||||
|
cpu: [arm]
|
||||||
|
os: [linux]
|
||||||
|
libc: [musl]
|
||||||
|
|
||||||
|
'@parcel/watcher-linux-arm64-glibc@2.5.1':
|
||||||
|
resolution: {integrity: sha512-LrGp+f02yU3BN9A+DGuY3v3bmnFUggAITBGriZHUREfNEzZh/GO06FF5u2kx8x+GBEUYfyTGamol4j3m9ANe8w==}
|
||||||
|
engines: {node: '>= 10.0.0'}
|
||||||
|
cpu: [arm64]
|
||||||
|
os: [linux]
|
||||||
|
libc: [glibc]
|
||||||
|
|
||||||
|
'@parcel/watcher-linux-arm64-musl@2.5.1':
|
||||||
|
resolution: {integrity: sha512-cFOjABi92pMYRXS7AcQv9/M1YuKRw8SZniCDw0ssQb/noPkRzA+HBDkwmyOJYp5wXcsTrhxO0zq1U11cK9jsFg==}
|
||||||
|
engines: {node: '>= 10.0.0'}
|
||||||
|
cpu: [arm64]
|
||||||
|
os: [linux]
|
||||||
|
libc: [musl]
|
||||||
|
|
||||||
|
'@parcel/watcher-linux-x64-glibc@2.5.1':
|
||||||
|
resolution: {integrity: sha512-GcESn8NZySmfwlTsIur+49yDqSny2IhPeZfXunQi48DMugKeZ7uy1FX83pO0X22sHntJ4Ub+9k34XQCX+oHt2A==}
|
||||||
|
engines: {node: '>= 10.0.0'}
|
||||||
|
cpu: [x64]
|
||||||
|
os: [linux]
|
||||||
|
libc: [glibc]
|
||||||
|
|
||||||
|
'@parcel/watcher-linux-x64-musl@2.5.1':
|
||||||
|
resolution: {integrity: sha512-n0E2EQbatQ3bXhcH2D1XIAANAcTZkQICBPVaxMeaCVBtOpBZpWJuf7LwyWPSBDITb7In8mqQgJ7gH8CILCURXg==}
|
||||||
|
engines: {node: '>= 10.0.0'}
|
||||||
|
cpu: [x64]
|
||||||
|
os: [linux]
|
||||||
|
libc: [musl]
|
||||||
|
|
||||||
|
'@parcel/watcher-win32-arm64@2.5.1':
|
||||||
|
resolution: {integrity: sha512-RFzklRvmc3PkjKjry3hLF9wD7ppR4AKcWNzH7kXR7GUe0Igb3Nz8fyPwtZCSquGrhU5HhUNDr/mKBqj7tqA2Vw==}
|
||||||
|
engines: {node: '>= 10.0.0'}
|
||||||
|
cpu: [arm64]
|
||||||
|
os: [win32]
|
||||||
|
|
||||||
|
'@parcel/watcher-win32-ia32@2.5.1':
|
||||||
|
resolution: {integrity: sha512-c2KkcVN+NJmuA7CGlaGD1qJh1cLfDnQsHjE89E60vUEMlqduHGCdCLJCID5geFVM0dOtA3ZiIO8BoEQmzQVfpQ==}
|
||||||
|
engines: {node: '>= 10.0.0'}
|
||||||
|
cpu: [ia32]
|
||||||
|
os: [win32]
|
||||||
|
|
||||||
|
'@parcel/watcher-win32-x64@2.5.1':
|
||||||
|
resolution: {integrity: sha512-9lHBdJITeNR++EvSQVUcaZoWupyHfXe1jZvGZ06O/5MflPcuPLtEphScIBL+AiCWBO46tDSHzWyD0uDmmZqsgA==}
|
||||||
|
engines: {node: '>= 10.0.0'}
|
||||||
|
cpu: [x64]
|
||||||
|
os: [win32]
|
||||||
|
|
||||||
|
'@parcel/watcher@2.5.1':
|
||||||
|
resolution: {integrity: sha512-dfUnCxiN9H4ap84DvD2ubjw+3vUNpstxa0TneY/Paat8a3R4uQZDLSvWjmznAY/DoahqTHl9V46HF/Zs3F29pg==}
|
||||||
|
engines: {node: '>= 10.0.0'}
|
||||||
|
|
||||||
|
'@tailwindcss/cli@4.1.18':
|
||||||
|
resolution: {integrity: sha512-sMZ+lZbDyxwjD2E0L7oRUjJ01Ffjtme5OtjvvnC+cV4CEDcbqzbp25TCpxHj6kWLU9+DlqJOiNgSOgctC2aZmg==}
|
||||||
|
hasBin: true
|
||||||
|
|
||||||
|
'@tailwindcss/node@4.1.18':
|
||||||
|
resolution: {integrity: sha512-DoR7U1P7iYhw16qJ49fgXUlry1t4CpXeErJHnQ44JgTSKMaZUdf17cfn5mHchfJ4KRBZRFA/Coo+MUF5+gOaCQ==}
|
||||||
|
|
||||||
|
'@tailwindcss/oxide-android-arm64@4.1.18':
|
||||||
|
resolution: {integrity: sha512-dJHz7+Ugr9U/diKJA0W6N/6/cjI+ZTAoxPf9Iz9BFRF2GzEX8IvXxFIi/dZBloVJX/MZGvRuFA9rqwdiIEZQ0Q==}
|
||||||
|
engines: {node: '>= 10'}
|
||||||
|
cpu: [arm64]
|
||||||
|
os: [android]
|
||||||
|
|
||||||
|
'@tailwindcss/oxide-darwin-arm64@4.1.18':
|
||||||
|
resolution: {integrity: sha512-Gc2q4Qhs660bhjyBSKgq6BYvwDz4G+BuyJ5H1xfhmDR3D8HnHCmT/BSkvSL0vQLy/nkMLY20PQ2OoYMO15Jd0A==}
|
||||||
|
engines: {node: '>= 10'}
|
||||||
|
cpu: [arm64]
|
||||||
|
os: [darwin]
|
||||||
|
|
||||||
|
'@tailwindcss/oxide-darwin-x64@4.1.18':
|
||||||
|
resolution: {integrity: sha512-FL5oxr2xQsFrc3X9o1fjHKBYBMD1QZNyc1Xzw/h5Qu4XnEBi3dZn96HcHm41c/euGV+GRiXFfh2hUCyKi/e+yw==}
|
||||||
|
engines: {node: '>= 10'}
|
||||||
|
cpu: [x64]
|
||||||
|
os: [darwin]
|
||||||
|
|
||||||
|
'@tailwindcss/oxide-freebsd-x64@4.1.18':
|
||||||
|
resolution: {integrity: sha512-Fj+RHgu5bDodmV1dM9yAxlfJwkkWvLiRjbhuO2LEtwtlYlBgiAT4x/j5wQr1tC3SANAgD+0YcmWVrj8R9trVMA==}
|
||||||
|
engines: {node: '>= 10'}
|
||||||
|
cpu: [x64]
|
||||||
|
os: [freebsd]
|
||||||
|
|
||||||
|
'@tailwindcss/oxide-linux-arm-gnueabihf@4.1.18':
|
||||||
|
resolution: {integrity: sha512-Fp+Wzk/Ws4dZn+LV2Nqx3IilnhH51YZoRaYHQsVq3RQvEl+71VGKFpkfHrLM/Li+kt5c0DJe/bHXK1eHgDmdiA==}
|
||||||
|
engines: {node: '>= 10'}
|
||||||
|
cpu: [arm]
|
||||||
|
os: [linux]
|
||||||
|
|
||||||
|
'@tailwindcss/oxide-linux-arm64-gnu@4.1.18':
|
||||||
|
resolution: {integrity: sha512-S0n3jboLysNbh55Vrt7pk9wgpyTTPD0fdQeh7wQfMqLPM/Hrxi+dVsLsPrycQjGKEQk85Kgbx+6+QnYNiHalnw==}
|
||||||
|
engines: {node: '>= 10'}
|
||||||
|
cpu: [arm64]
|
||||||
|
os: [linux]
|
||||||
|
libc: [glibc]
|
||||||
|
|
||||||
|
'@tailwindcss/oxide-linux-arm64-musl@4.1.18':
|
||||||
|
resolution: {integrity: sha512-1px92582HkPQlaaCkdRcio71p8bc8i/ap5807tPRDK/uw953cauQBT8c5tVGkOwrHMfc2Yh6UuxaH4vtTjGvHg==}
|
||||||
|
engines: {node: '>= 10'}
|
||||||
|
cpu: [arm64]
|
||||||
|
os: [linux]
|
||||||
|
libc: [musl]
|
||||||
|
|
||||||
|
'@tailwindcss/oxide-linux-x64-gnu@4.1.18':
|
||||||
|
resolution: {integrity: sha512-v3gyT0ivkfBLoZGF9LyHmts0Isc8jHZyVcbzio6Wpzifg/+5ZJpDiRiUhDLkcr7f/r38SWNe7ucxmGW3j3Kb/g==}
|
||||||
|
engines: {node: '>= 10'}
|
||||||
|
cpu: [x64]
|
||||||
|
os: [linux]
|
||||||
|
libc: [glibc]
|
||||||
|
|
||||||
|
'@tailwindcss/oxide-linux-x64-musl@4.1.18':
|
||||||
|
resolution: {integrity: sha512-bhJ2y2OQNlcRwwgOAGMY0xTFStt4/wyU6pvI6LSuZpRgKQwxTec0/3Scu91O8ir7qCR3AuepQKLU/kX99FouqQ==}
|
||||||
|
engines: {node: '>= 10'}
|
||||||
|
cpu: [x64]
|
||||||
|
os: [linux]
|
||||||
|
libc: [musl]
|
||||||
|
|
||||||
|
'@tailwindcss/oxide-wasm32-wasi@4.1.18':
|
||||||
|
resolution: {integrity: sha512-LffYTvPjODiP6PT16oNeUQJzNVyJl1cjIebq/rWWBF+3eDst5JGEFSc5cWxyRCJ0Mxl+KyIkqRxk1XPEs9x8TA==}
|
||||||
|
engines: {node: '>=14.0.0'}
|
||||||
|
cpu: [wasm32]
|
||||||
|
bundledDependencies:
|
||||||
|
- '@napi-rs/wasm-runtime'
|
||||||
|
- '@emnapi/core'
|
||||||
|
- '@emnapi/runtime'
|
||||||
|
- '@tybys/wasm-util'
|
||||||
|
- '@emnapi/wasi-threads'
|
||||||
|
- tslib
|
||||||
|
|
||||||
|
'@tailwindcss/oxide-win32-arm64-msvc@4.1.18':
|
||||||
|
resolution: {integrity: sha512-HjSA7mr9HmC8fu6bdsZvZ+dhjyGCLdotjVOgLA2vEqxEBZaQo9YTX4kwgEvPCpRh8o4uWc4J/wEoFzhEmjvPbA==}
|
||||||
|
engines: {node: '>= 10'}
|
||||||
|
cpu: [arm64]
|
||||||
|
os: [win32]
|
||||||
|
|
||||||
|
'@tailwindcss/oxide-win32-x64-msvc@4.1.18':
|
||||||
|
resolution: {integrity: sha512-bJWbyYpUlqamC8dpR7pfjA0I7vdF6t5VpUGMWRkXVE3AXgIZjYUYAK7II1GNaxR8J1SSrSrppRar8G++JekE3Q==}
|
||||||
|
engines: {node: '>= 10'}
|
||||||
|
cpu: [x64]
|
||||||
|
os: [win32]
|
||||||
|
|
||||||
|
'@tailwindcss/oxide@4.1.18':
|
||||||
|
resolution: {integrity: sha512-EgCR5tTS5bUSKQgzeMClT6iCY3ToqE1y+ZB0AKldj809QXk1Y+3jB0upOYZrn9aGIzPtUsP7sX4QQ4XtjBB95A==}
|
||||||
|
engines: {node: '>= 10'}
|
||||||
|
|
||||||
|
braces@3.0.3:
|
||||||
|
resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==}
|
||||||
|
engines: {node: '>=8'}
|
||||||
|
|
||||||
|
detect-libc@1.0.3:
|
||||||
|
resolution: {integrity: sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==}
|
||||||
|
engines: {node: '>=0.10'}
|
||||||
|
hasBin: true
|
||||||
|
|
||||||
|
detect-libc@2.1.2:
|
||||||
|
resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==}
|
||||||
|
engines: {node: '>=8'}
|
||||||
|
|
||||||
|
enhanced-resolve@5.18.4:
|
||||||
|
resolution: {integrity: sha512-LgQMM4WXU3QI+SYgEc2liRgznaD5ojbmY3sb8LxyguVkIg5FxdpTkvk72te2R38/TGKxH634oLxXRGY6d7AP+Q==}
|
||||||
|
engines: {node: '>=10.13.0'}
|
||||||
|
|
||||||
|
fill-range@7.1.1:
|
||||||
|
resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==}
|
||||||
|
engines: {node: '>=8'}
|
||||||
|
|
||||||
|
graceful-fs@4.2.11:
|
||||||
|
resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==}
|
||||||
|
|
||||||
|
is-extglob@2.1.1:
|
||||||
|
resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==}
|
||||||
|
engines: {node: '>=0.10.0'}
|
||||||
|
|
||||||
|
is-glob@4.0.3:
|
||||||
|
resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==}
|
||||||
|
engines: {node: '>=0.10.0'}
|
||||||
|
|
||||||
|
is-number@7.0.0:
|
||||||
|
resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==}
|
||||||
|
engines: {node: '>=0.12.0'}
|
||||||
|
|
||||||
|
jiti@2.6.1:
|
||||||
|
resolution: {integrity: sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==}
|
||||||
|
hasBin: true
|
||||||
|
|
||||||
|
lightningcss-android-arm64@1.30.2:
|
||||||
|
resolution: {integrity: sha512-BH9sEdOCahSgmkVhBLeU7Hc9DWeZ1Eb6wNS6Da8igvUwAe0sqROHddIlvU06q3WyXVEOYDZ6ykBZQnjTbmo4+A==}
|
||||||
|
engines: {node: '>= 12.0.0'}
|
||||||
|
cpu: [arm64]
|
||||||
|
os: [android]
|
||||||
|
|
||||||
|
lightningcss-darwin-arm64@1.30.2:
|
||||||
|
resolution: {integrity: sha512-ylTcDJBN3Hp21TdhRT5zBOIi73P6/W0qwvlFEk22fkdXchtNTOU4Qc37SkzV+EKYxLouZ6M4LG9NfZ1qkhhBWA==}
|
||||||
|
engines: {node: '>= 12.0.0'}
|
||||||
|
cpu: [arm64]
|
||||||
|
os: [darwin]
|
||||||
|
|
||||||
|
lightningcss-darwin-x64@1.30.2:
|
||||||
|
resolution: {integrity: sha512-oBZgKchomuDYxr7ilwLcyms6BCyLn0z8J0+ZZmfpjwg9fRVZIR5/GMXd7r9RH94iDhld3UmSjBM6nXWM2TfZTQ==}
|
||||||
|
engines: {node: '>= 12.0.0'}
|
||||||
|
cpu: [x64]
|
||||||
|
os: [darwin]
|
||||||
|
|
||||||
|
lightningcss-freebsd-x64@1.30.2:
|
||||||
|
resolution: {integrity: sha512-c2bH6xTrf4BDpK8MoGG4Bd6zAMZDAXS569UxCAGcA7IKbHNMlhGQ89eRmvpIUGfKWNVdbhSbkQaWhEoMGmGslA==}
|
||||||
|
engines: {node: '>= 12.0.0'}
|
||||||
|
cpu: [x64]
|
||||||
|
os: [freebsd]
|
||||||
|
|
||||||
|
lightningcss-linux-arm-gnueabihf@1.30.2:
|
||||||
|
resolution: {integrity: sha512-eVdpxh4wYcm0PofJIZVuYuLiqBIakQ9uFZmipf6LF/HRj5Bgm0eb3qL/mr1smyXIS1twwOxNWndd8z0E374hiA==}
|
||||||
|
engines: {node: '>= 12.0.0'}
|
||||||
|
cpu: [arm]
|
||||||
|
os: [linux]
|
||||||
|
|
||||||
|
lightningcss-linux-arm64-gnu@1.30.2:
|
||||||
|
resolution: {integrity: sha512-UK65WJAbwIJbiBFXpxrbTNArtfuznvxAJw4Q2ZGlU8kPeDIWEX1dg3rn2veBVUylA2Ezg89ktszWbaQnxD/e3A==}
|
||||||
|
engines: {node: '>= 12.0.0'}
|
||||||
|
cpu: [arm64]
|
||||||
|
os: [linux]
|
||||||
|
libc: [glibc]
|
||||||
|
|
||||||
|
lightningcss-linux-arm64-musl@1.30.2:
|
||||||
|
resolution: {integrity: sha512-5Vh9dGeblpTxWHpOx8iauV02popZDsCYMPIgiuw97OJ5uaDsL86cnqSFs5LZkG3ghHoX5isLgWzMs+eD1YzrnA==}
|
||||||
|
engines: {node: '>= 12.0.0'}
|
||||||
|
cpu: [arm64]
|
||||||
|
os: [linux]
|
||||||
|
libc: [musl]
|
||||||
|
|
||||||
|
lightningcss-linux-x64-gnu@1.30.2:
|
||||||
|
resolution: {integrity: sha512-Cfd46gdmj1vQ+lR6VRTTadNHu6ALuw2pKR9lYq4FnhvgBc4zWY1EtZcAc6EffShbb1MFrIPfLDXD6Xprbnni4w==}
|
||||||
|
engines: {node: '>= 12.0.0'}
|
||||||
|
cpu: [x64]
|
||||||
|
os: [linux]
|
||||||
|
libc: [glibc]
|
||||||
|
|
||||||
|
lightningcss-linux-x64-musl@1.30.2:
|
||||||
|
resolution: {integrity: sha512-XJaLUUFXb6/QG2lGIW6aIk6jKdtjtcffUT0NKvIqhSBY3hh9Ch+1LCeH80dR9q9LBjG3ewbDjnumefsLsP6aiA==}
|
||||||
|
engines: {node: '>= 12.0.0'}
|
||||||
|
cpu: [x64]
|
||||||
|
os: [linux]
|
||||||
|
libc: [musl]
|
||||||
|
|
||||||
|
lightningcss-win32-arm64-msvc@1.30.2:
|
||||||
|
resolution: {integrity: sha512-FZn+vaj7zLv//D/192WFFVA0RgHawIcHqLX9xuWiQt7P0PtdFEVaxgF9rjM/IRYHQXNnk61/H/gb2Ei+kUQ4xQ==}
|
||||||
|
engines: {node: '>= 12.0.0'}
|
||||||
|
cpu: [arm64]
|
||||||
|
os: [win32]
|
||||||
|
|
||||||
|
lightningcss-win32-x64-msvc@1.30.2:
|
||||||
|
resolution: {integrity: sha512-5g1yc73p+iAkid5phb4oVFMB45417DkRevRbt/El/gKXJk4jid+vPFF/AXbxn05Aky8PapwzZrdJShv5C0avjw==}
|
||||||
|
engines: {node: '>= 12.0.0'}
|
||||||
|
cpu: [x64]
|
||||||
|
os: [win32]
|
||||||
|
|
||||||
|
lightningcss@1.30.2:
|
||||||
|
resolution: {integrity: sha512-utfs7Pr5uJyyvDETitgsaqSyjCb2qNRAtuqUeWIAKztsOYdcACf2KtARYXg2pSvhkt+9NfoaNY7fxjl6nuMjIQ==}
|
||||||
|
engines: {node: '>= 12.0.0'}
|
||||||
|
|
||||||
|
magic-string@0.30.21:
|
||||||
|
resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==}
|
||||||
|
|
||||||
|
micromatch@4.0.8:
|
||||||
|
resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==}
|
||||||
|
engines: {node: '>=8.6'}
|
||||||
|
|
||||||
|
mri@1.2.0:
|
||||||
|
resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==}
|
||||||
|
engines: {node: '>=4'}
|
||||||
|
|
||||||
|
node-addon-api@7.1.1:
|
||||||
|
resolution: {integrity: sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==}
|
||||||
|
|
||||||
|
picocolors@1.1.1:
|
||||||
|
resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==}
|
||||||
|
|
||||||
|
picomatch@2.3.1:
|
||||||
|
resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==}
|
||||||
|
engines: {node: '>=8.6'}
|
||||||
|
|
||||||
|
source-map-js@1.2.1:
|
||||||
|
resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==}
|
||||||
|
engines: {node: '>=0.10.0'}
|
||||||
|
|
||||||
|
tailwindcss@4.1.18:
|
||||||
|
resolution: {integrity: sha512-4+Z+0yiYyEtUVCScyfHCxOYP06L5Ne+JiHhY2IjR2KWMIWhJOYZKLSGZaP5HkZ8+bY0cxfzwDE5uOmzFXyIwxw==}
|
||||||
|
|
||||||
|
tapable@2.3.0:
|
||||||
|
resolution: {integrity: sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==}
|
||||||
|
engines: {node: '>=6'}
|
||||||
|
|
||||||
|
to-regex-range@5.0.1:
|
||||||
|
resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==}
|
||||||
|
engines: {node: '>=8.0'}
|
||||||
|
|
||||||
|
snapshots:
|
||||||
|
|
||||||
|
'@jridgewell/gen-mapping@0.3.13':
|
||||||
|
dependencies:
|
||||||
|
'@jridgewell/sourcemap-codec': 1.5.5
|
||||||
|
'@jridgewell/trace-mapping': 0.3.31
|
||||||
|
|
||||||
|
'@jridgewell/remapping@2.3.5':
|
||||||
|
dependencies:
|
||||||
|
'@jridgewell/gen-mapping': 0.3.13
|
||||||
|
'@jridgewell/trace-mapping': 0.3.31
|
||||||
|
|
||||||
|
'@jridgewell/resolve-uri@3.1.2': {}
|
||||||
|
|
||||||
|
'@jridgewell/sourcemap-codec@1.5.5': {}
|
||||||
|
|
||||||
|
'@jridgewell/trace-mapping@0.3.31':
|
||||||
|
dependencies:
|
||||||
|
'@jridgewell/resolve-uri': 3.1.2
|
||||||
|
'@jridgewell/sourcemap-codec': 1.5.5
|
||||||
|
|
||||||
|
'@parcel/watcher-android-arm64@2.5.1':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@parcel/watcher-darwin-arm64@2.5.1':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@parcel/watcher-darwin-x64@2.5.1':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@parcel/watcher-freebsd-x64@2.5.1':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@parcel/watcher-linux-arm-glibc@2.5.1':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@parcel/watcher-linux-arm-musl@2.5.1':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@parcel/watcher-linux-arm64-glibc@2.5.1':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@parcel/watcher-linux-arm64-musl@2.5.1':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@parcel/watcher-linux-x64-glibc@2.5.1':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@parcel/watcher-linux-x64-musl@2.5.1':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@parcel/watcher-win32-arm64@2.5.1':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@parcel/watcher-win32-ia32@2.5.1':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@parcel/watcher-win32-x64@2.5.1':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@parcel/watcher@2.5.1':
|
||||||
|
dependencies:
|
||||||
|
detect-libc: 1.0.3
|
||||||
|
is-glob: 4.0.3
|
||||||
|
micromatch: 4.0.8
|
||||||
|
node-addon-api: 7.1.1
|
||||||
|
optionalDependencies:
|
||||||
|
'@parcel/watcher-android-arm64': 2.5.1
|
||||||
|
'@parcel/watcher-darwin-arm64': 2.5.1
|
||||||
|
'@parcel/watcher-darwin-x64': 2.5.1
|
||||||
|
'@parcel/watcher-freebsd-x64': 2.5.1
|
||||||
|
'@parcel/watcher-linux-arm-glibc': 2.5.1
|
||||||
|
'@parcel/watcher-linux-arm-musl': 2.5.1
|
||||||
|
'@parcel/watcher-linux-arm64-glibc': 2.5.1
|
||||||
|
'@parcel/watcher-linux-arm64-musl': 2.5.1
|
||||||
|
'@parcel/watcher-linux-x64-glibc': 2.5.1
|
||||||
|
'@parcel/watcher-linux-x64-musl': 2.5.1
|
||||||
|
'@parcel/watcher-win32-arm64': 2.5.1
|
||||||
|
'@parcel/watcher-win32-ia32': 2.5.1
|
||||||
|
'@parcel/watcher-win32-x64': 2.5.1
|
||||||
|
|
||||||
|
'@tailwindcss/cli@4.1.18':
|
||||||
|
dependencies:
|
||||||
|
'@parcel/watcher': 2.5.1
|
||||||
|
'@tailwindcss/node': 4.1.18
|
||||||
|
'@tailwindcss/oxide': 4.1.18
|
||||||
|
enhanced-resolve: 5.18.4
|
||||||
|
mri: 1.2.0
|
||||||
|
picocolors: 1.1.1
|
||||||
|
tailwindcss: 4.1.18
|
||||||
|
|
||||||
|
'@tailwindcss/node@4.1.18':
|
||||||
|
dependencies:
|
||||||
|
'@jridgewell/remapping': 2.3.5
|
||||||
|
enhanced-resolve: 5.18.4
|
||||||
|
jiti: 2.6.1
|
||||||
|
lightningcss: 1.30.2
|
||||||
|
magic-string: 0.30.21
|
||||||
|
source-map-js: 1.2.1
|
||||||
|
tailwindcss: 4.1.18
|
||||||
|
|
||||||
|
'@tailwindcss/oxide-android-arm64@4.1.18':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@tailwindcss/oxide-darwin-arm64@4.1.18':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@tailwindcss/oxide-darwin-x64@4.1.18':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@tailwindcss/oxide-freebsd-x64@4.1.18':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@tailwindcss/oxide-linux-arm-gnueabihf@4.1.18':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@tailwindcss/oxide-linux-arm64-gnu@4.1.18':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@tailwindcss/oxide-linux-arm64-musl@4.1.18':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@tailwindcss/oxide-linux-x64-gnu@4.1.18':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@tailwindcss/oxide-linux-x64-musl@4.1.18':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@tailwindcss/oxide-wasm32-wasi@4.1.18':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@tailwindcss/oxide-win32-arm64-msvc@4.1.18':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@tailwindcss/oxide-win32-x64-msvc@4.1.18':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@tailwindcss/oxide@4.1.18':
|
||||||
|
optionalDependencies:
|
||||||
|
'@tailwindcss/oxide-android-arm64': 4.1.18
|
||||||
|
'@tailwindcss/oxide-darwin-arm64': 4.1.18
|
||||||
|
'@tailwindcss/oxide-darwin-x64': 4.1.18
|
||||||
|
'@tailwindcss/oxide-freebsd-x64': 4.1.18
|
||||||
|
'@tailwindcss/oxide-linux-arm-gnueabihf': 4.1.18
|
||||||
|
'@tailwindcss/oxide-linux-arm64-gnu': 4.1.18
|
||||||
|
'@tailwindcss/oxide-linux-arm64-musl': 4.1.18
|
||||||
|
'@tailwindcss/oxide-linux-x64-gnu': 4.1.18
|
||||||
|
'@tailwindcss/oxide-linux-x64-musl': 4.1.18
|
||||||
|
'@tailwindcss/oxide-wasm32-wasi': 4.1.18
|
||||||
|
'@tailwindcss/oxide-win32-arm64-msvc': 4.1.18
|
||||||
|
'@tailwindcss/oxide-win32-x64-msvc': 4.1.18
|
||||||
|
|
||||||
|
braces@3.0.3:
|
||||||
|
dependencies:
|
||||||
|
fill-range: 7.1.1
|
||||||
|
|
||||||
|
detect-libc@1.0.3: {}
|
||||||
|
|
||||||
|
detect-libc@2.1.2: {}
|
||||||
|
|
||||||
|
enhanced-resolve@5.18.4:
|
||||||
|
dependencies:
|
||||||
|
graceful-fs: 4.2.11
|
||||||
|
tapable: 2.3.0
|
||||||
|
|
||||||
|
fill-range@7.1.1:
|
||||||
|
dependencies:
|
||||||
|
to-regex-range: 5.0.1
|
||||||
|
|
||||||
|
graceful-fs@4.2.11: {}
|
||||||
|
|
||||||
|
is-extglob@2.1.1: {}
|
||||||
|
|
||||||
|
is-glob@4.0.3:
|
||||||
|
dependencies:
|
||||||
|
is-extglob: 2.1.1
|
||||||
|
|
||||||
|
is-number@7.0.0: {}
|
||||||
|
|
||||||
|
jiti@2.6.1: {}
|
||||||
|
|
||||||
|
lightningcss-android-arm64@1.30.2:
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
lightningcss-darwin-arm64@1.30.2:
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
lightningcss-darwin-x64@1.30.2:
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
lightningcss-freebsd-x64@1.30.2:
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
lightningcss-linux-arm-gnueabihf@1.30.2:
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
lightningcss-linux-arm64-gnu@1.30.2:
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
lightningcss-linux-arm64-musl@1.30.2:
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
lightningcss-linux-x64-gnu@1.30.2:
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
lightningcss-linux-x64-musl@1.30.2:
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
lightningcss-win32-arm64-msvc@1.30.2:
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
lightningcss-win32-x64-msvc@1.30.2:
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
lightningcss@1.30.2:
|
||||||
|
dependencies:
|
||||||
|
detect-libc: 2.1.2
|
||||||
|
optionalDependencies:
|
||||||
|
lightningcss-android-arm64: 1.30.2
|
||||||
|
lightningcss-darwin-arm64: 1.30.2
|
||||||
|
lightningcss-darwin-x64: 1.30.2
|
||||||
|
lightningcss-freebsd-x64: 1.30.2
|
||||||
|
lightningcss-linux-arm-gnueabihf: 1.30.2
|
||||||
|
lightningcss-linux-arm64-gnu: 1.30.2
|
||||||
|
lightningcss-linux-arm64-musl: 1.30.2
|
||||||
|
lightningcss-linux-x64-gnu: 1.30.2
|
||||||
|
lightningcss-linux-x64-musl: 1.30.2
|
||||||
|
lightningcss-win32-arm64-msvc: 1.30.2
|
||||||
|
lightningcss-win32-x64-msvc: 1.30.2
|
||||||
|
|
||||||
|
magic-string@0.30.21:
|
||||||
|
dependencies:
|
||||||
|
'@jridgewell/sourcemap-codec': 1.5.5
|
||||||
|
|
||||||
|
micromatch@4.0.8:
|
||||||
|
dependencies:
|
||||||
|
braces: 3.0.3
|
||||||
|
picomatch: 2.3.1
|
||||||
|
|
||||||
|
mri@1.2.0: {}
|
||||||
|
|
||||||
|
node-addon-api@7.1.1: {}
|
||||||
|
|
||||||
|
picocolors@1.1.1: {}
|
||||||
|
|
||||||
|
picomatch@2.3.1: {}
|
||||||
|
|
||||||
|
source-map-js@1.2.1: {}
|
||||||
|
|
||||||
|
tailwindcss@4.1.18: {}
|
||||||
|
|
||||||
|
tapable@2.3.0: {}
|
||||||
|
|
||||||
|
to-regex-range@5.0.1:
|
||||||
|
dependencies:
|
||||||
|
is-number: 7.0.0
|
||||||
38
samples/HeatMap/wwwroot/app.css
Normal file
38
samples/HeatMap/wwwroot/app.css
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
h1:focus {
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.valid.modified:not([type=checkbox]) {
|
||||||
|
outline: 1px solid #26b050;
|
||||||
|
}
|
||||||
|
|
||||||
|
.invalid {
|
||||||
|
outline: 1px solid #e50000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.validation-message {
|
||||||
|
color: #e50000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.blazor-error-boundary {
|
||||||
|
background: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTYiIGhlaWdodD0iNDkiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIG92ZXJmbG93PSJoaWRkZW4iPjxkZWZzPjxjbGlwUGF0aCBpZD0iY2xpcDAiPjxyZWN0IHg9IjIzNSIgeT0iNTEiIHdpZHRoPSI1NiIgaGVpZ2h0PSI0OSIvPjwvY2xpcFBhdGg+PC9kZWZzPjxnIGNsaXAtcGF0aD0idXJsKCNjbGlwMCkiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0yMzUgLTUxKSI+PHBhdGggZD0iTTI2My41MDYgNTFDMjY0LjcxNyA1MSAyNjUuODEzIDUxLjQ4MzcgMjY2LjYwNiA1Mi4yNjU4TDI2Ny4wNTIgNTIuNzk4NyAyNjcuNTM5IDUzLjYyODMgMjkwLjE4NSA5Mi4xODMxIDI5MC41NDUgOTIuNzk1IDI5MC42NTYgOTIuOTk2QzI5MC44NzcgOTMuNTEzIDI5MSA5NC4wODE1IDI5MSA5NC42NzgyIDI5MSA5Ny4wNjUxIDI4OS4wMzggOTkgMjg2LjYxNyA5OUwyNDAuMzgzIDk5QzIzNy45NjMgOTkgMjM2IDk3LjA2NTEgMjM2IDk0LjY3ODIgMjM2IDk0LjM3OTkgMjM2LjAzMSA5NC4wODg2IDIzNi4wODkgOTMuODA3MkwyMzYuMzM4IDkzLjAxNjIgMjM2Ljg1OCA5Mi4xMzE0IDI1OS40NzMgNTMuNjI5NCAyNTkuOTYxIDUyLjc5ODUgMjYwLjQwNyA1Mi4yNjU4QzI2MS4yIDUxLjQ4MzcgMjYyLjI5NiA1MSAyNjMuNTA2IDUxWk0yNjMuNTg2IDY2LjAxODNDMjYwLjczNyA2Ni4wMTgzIDI1OS4zMTMgNjcuMTI0NSAyNTkuMzEzIDY5LjMzNyAyNTkuMzEzIDY5LjYxMDIgMjU5LjMzMiA2OS44NjA4IDI1OS4zNzEgNzAuMDg4N0wyNjEuNzk1IDg0LjAxNjEgMjY1LjM4IDg0LjAxNjEgMjY3LjgyMSA2OS43NDc1QzI2Ny44NiA2OS43MzA5IDI2Ny44NzkgNjkuNTg3NyAyNjcuODc5IDY5LjMxNzkgMjY3Ljg3OSA2Ny4xMTgyIDI2Ni40NDggNjYuMDE4MyAyNjMuNTg2IDY2LjAxODNaTTI2My41NzYgODYuMDU0N0MyNjEuMDQ5IDg2LjA1NDcgMjU5Ljc4NiA4Ny4zMDA1IDI1OS43ODYgODkuNzkyMSAyNTkuNzg2IDkyLjI4MzcgMjYxLjA0OSA5My41Mjk1IDI2My41NzYgOTMuNTI5NSAyNjYuMTE2IDkzLjUyOTUgMjY3LjM4NyA5Mi4yODM3IDI2Ny4zODcgODkuNzkyMSAyNjcuMzg3IDg3LjMwMDUgMjY2LjExNiA4Ni4wNTQ3IDI2My41NzYgODYuMDU0N1oiIGZpbGw9IiNGRkU1MDAiIGZpbGwtcnVsZT0iZXZlbm9kZCIvPjwvZz48L3N2Zz4=) no-repeat 1rem/1.8rem, #b32121;
|
||||||
|
padding: 1rem 1rem 1rem 3.7rem;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.blazor-error-boundary::after {
|
||||||
|
content: "An error has occurred."
|
||||||
|
}
|
||||||
|
|
||||||
|
.darker-border-checkbox.form-check-input {
|
||||||
|
border-color: #929292;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-floating > .form-control-plaintext::placeholder, .form-floating > .form-control::placeholder {
|
||||||
|
color: var(--bs-secondary-color);
|
||||||
|
text-align: end;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-floating > .form-control-plaintext:focus::placeholder, .form-floating > .form-control:focus::placeholder {
|
||||||
|
text-align: start;
|
||||||
|
}
|
||||||
1
samples/HeatMap/wwwroot/tailwind.css
Normal file
1
samples/HeatMap/wwwroot/tailwind.css
Normal file
@@ -0,0 +1 @@
|
|||||||
|
@import "tailwindcss";
|
||||||
@@ -6,7 +6,6 @@
|
|||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<SupportedPlatform Include="browser" />
|
<SupportedPlatform Include="browser" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|||||||
11
src/BlazorSvgComponents/Circle.razor
Normal file
11
src/BlazorSvgComponents/Circle.razor
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
@inherits SvgComponentBase
|
||||||
|
|
||||||
|
<circle cx="@CenterX" cy="@CenterY" r="@Radius" @attributes="@CommonAttributes"/>
|
||||||
|
|
||||||
|
@code {
|
||||||
|
[Parameter] public int CenterX { get; set; }
|
||||||
|
|
||||||
|
[Parameter] public int CenterY { get; set; }
|
||||||
|
|
||||||
|
[Parameter] public int Radius { get; set; }
|
||||||
|
}
|
||||||
13
src/BlazorSvgComponents/Ellipse.razor
Normal file
13
src/BlazorSvgComponents/Ellipse.razor
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
@inherits SvgComponentBase
|
||||||
|
|
||||||
|
<ellipse rx="@EllipseX" ry="@EllipseY" cx="@CenterX" cy="@CenterY" @attributes="@CommonAttributes"/>
|
||||||
|
|
||||||
|
@code {
|
||||||
|
[Parameter] public int CenterX { get; set; }
|
||||||
|
|
||||||
|
[Parameter] public int CenterY { get; set; }
|
||||||
|
|
||||||
|
[Parameter] public int EllipseX { get; set; }
|
||||||
|
|
||||||
|
[Parameter] public int EllipseY { get; set; }
|
||||||
|
}
|
||||||
10
src/BlazorSvgComponents/Line.razor
Normal file
10
src/BlazorSvgComponents/Line.razor
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
@using BlazorSvgComponents.Models
|
||||||
|
@inherits SvgComponentBase
|
||||||
|
|
||||||
|
<line x1="@(Start.X)" y1="@(Start.Y)" x2="@(End.X)" y2="@(End.Y)" @attributes="@CommonAttributes"/>
|
||||||
|
|
||||||
|
@code {
|
||||||
|
[Parameter] public SvgPoint Start { get; set; }
|
||||||
|
|
||||||
|
[Parameter] public SvgPoint End { get; set; }
|
||||||
|
}
|
||||||
6
src/BlazorSvgComponents/Models/SvgPoint.cs
Normal file
6
src/BlazorSvgComponents/Models/SvgPoint.cs
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
namespace BlazorSvgComponents.Models;
|
||||||
|
|
||||||
|
public readonly record struct SvgPoint(int X, int Y)
|
||||||
|
{
|
||||||
|
public override string ToString() => $"{X},{Y}";
|
||||||
|
}
|
||||||
73
src/BlazorSvgComponents/Models/SvgTransform.cs
Normal file
73
src/BlazorSvgComponents/Models/SvgTransform.cs
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace BlazorSvgComponents.Models;
|
||||||
|
|
||||||
|
public readonly struct SvgTransform
|
||||||
|
{
|
||||||
|
public string Transform { get; }
|
||||||
|
|
||||||
|
internal SvgTransform(string transform)
|
||||||
|
{
|
||||||
|
Transform = transform;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ToString() => Transform;
|
||||||
|
|
||||||
|
public static SvgTransformBuilder CreateBuilder() => new();
|
||||||
|
|
||||||
|
public static SvgTransform Empty => new(string.Empty);
|
||||||
|
}
|
||||||
|
|
||||||
|
public class SvgTransformBuilder
|
||||||
|
{
|
||||||
|
private readonly StringBuilder _builder = new();
|
||||||
|
|
||||||
|
public SvgTransformBuilder TransformMatrix(int a, int b, int c, int d, int e, int f)
|
||||||
|
{
|
||||||
|
_builder.Append("matrix(")
|
||||||
|
.Append(a).Append(',')
|
||||||
|
.Append(b).Append(',')
|
||||||
|
.Append(c).Append(',')
|
||||||
|
.Append(d).Append(',')
|
||||||
|
.Append(e).Append(',')
|
||||||
|
.Append(f).Append(')')
|
||||||
|
.Append(' ');
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SvgTransformBuilder Translate(int x, int y = 0)
|
||||||
|
{
|
||||||
|
_builder.Append($"translate({x} {y}) ");
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SvgTransformBuilder Scale(int x, int y)
|
||||||
|
{
|
||||||
|
_builder.Append($"scale({x} {y}) ");
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SvgTransformBuilder Rotate(int a, int x = 0, int y = 0)
|
||||||
|
{
|
||||||
|
_builder.Append($"rotate({a} {x} {y}) ");
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SvgTransformBuilder SkewX(int a)
|
||||||
|
{
|
||||||
|
_builder.Append($"skewX({a}) ");
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SvgTransformBuilder SkewY(int a)
|
||||||
|
{
|
||||||
|
_builder.Append($"skewY({a}) ");
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SvgTransform Build()
|
||||||
|
{
|
||||||
|
return new SvgTransform(_builder.ToString().Trim());
|
||||||
|
}
|
||||||
|
}
|
||||||
8
src/BlazorSvgComponents/Models/SvgViewBox.cs
Normal file
8
src/BlazorSvgComponents/Models/SvgViewBox.cs
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
namespace BlazorSvgComponents.Models;
|
||||||
|
|
||||||
|
public readonly record struct SvgViewBox(int StartX, int StartY, int EndX, int EndY)
|
||||||
|
{
|
||||||
|
public override string ToString() => $"{StartX} {StartY} {EndX} {EndY}";
|
||||||
|
|
||||||
|
public bool IsEmpty => StartX == 0 && StartY == 0 && EndX == 0 && EndY == 0;
|
||||||
|
}
|
||||||
13
src/BlazorSvgComponents/Polygon.razor
Normal file
13
src/BlazorSvgComponents/Polygon.razor
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
@using System.Text
|
||||||
|
@using BlazorSvgComponents.Models
|
||||||
|
@inherits SvgComponentBase
|
||||||
|
|
||||||
|
<polygon points="@PointAttribute" @attributes="@CommonAttributes"/>
|
||||||
|
|
||||||
|
@code {
|
||||||
|
[Parameter] public List<SvgPoint> Points { get; set; } = [];
|
||||||
|
|
||||||
|
private string PointAttribute =>
|
||||||
|
Points.Aggregate(new StringBuilder(), (builder, p) => builder.Append(' ').Append(p)).ToString().Trim();
|
||||||
|
|
||||||
|
}
|
||||||
13
src/BlazorSvgComponents/Polyline.razor
Normal file
13
src/BlazorSvgComponents/Polyline.razor
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
@using System.Text
|
||||||
|
@using BlazorSvgComponents.Models
|
||||||
|
@inherits SvgComponentBase
|
||||||
|
|
||||||
|
<polyline points="@PointAttribute" @attributes="@CommonAttributes"/>
|
||||||
|
|
||||||
|
@code {
|
||||||
|
[Parameter] public List<SvgPoint> Points { get; set; } = [];
|
||||||
|
|
||||||
|
private string PointAttribute =>
|
||||||
|
Points.Aggregate(new StringBuilder(), (builder, p) => builder.Append(' ').Append(p)).ToString().Trim();
|
||||||
|
|
||||||
|
}
|
||||||
17
src/BlazorSvgComponents/Rectangle.razor
Normal file
17
src/BlazorSvgComponents/Rectangle.razor
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
@inherits SvgComponentBase
|
||||||
|
|
||||||
|
<rect x="@X" y="@Y" width="@Width" height="@Height" rx="@RadiusX" ry="@RadiusY" @attributes="@CommonAttributes"/>
|
||||||
|
|
||||||
|
@code {
|
||||||
|
[Parameter] public int X { get; set; }
|
||||||
|
|
||||||
|
[Parameter] public int Y { get; set; }
|
||||||
|
|
||||||
|
[Parameter] public int Width { get; set; }
|
||||||
|
|
||||||
|
[Parameter] public int Height { get; set; }
|
||||||
|
|
||||||
|
[Parameter] public int RadiusX { get; set; }
|
||||||
|
|
||||||
|
[Parameter] public int RadiusY { get; set; }
|
||||||
|
}
|
||||||
68
src/BlazorSvgComponents/SvgComponentBase.cs
Normal file
68
src/BlazorSvgComponents/SvgComponentBase.cs
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
using System.Collections.ObjectModel;
|
||||||
|
using System.Globalization;
|
||||||
|
using Microsoft.AspNetCore.Components;
|
||||||
|
using BlazorSvgComponents.Models;
|
||||||
|
|
||||||
|
namespace BlazorSvgComponents;
|
||||||
|
|
||||||
|
public enum StrokeLineCapKind
|
||||||
|
{
|
||||||
|
Butt,
|
||||||
|
Round,
|
||||||
|
Square
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum StrokeLineJoinKind
|
||||||
|
{
|
||||||
|
Miter,
|
||||||
|
Round,
|
||||||
|
Bevel
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract class SvgComponentBase : ComponentBase
|
||||||
|
{
|
||||||
|
[Parameter] public string Fill { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
[Parameter] public string Stroke { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
[Parameter] public int StrokeWidth { get; set; }
|
||||||
|
|
||||||
|
[Parameter] public float Opacity { get; set; } = 1f;
|
||||||
|
|
||||||
|
[Parameter] public float FillOpacity { get; set; } = 1f;
|
||||||
|
|
||||||
|
[Parameter] public float StrokeOpacity { get; set; } = 1f;
|
||||||
|
|
||||||
|
[Parameter] public StrokeLineCapKind StrokeLineCap { get; set; }
|
||||||
|
|
||||||
|
[Parameter] public StrokeLineJoinKind StrokeLineJoin { get; set; }
|
||||||
|
|
||||||
|
[Parameter] public string Id { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
[Parameter] public string Class { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
[Parameter] public string Style { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
[Parameter] public string Title { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
[Parameter] public SvgTransform Transform { get; set; } = SvgTransform.Empty;
|
||||||
|
|
||||||
|
protected IReadOnlyDictionary<string, object> CommonAttributes => new ReadOnlyDictionary<string, object>(
|
||||||
|
new Dictionary<string, string>
|
||||||
|
{
|
||||||
|
{ "fill", Fill },
|
||||||
|
{ "stroke", Stroke },
|
||||||
|
{ "stroke-width", StrokeWidth.ToString() },
|
||||||
|
{ "opacity", Opacity.ToString(CultureInfo.InvariantCulture) },
|
||||||
|
{ "fill-opacity", FillOpacity.ToString(CultureInfo.InvariantCulture) },
|
||||||
|
{ "stroke-opacity", StrokeOpacity.ToString(CultureInfo.InvariantCulture) },
|
||||||
|
{ "stroke-linecap", StrokeLineCap.ToString() },
|
||||||
|
{ "stroke-linejoin", StrokeLineJoin.ToString() },
|
||||||
|
{ "id", Id },
|
||||||
|
{ "class", Class },
|
||||||
|
{ "style", Style },
|
||||||
|
{ "title", Title },
|
||||||
|
{ "transform", Transform.ToString() },
|
||||||
|
}.Where(pair => !string.IsNullOrEmpty(pair.Value))
|
||||||
|
.Select(pair => new KeyValuePair<string, object>(pair.Key, pair.Value)).ToDictionary());
|
||||||
|
}
|
||||||
26
src/BlazorSvgComponents/SvgContainer.razor
Normal file
26
src/BlazorSvgComponents/SvgContainer.razor
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
@using BlazorSvgComponents.Models
|
||||||
|
@if (ViewBox.IsEmpty)
|
||||||
|
{
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="@Width" height="@Height">
|
||||||
|
@ChildContent
|
||||||
|
</svg>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="@Width" height="@Height" viewBox="@ViewBox">
|
||||||
|
@ChildContent
|
||||||
|
</svg>
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@code
|
||||||
|
{
|
||||||
|
[Parameter] public RenderFragment? ChildContent { get; set; }
|
||||||
|
|
||||||
|
[Parameter] public string Width { get; set; } = "300";
|
||||||
|
|
||||||
|
|
||||||
|
[Parameter] public string Height { get; set; } = "150";
|
||||||
|
|
||||||
|
[Parameter] public SvgViewBox ViewBox { get; set; }
|
||||||
|
}
|
||||||
7
src/BlazorSvgComponents/SvgGroup.razor
Normal file
7
src/BlazorSvgComponents/SvgGroup.razor
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
@inherits SvgComponentBase
|
||||||
|
|
||||||
|
<g @attributes="@CommonAttributes">@ChildContent</g>
|
||||||
|
|
||||||
|
@code {
|
||||||
|
[Parameter] public RenderFragment? ChildContent { get; set; }
|
||||||
|
}
|
||||||
14
src/BlazorSvgComponents/SvgText.razor
Normal file
14
src/BlazorSvgComponents/SvgText.razor
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
@inherits SvgComponentBase
|
||||||
|
|
||||||
|
<text x="@X" y="@Y" @attributes="@CommonAttributes">
|
||||||
|
@Content
|
||||||
|
</text>
|
||||||
|
|
||||||
|
@code {
|
||||||
|
[Parameter] public string Content { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
[Parameter] public int X { get; set; }
|
||||||
|
|
||||||
|
[Parameter] public int Y { get; set; }
|
||||||
|
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user