features/rewrite/modal1 #10

Merged
koma merged 18 commits from features/rewrite/modal1 into features/rewrite/main 2 years ago

@ -15,4 +15,11 @@
<ProjectReference Include="..\Connected.Components.Showcase\Connected.Components.Showcase.csproj" /> <ProjectReference Include="..\Connected.Components.Showcase\Connected.Components.Showcase.csproj" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<Watch Include="..\..\src\**" />
<Watch Remove="..\..\src\**\obj\**" />
<Watch Remove="..\..\src\**\bin\**" />
</ItemGroup>
</Project> </Project>

@ -1,5 +1,7 @@
@inherits LayoutComponentBase @inherits LayoutComponentBase
<ModalDialog/>
<main> <main>
@Body @Body
</main> </main>

@ -1,83 +1,123 @@
@page "/demo" @page "/demo"
<body> <body class="">
<div class="document-container d-flex"> <div class="document-container d-flex">
<aside> <aside>
<div class="sidebar @sidebarClosed"> <div class="sidebar @sidebarClosed bottombar">
<div class="profile-details"> <div class="profile-details">
<div class="avatar"> <div class="avatar">
<img src="http://sys-app/core/app/sys/avatar/1733c1cf-a588-4a45-9773-dcd320bee57f/1" title="Janko Jordan"> <img src="http://sys-app/core/app/sys/avatar/1733c1cf-a588-4a45-9773-dcd320bee57f/1" title="Janko Jordan">
</div> </div>
<div class="name-job"> <div class="profile-description">
<div class="profile-name">Janko Jordan</div> <div class="profile-name">Janko Jordan</div>
<div class="profile-job">Web Designer</div> <div class="profile-job">Web Designer</div>
</div> </div>
<i class='bx bx-log-out'></i> <i class='bx bx-log-out'></i>
</div> </div>
<ul class="nav-links"> <nav>
<li class="@NavClosed"> <ul class="navbar mt-sm-5 pt-sm-5">
<div @onclick="ToggleNav" class="iocn-link"> <li class="navbar-item fab">
<a href="#"> <a href="#">
<i class='bx bx-collection' @onclick="ToggleNav"></i> <i class='bx bx-pencil'></i>
<span class="link_name">Proizvodni nalogi</span> <span class="navbar-link">New document</span>
</a> </a>
<i class='bx bxs-chevron-down arrow'></i> <span class="navbar-tooltip">
</div> New document
<ul class="sub-menu"> </span>
<li><a class="link_name" href="#">Proizvodni nalogi</a></li>
<li><a href="#">Osnutek</a></li>
<li><a href="#">V obdelavi</a></li>
<li><a href="#">Aktiven</a></li>
<li><a href="#">Zaprt</a></li>
</ul>
</li> </li>
<li>
<li class="navbar-item">
<a href="#"> <a href="#">
<i class='bx bx-grid-alt'></i> <i class='bx bx-home'></i>
<span class="link_name">Izvedba</span> <span class="navbar-link">Main navbar link 1</span>
<span class="navbar-link navbar-link-detail">
<div class="badge-label">
22
</div>
</span>
</a> </a>
<ul class="sub-menu blank"> <span class="navbar-tooltip">
<li><a class="link_name" href="#">Izvedba</a></li> Main navbar link 1
</ul> </span>
</li> </li>
</ul>
<li class="navbar-item">
<a href="#">
<i class='bx bx-shape-square'></i>
<span class="navbar-link">Main navbar link 2</span>
<span class="navbar-link navbar-link-detail">
<div class="badge-label">
22
</div> </div>
</aside> </span>
</a>
<span class="navbar-tooltip">
Main navbar link 2
</span>
</li>
<li class="navbar-item">
<a href="#">
<i class='bx bx-message-square-dots'></i>
<span class="navbar-link">Main navbar link 3</span>
<span class="navbar-link navbar-link-detail">
<div class="badge-label">
22
</div>
</span>
</a>
<span class="navbar-tooltip">
Main navbar link 3
</span>
</li>
<section class="main @sidebarClosed"> <li class="navbar-item">
<a href="#">
<i class='bx bx-customize'></i>
<span class="navbar-link">Main navbar link 4</span>
<span class="navbar-link navbar-link-detail">
<div class="badge-label">
22
</div>
</span>
</a>
<span class="navbar-tooltip">
Main navbar link 4
</span>
</li>
<div class="sidebar-divider"></div>
</ul>
</nav>
</div>
</aside>
<div class="color-picker-container">
<form class="color-picker" action="">
<fieldset>
<legend class="visually-hidden">Pick a color scheme</legend>
<label for="light" class="visually-hidden">Light</label> <main class="main @sidebarClosed @sidebarRightClosed">
<input type="radio" id="light" name="theme" checked>
<label for="pink" class="visually-hidden">Pink theme</label>
<input type="radio" id="pink" name="theme">
<label for="dark" class="visually-hidden">Dark theme</label>
<input type="radio" id="dark" name="theme">
</fieldset>
</form>
</div>
<div class=""> <div class="d-flex justify-space-between">
<div>
<i class='bx bx-menu' @onclick="ToggleSidebar"></i> <i class='bx bx-menu' @onclick="ToggleSidebar"></i>
@* <Glyph SVG="@Icons.Material.Rounded.Dangerous" /> *@
<span class="text">Open Sidebar</span> <span class="text">Open Sidebar</span>
</div>
<div>
<i class='bx bx-filter' @onclick="ToggleSidebarRight"></i>
<span class="text">Open Filters</span>
</div>
</div>
<section id="borders" class="mt-3 b-1 b-r-4 p-5"> <section id="borders" class="mt-3 b-1 b-r-4 p-5">
<h2>Borders</h2> <h2>Borders</h2>
<p>Use border utilities to quickly style the border, border color and border-radius of an element. <p>Use border utilities to quickly style the border, border color and border-radius of an element.
@ -238,7 +278,7 @@
Lorem Lorem
ipsum ipsum
dolor sit, amet consectetur dolor sit, amet consectetur
adipisicing adipis
elit. Alias praesentium quo est pariatur sed nobis maiores rem aperiam ut voluptas? elit. Alias praesentium quo est pariatur sed nobis maiores rem aperiam ut voluptas?
</p> </p>
</div> </div>
@ -457,15 +497,15 @@
<h4 class="text-core mt-5">Sizes</h4> <h4 class="text-core mt-5">Sizes</h4>
<div class=""> <div class="">
<button type="button" href="#" class="btn btn-sm btn-core">small button</button> <button type="button" href="#" class="btn btn-sm btn-core">small button</button>
<button type="button" href="#" class="btn btn-sm btn-light">small button</button> <button type="button" href="#" class="btn btn-sm btn-secondary">small button</button>
</div> </div>
<div class="mt-4 "> <div class="mt-4 ">
<button type="button" href="#" class="btn btn-lg btn-core">large button</button> <button type="button" href="#" class="btn btn-lg btn-core">large button</button>
<button type="button" href="#" class="btn btn-lg btn-light">large button</button> <button type="button" href="#" class="btn btn-lg btn-secondary">large button</button>
</div> </div>
<div class="mt-4 "> <div class="mt-4 ">
<button type="button" href="#" class="btn btn-block btn-core">full width button</button> <button type="button" href="#" class="btn btn-block btn-core">full width button</button>
<button type="button" href="#" class="mt-4 btn btn-block btn-light">full width <button type="button" href="#" class="mt-4 btn btn-block btn-secondary">full width
button</button> button</button>
</div> </div>
</div> </div>
@ -496,8 +536,30 @@
</p> </p>
<div> <div>
<div class="container"> <div class="grid grid-col-3 gap-3">
<div>
<label class="toggle-group" for="toggle-1">
<input class="toggle-input" id="toggle-1" name="toggle" type="checkbox" checked>
<div class="toggle-fill"></div>
<label for="toggle-1" class="toggle-label">Checked</label>
</label>
<label class="toggle-group" for="toggle-2">
<input class="toggle-input" id="toggle-2" name="toggle" type="checkbox">
<div class="toggle-fill"></div>
<label for="toggle-2" class="toggle-label">Unchecked</label>
</label>
<label class="toggle-group" for="toggle-3">
<input class="toggle-input" id="toggle-3" name="toggle" type="checkbox" disabled>
<div class="toggle-fill"></div>
<label for="toggle-3" class="toggle-label">Disabled</label>
</label>
</div>
@* <div>
<div class="checkbox-group"> <div class="checkbox-group">
<input id="checkbox-1" name="checkbox" type="checkbox" checked> <input id="checkbox-1" name="checkbox" type="checkbox" checked>
<label for="checkbox-1" class="checkbox-label">Checked</label> <label for="checkbox-1" class="checkbox-label">Checked</label>
@ -509,11 +571,36 @@
</div> </div>
<div class="checkbox-group"> <div class="checkbox-group">
<input id="checkbox-1" name="checkbox" type="checkbox" disabled> <input id="checkbox-3" name="checkbox" type="checkbox" disabled>
<label for="checkbox-1" class="checkbox-label">Checked disabled</label> <label for="checkbox-3" class="checkbox-label">Checked disabled</label>
</div> </div>
</div> *@
<div>
<label class="checkbox-group" for="checkbox-1">
<input class="checkbox-input" id="checkbox-1" name="checkbox" type="checkbox" checked>
<div class="checkbox-fill"></div>
<label for="checkbox-1" class="checkbox-label">Checked</label>
</label>
<label class="checkbox-group" for="checkbox-2">
<input class="checkbox-input" id="checkbox-2" name="checkbox" type="checkbox">
<div class="checkbox-fill"></div>
<label for="checkbox-2" class="checkbox-label">Unchecked</label>
</label>
<label class="checkbox-group" for="checkbox-3">
<input class="checkbox-input" id="checkbox-3" name="checkbox" type="checkbox" disabled>
<div class="checkbox-fill"></div>
<label for="checkbox-3" class="checkbox-label">Disabled</label>
</label>
</div>
@* <div>
<div class="radio-group"> <div class="radio-group">
<input id="radio-1" name="radio" type="radio" checked> <input id="radio-1" name="radio" type="radio" checked>
<label for="radio-1" class="radio-label">Checked</label> <label for="radio-1" class="radio-label">Checked</label>
@ -528,8 +615,31 @@
<input id="radio-3" name="radio" type="radio" disabled> <input id="radio-3" name="radio" type="radio" disabled>
<label for="radio-3" class="radio-label">Disabled</label> <label for="radio-3" class="radio-label">Disabled</label>
</div> </div>
</div> </div> *@
<div>
<label class="radio-group" for="radio-1">
<input class="radio-input" id="radio-1" name="radio" type="radio" checked>
<div class="radio-fill"></div>
<label for="radio-1" class="radio-label">Checked</label>
</label>
<label class="radio-group" for="radio-2">
<input class="radio-input" id="radio-2" name="radio" type="radio">
<div class="radio-fill"></div>
<label for="radio-2" class="radio-label">Unchecked</label>
</label>
<label class="radio-group" for="radio-3">
<input class="radio-input" id="radio-3" name="radio" type="radio" disabled>
<div class="radio-fill"></div>
<label for="radio-3" class="radio-label">Disabled</label>
</label>
</div>
</div>
</div> </div>
</section> </section>
@ -541,7 +651,7 @@
<form> <form>
<div class="d-flex flex-wrap gap-3"> <div class="grid grid-col-3 gap-3">
<div class="form-group error"> <div class="form-group error">
@ -646,6 +756,7 @@
<i class='bx bx-error-circle'></i> <i class='bx bx-error-circle'></i>
</span> </span>
</span> </span>
<div class="backdrop"></div>
<div class="drop-down"> <div class="drop-down">
<div class="dropdown-menu" aria-labelledby="dropdownMenuButton"> <div class="dropdown-menu" aria-labelledby="dropdownMenuButton">
<div class="dropdown-header">Header</div> <div class="dropdown-header">Header</div>
@ -678,11 +789,9 @@
</div> </div>
<div class="btn-box"> <div class="btn-box my-5">
<button type="button" href="#" class="btn btn-core " aria-pressed="true">active <button type="button" href="#" class="btn btn-core mr-2" aria-pressed="true">Accept</button>
button</button> <button type="button" href="#" class="btn btn-secondary" aria-pressed="true">Cancel</button>
<button type="button" href="#" class="btn btn-outline-core " aria-pressed="true">active
button</button>
</div> </div>
</form> </form>
@ -707,9 +816,360 @@
<div>12</div> <div>12</div>
</div> </div>
<div>
<hr class="mt-4 mb-4">
<h2 class="mb-2"> Data Grid</h2>
<p>Data grid DENSE + COLLAPSE + SELECT</p>
<div class="chip-icon float-left" @onclick="ToggleSidebarRight"><i class='bx bx-filter'></i></div>
<div class="horizontal-scroll-container">
<div class="chip-group">
<div class="chip-group-content">
<div class="chip-leading-icon"><i class='bx bx-user'></i></div>
<div class="chip-label">Chip label text</div>
<div class="chip-cta-icon"><i class='bx bx-x'></i></div>
</div>
</div>
<div class="chip-group">
<div class="chip-group-content">
<div class="chip-leading-icon"> <img class="img-fluid" src="https://source.unsplash.com/random?face" /> </div>
<div class="chip-label">Chip label text</div>
<div class="chip-cta-icon"><i class='bx bx-x'></i></div>
</div>
</div>
<div class="chip-group filter"> <!-- TO DO on chip-group filter toggle class active-->
<div class="chip-group-content">
<div class="chip-leading-icon"><i class='bx bx-check'></i></div>
<div class="chip-label">Chip label text</div>
<div class="chip-cta-icon"><i class='bx bx-x'></i></div>
</div>
</div>
<div class="chip-group filter active"> <!-- TO DO on chip-group filter toggle class active-->
<div class="chip-group-content">
<div class="chip-leading-icon"><i class='bx bx-check'></i></div>
<div class="chip-label">Chip label text</div>
<div class="chip-cta-icon"><i class='bx bx-x'></i></div>
</div>
</div> </div>
<div class="chip-group">
<div class="chip-group-content">
<div class="chip-leading-icon"><i class='bx bx-user'></i></div>
<div class="chip-label">
<select type="textarea" placeholder="Select">Se
</select>
<div class="drop-down">
<div class="dropdown-menu" aria-labelledby="dropdownMenuButton">
<div class="dropdown-header">Header</div>
<a class="dropdown-item" href="#">Action</a>
<a class="dropdown-item" href="#">Another action</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item" href="#">Something else here</a>
</div>
</div>
</div>
<div class="chip-cta-icon"><i class='bx bx-x'></i></div>
</div>
</div>
</div>
<div class="data-grid dense select collapse @NavClosed mt-5">
<!--dense select collapse-->
<div class="data-grid-row-content">
<!--active-->
<div class="data-grid-select">
@* <label class="checkbox-group m-0" for="checkbox-S11">
<input class="checkbox-input" id="checkbox-S11" name="checkbox" type="checkbox" checked>
<div class="checkbox-fill"></div>
</label> *@
<label class="toggle-group m-0" for="toggle-s11">
<input class="toggle-input" id="toggle-s11" name="toggle" type="checkbox">
<div class="toggle-fill"></div>
</label>
</div>
<div class="data-grid-container">
<div class="row">
<div class="col-12 col-md-4">
<div class="text-hc">Product 1</div>
<a class="text-link text-semibold" href="#">0023 001445669 1</a>
<div class="text-small">Product serial code</div>
</div>
<div class="col-12 col-md-4">
<label>Material code</label>
<div class="">Material 29</div>
</div>
<div class="col-12 col-md-4 text-md-right">
<label>Price</label>
<div class="text-semibold ">77,29</div>
</div>
</div>
<div class="row collapsed @NavClosed">
<div class="col-12 col-md-4 ">
<div class="text-small">
You have successfully published ticket You have successfully published ticket Partner network on desk Connected Partner network on desk Connected
</div>
</div>
</div>
</div>
<div style="font-size:1.75rem; margin-top:-.25rem" class="data-grid-collapse-cta" @onclick="ToggleNav">
<i class='bx bx-chevron-down'></i>
</div>
</div>
</div>
</div>
<section id="form-wizard" class="form-wizard mt-5">
<h3>Form wizard</h3>
<div class="form-outer">
<div class="form-step @NextSlide">
<div class="row">
<div class="col-12">Description for step 1</div>
@* <div class="col-12 col-md-6 ">
<div class="d-flex justify-flex-end gap-3">
<div class="dot active"></div>
<div class="dot"></div>
<div class="dot"></div>
<div class="dot"></div>
</div>
</div> *@
<div class="form-group col-12 col-md-6">
<input type="text" required="required" /><span class="highlight"></span><span class="bar"></span>
<label class="label-animated">Name</label>
<div class="input-helper-text">Some helping Text</div>
<div class="input-error-text">At least 6 characters required</div>
<span class="input-glyph-wraper">
<span class="input-glyph">
<span class="input-glyph button">
<i class='bx bx-x-circle'></i>
</span>
<span class="input-glyph error">
<i class='bx bx-error-circle'></i>
</span>
</span>
</span>
</div>
<div class="form-group col-12 col-md-6">
<input type="text" required="required" /><span class="highlight"></span><span class="bar"></span>
<label class="label-animated">Surname</label>
<div class="input-helper-text">Some helping Text</div>
<div class="input-error-text">At least 6 characters required</div>
<span class="input-glyph-wraper">
<span class="input-glyph">
<span class="input-glyph button">
<i class='bx bx-x-circle'></i>
</span>
<span class="input-glyph error">
<i class='bx bx-error-circle'></i>
</span>
</span>
</span>
</div>
</div>
</div>
<div class="form-step @NextSlide">
<div class="bg-info">2</div>
</div>
</div>
<div class="btn-box text-right my-5 d-flex justify-space-between">
<button type="button" href="#" class="btn btn-secondary" aria-pressed="true">Cancel</button>
<div>
<button type="button" @onclick="TogglePreviousSlide" class="btn btn-core mr-2" aria-pressed="true"><i class='bx bx-chevron-left'></i>Back</button>
<button type="button" @onclick="ToggleNextSlide" class="btn btn-core mr-2" aria-pressed="true">Next<i class='bx bx-chevron-right'></i></button>
</div>
</div>
<div class="dots d-flex justify-center gap-3">
<div class="dot completed"></div>
<div class="dot @NextSlide"></div>
<div class="dot"></div>
<div class="dot"></div>
</div>
</section> </section>
<section id="modal">
<!-- TO DO close modal on pres esc and when clicked outside the modal-->
<!-- TO DO when modal is open add class to body .scroll-disabled-->
<!-- Button trigger modal -->
<button type="button" class="btn btn-primary" @onclick="ToggleNav" data-bs-target="#staticBackdrop">
Launch backdrop modal
</button>
<!-- Modal -->
<div class="modal fade @NavClosed" tabindex="-1">
<div class="modal-dialog modal-dialog-scrollable modal-dialog-centered">
<div class="modal-content">
<div class="modal-header">
<h3 class="modal-title">Modal title</h3>
@* <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button> *@
</div>
<div class="modal-body">
lorem20
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" @onclick="ToggleNav">Close</button>
<button type="button" class="btn btn-core">Understood</button>
</div>
</div>
</div>
</div>
</section>
</main>
<aside>
<div class="sidebar @sidebarRightClosed right">
<div class="position-sticky" style="top:0;">
<div class="scrollable">
<div class="scroll-wrapper ">
<div class="scroll-container ">
<div class="scroll-content ">
<nav>
<ul class="navbar">
<li class="navbar-header">Pick a color scheme</li>
<div class="color-picker-container">
<form class="color-picker" action="">
<fieldset>
<label for="light" class="visually-hidden">Light</label>
<input type="radio" id="light" name="theme" checked>
<label for="pink" class="visually-hidden">Pink theme</label>
<input type="radio" id="pink" name="theme">
<label for="dark" class="visually-hidden">Dark theme</label>
<input type="radio" id="dark" name="theme">
</fieldset>
</form>
</div>
<div class="sidebar-divider"></div>
<li class="navbar-header">Header</li>
<li class="navbar-item">
<a href="#">
<span class="navbar-link">Main navbar link 1</span>
<span class="navbar-link navbar-link-detail">
<div class="badge-label">
22
</div>
</span>
</a>
</li>
<li class="navbar-item">
<a href="#">
<span class="navbar-link">Main navbar link 1</span>
<span class="navbar-link navbar-link-detail">
<div class="badge-label">
22
</div>
</span>
</a>
</li>
<div class="sidebar-divider"></div>
<li class="navbar-header">Header</li>
<form>
<div class="form-group ">
<input type="name" required="required" /><span class="highlight"></span><span class="bar"></span>
<label class="label-animated">Password</label>
<div class="input-helper-text">Some helping Text</div>
<div class="input-error-text">At least 6 characters required</div>
<span class="input-glyph-wraper">
<span class="input-glyph">
<span class="input-glyph button">
<svg class="icon-root svg-icon icon-size-medium" focusable="false" viewBox="0 0 24 24" aria-hidden="true">
@Icons.Material.Filled.Analytics
</svg>
</span>
<span class="input-glyph error">
<i class='bx bx-error-circle'></i>
</span>
</span>
</span>
</div> </div>
</form>
<div>
<div class="sidebar-divider mt-5"></div>
<li class="navbar-header">Header</li>
<div>
<label class="toggle-group reversed" for="toggle-r1">
<input class="toggle-input" id="toggle-r1" name="toggle" type="checkbox" checked>
<div class="toggle-fill"></div>
<label for="toggle-r1" class="toggle-label">Checked</label>
</label>
</div>
<div>
<label class="toggle-group reversed" for="toggle-r2">
<input class="toggle-input" id="toggle-r2" name="toggle" type="checkbox">
<div class="toggle-fill"></div>
<label for="toggle-r2" class="toggle-label">Checked</label>
</label>
</div>
</div>
</ul>
</nav>
</div>
</div>
</div>
</div>
<div class="">test</div>
</div>
</div>
</aside>
</div>
<div class="modal-backdrop fade show"></div>
</body> </body>
@code { @code {
@ -720,12 +1180,39 @@
sidebarClosed = string.IsNullOrWhiteSpace(sidebarClosed) ? "close" : ""; sidebarClosed = string.IsNullOrWhiteSpace(sidebarClosed) ? "close" : "";
} }
private string sidebarRightClosed { get; set; } = "close-r";
private string NavClosed { get; set; } = "showMenu"; private void ToggleSidebarRight()
{
sidebarRightClosed = string.IsNullOrWhiteSpace(sidebarRightClosed) ? "close-r" : "";
}
private string NavClosed { get; set; } = "";
private void ToggleNav() private void ToggleNav()
{ {
NavClosed = string.IsNullOrWhiteSpace(NavClosed) ? "showMenu" : ""; NavClosed = string.IsNullOrWhiteSpace(NavClosed) ? "show" : "";
}
private string NextSlide { get; set; } = "";
private void ToggleNextSlide()
{
NextSlide = string.IsNullOrWhiteSpace(NextSlide) ? "next" : "";
} }
private string PreviousSlide { get; set; } = "";
private void TogglePreviousSlide()
{
PreviousSlide = string.IsNullOrWhiteSpace(PreviousSlide) ? "previous" : "";
}
} }

@ -1,6 +1,7 @@
using Connected.Components.Showcase.Runner; using Connected.Components.Showcase.Runner;
using Microsoft.AspNetCore.Components.Web; using Microsoft.AspNetCore.Components.Web;
using Microsoft.AspNetCore.Components.WebAssembly.Hosting; using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
using Connected.Services;
internal class Program internal class Program
{ {
@ -12,6 +13,8 @@ internal class Program
builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) }); builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });
builder.Services.AddModalDialogService();
await builder.Build().RunAsync(); await builder.Build().RunAsync();
} }
} }

@ -3,6 +3,7 @@
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Connected.Components.Showcase.Runner</title> <title>Connected.Components.Showcase.Runner</title>
<base href="/" /> <base href="/" />
<link href="css/app.css" rel="stylesheet" /> <link href="css/app.css" rel="stylesheet" />

@ -1,44 +1,9 @@
<button <button type="button"
type="button"
href="#"
@onclick="@OnClick" @onclick="@OnClick"
disabled=@Disabled disabled=@Disabled
style="@Style" style="@StyleList"
class="@ClassList"> class="@ClassList">
<div class="@ContentClassList"> <div class="@ContentClassList">
@if (!string.IsNullOrEmpty(Glyph))
{
@if (GlyphPosition == Position.Top || GlyphPosition == Position.Bottom)
{
<div style="align-items:center">
@if (GlyphPosition == Position.Top)
{
<Glyph SVG="@Glyph" Color="@GlyphColor"/>
}
@ChildContent @ChildContent
@if (GlyphPosition == Position.Bottom)
{
<Glyph SVG="@Glyph" Color="@GlyphColor"/>
}
</div>
}
@if (GlyphPosition == Position.Left || GlyphPosition == Position.Right)
{
<div style="display:flex; align-items:center">
@if (GlyphPosition == Position.Left)
{
<Glyph SVG="@Glyph" Color="@GlyphColor" Class="m-1" />
}
@ChildContent
@if (GlyphPosition == Position.Right)
{
<Glyph SVG="@Glyph" Color="@GlyphColor" Class="m-1" />
}
</div>
}
} else
{
@ChildContent
}
</div> </div>
</button> </button>

@ -1,8 +1,6 @@
using Connected.Utilities; using Connected.Utilities;
using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Web; using Microsoft.AspNetCore.Components.Web;
using static Connected.Colors;
using System;
namespace Connected.Components; namespace Connected.Components;
public partial class Button public partial class Button
@ -28,10 +26,10 @@ public partial class Button
/// <summary> /// <summary>
/// Size of the button. /// Size of the button.
/// Options: Size.[Small,Medium,Large,FullWidth] /// Options: Size.[Small,Medium,Large,FullWidth]
/// Default: Size.Large /// Default: Size.Medium
/// </summary> /// </summary>
[Parameter] [Parameter]
public Size Size { get; set; } = Size.Large; public Size Size { get; set; } = Size.Medium;
/// <summary> /// <summary>
/// Text shown inside the button /// Text shown inside the button
@ -48,29 +46,6 @@ public partial class Button
[Parameter] [Parameter]
public bool Disabled { get; set; } = false; public bool Disabled { get; set; } = false;
/// <summary>
/// Glyph (Icon) inside the button.
/// Options: SVG string --> Icons
/// Default: string.Empty
/// </summary>
[Parameter]
public string Glyph { get; set; } = string.Empty;
/// <summary>
/// Position of the glyph relative to button Text parameter. If Glyph parameter == string.Empty this parameter is ignored
/// Options: Position.[left,top,right,bottom]
/// Default: Position.left
/// </summary>
[Parameter]
public Position GlyphPosition { get; set; } = Position.Left;
/// <summary>
/// HEX string of the color for the glyph. If Glyph parameter is empty this parameter is ignored
/// Options: any HEX color string
/// Default: Black (#000000)
/// </summary>
[Parameter]
public string GlyphColor { get; set; } = "#000000";
/// <summary> /// <summary>
/// User defined custom class added on top of default generated classes /// User defined custom class added on top of default generated classes
@ -90,7 +65,7 @@ public partial class Button
/// <summary> /// <summary>
/// User defined custom style /// User defined custom style
/// Options: any user defined string with valid CSS style /// Options: any valid CSS style
/// Default: string.Empty /// Default: string.Empty
/// </summary> /// </summary>
[Parameter] [Parameter]
@ -115,10 +90,21 @@ public partial class Button
#region Styling #region Styling
public string StyleList
{
get
{
return new StyleBuilder()
.AddStyle(Style)
.Build();
}
}
/// <summary> /// <summary>
/// Generated class list for button based on user parameters /// Generated class list for button based on user parameters
/// </summary> /// </summary>
private string ClassList public string ClassList
{ {
get get
{ {
@ -134,7 +120,7 @@ public partial class Button
/// <summary> /// <summary>
/// Generated class list for button based on user parameters /// Generated class list for button based on user parameters
/// </summary> /// </summary>
private string ContentClassList public string ContentClassList
{ {
get get
{ {

@ -2,12 +2,22 @@
@inherits InputBase; @inherits InputBase;
<div class="checkbox-group"> <label class="checkbox-group"
@if (Checked) for="@Id">
{ <input class="@ClassList"
<input id="@Id" name="checkbox" type="checkbox" @onchange="OnChange" @attributes=@InputAttributes checked> style="@StyleList"
} else { id="@Id"
<input id="@Id" name="checkbox" type="checkbox" @onchange="OnChange" @attributes=@InputAttributes> type="checkbox"
} @attributes=@InputAttributes
<label for="@Id" class="checkbox-label">@Label</label> checked="@Checked"
</div> readonly="@Readonly"
disabled="@Disabled">
<div class="checkbox-fill"></div>
<label for="@Id"
class="@LabelClassList"
style="@LabelStyleList">
@Label
</label>
</label>

@ -1,21 +1,100 @@
using Connected.Models; using Connected.Models;
using Connected.Utilities;
using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components;
namespace Connected.Components; namespace Connected.Components;
public partial class CheckBox : InputBase public partial class CheckBox : InputBase
{ {
/// <summary>
/// State of the CheckBox
/// Options: true, false
/// Default: false
/// </summary>
[Parameter] [Parameter]
public bool Checked { get; set; } = false; public bool Checked { get; set; } = false;
/// <summary>
/// ID for the CheckBox
/// </summary>
[Parameter, EditorRequired] [Parameter, EditorRequired]
public string Id { get; set; } public string? Id { get; set; }
/// <summary>
/// Event when the checked is changed
/// </summary>
[Parameter]
public EventCallback<bool> CheckedChanged { get; set; }
/// <summary>
/// OPTIONAL - Style for the input
/// Options: any valid CSS style
/// Default: string.Empty
/// </summary>
[Parameter]
public string Style { get; set; } = string.Empty;
/// <summary>
/// OPTIONAL - Class for the label of input
/// Options: any valid Class name or multiple separated with space
/// Default: string.Empty
/// </summary>
[Parameter]
public string LabelClass { get; set; } = string.Empty;
/// <summary>
/// OPTIONAL - Style for the label of input
/// Options: any valid CSS style
/// Default: string.Empty
/// </summary>
[Parameter] [Parameter]
public EventCallback<bool> CheckedChange { get; set; } public string LabelStyle { get; set; } = string.Empty;
public async Task OnChange(ChangeEventArgs args)
/// <summary>
/// OnChange event when checked is changed
/// </summary>
/// <returns></returns>
public async Task OnChange()
{ {
Checked = (bool)args.Value; Checked = !Checked;
CheckedChange.InvokeAsync(Checked); await CheckedChanged.InvokeAsync(Checked);
} }
private string ClassList
{
get
{
return new CssBuilder("checkbox-input")
.AddClass(base.Class)
.Build();
}
}
private string StyleList
{
get
{
return new StyleBuilder()
.AddStyle(Style)
.Build();
}
}
private string LabelClassList
{
get
{
return new CssBuilder("checkbox-label")
.AddClass(LabelClass)
.Build();
}
}
private string LabelStyleList
{
get
{
return new StyleBuilder()
.AddStyle(LabelStyle)
.Build();
}
}
} }

@ -1,9 +0,0 @@
@using Connected.Models;
@inherits InputBase;
<div>
<div class="container">
@ChildContent
</div>
</div>

@ -1,11 +0,0 @@
using Microsoft.AspNetCore.Components;
namespace Connected.Components;
public partial class CheckBoxGroup
{
[Parameter, EditorRequired]
public string Id { get; set; }
[Parameter]
public RenderFragment ChildContent { get; set; }
}

@ -1,6 +1,6 @@
 
<div style="width:@WidthString; height:@HeightString; overflow:hidden"> <div style="@GlyphStyleList">
<svg viewBox="0 0 24 24" style="fill:@Color;" class="@GlyphClassList" @onclick="@OnClick"> <svg viewBox="0 0 24 24" class="@GlyphClassList" @onclick="@OnClick">
@((MarkupString)SVG) @((MarkupString)SVG)
</svg> </svg>
</div> </div>

@ -2,46 +2,76 @@
using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Web; using Microsoft.AspNetCore.Components.Web;
namespace Connected.Components namespace Connected.Components;
{
public partial class Glyph public partial class Glyph
{ {
/// <summary>
/// SVG markup string for glyph
/// Options: any valid SVG markup string
/// Default: string.Empty
/// </summary>
[Parameter] [Parameter]
public string SVG { get; set; } = string.Empty; public string SVG { get; set; } = string.Empty;
/// <summary>
/// Color of the glyph
/// Options: Color.[Core,Primary,Secondary,Success,Info,Warning,Danger,White,Light,Dark]
/// Default: Color.Dark
/// </summary>
[Parameter] [Parameter]
public string Color { get; set; } = "#000000"; public Color Color { get; set; } = Color.Dark;
/// <summary>
/// Width of the glyph in px
/// Options: Any positive integer number
/// Default: 24
/// </summary>
[Parameter] [Parameter]
public int Width { get; set; } = 24; public int Width { get; set; } = 24;
/// <summary>
/// Height of the glyph in px
/// Options: Any positive integer number
/// Default: 24
/// </summary>
[Parameter] [Parameter]
public int Height { get; set; } = 24; public int Height { get; set; } = 24;
private string WidthString /// <summary>
{ /// Class name or multiple classes separated by space
get /// Options: Any valid class name or names separated by space
{ /// Default: string.Empty
return Width.ToString() + "px"; /// </summary>
} [Parameter]
} public string Class { get; set; } = string.Empty;
private string HeightString private string GlyphClassList
{ {
get get
{ {
return Width.ToString() + "px"; return new CssBuilder()
.AddClass("color-"+Helper.GetEnumDescription<Color>(Color))
.AddClass(Class)
.Build();
} }
} }
/// <summary>
/// User defined style for the glyph
/// Options: Any valid CSS style
/// Default: string.Empty
/// </summary>
[Parameter] [Parameter]
public string Class { get; set; } = string.Empty; public string Style { get; set; } = string.Empty;
private string GlyphClassList private string GlyphStyleList
{ {
get get
{ {
return new CssBuilder() return new StyleBuilder()
.AddClass(Class) .AddStyle("width: "+Width.ToString()+"px; height:"+Height.ToString()+"px; overflow: hidden")
.AddStyle(Style)
.Build(); .Build();
} }
} }
@ -54,7 +84,5 @@ namespace Connected.Components
protected async Task OnClick(MouseEventArgs e) protected async Task OnClick(MouseEventArgs e)
{ {
await Click.InvokeAsync(e); await Click.InvokeAsync(e);
}
} }
} }

@ -0,0 +1,46 @@
@inherits Button
<button type="button"
href="#"
@onclick="@OnClick"
disabled=@Disabled
style="@StyleList"
class="@ClassList">
<div class="@ContentClassList">
@if (!string.IsNullOrEmpty(Glyph))
{
@if (GlyphPosition == Position.Top || GlyphPosition == Position.Bottom)
{
<div style="align-items:center">
@if (GlyphPosition == Position.Top)
{
<Glyph SVG="@Glyph" Color="@GlyphColor" />
}
@ChildContent
@if (GlyphPosition == Position.Bottom)
{
<Glyph SVG="@Glyph" Color="@GlyphColor" />
}
</div>
}
@if (GlyphPosition == Position.Left || GlyphPosition == Position.Right)
{
<div style="display:flex; align-items:center">
@if (GlyphPosition == Position.Left)
{
<Glyph SVG="@Glyph" Color="@GlyphColor" Class="m-1" />
}
@ChildContent
@if (GlyphPosition == Position.Right)
{
<Glyph SVG="@Glyph" Color="@GlyphColor" Class="m-1" />
}
</div>
}
}
else
{
@ChildContent
}
</div>
</button>

@ -0,0 +1,34 @@
using Microsoft.AspNetCore.Components;
namespace Connected.Components;
public partial class GlyphButton : Button
{
#region Parameters
/// <summary>
/// Glyph (Icon) inside the button.
/// Options: SVG string --> Icons
/// Default: string.Empty
/// </summary>
[Parameter, EditorRequired]
public string Glyph { get; set; } = string.Empty;
/// <summary>
/// Position of the glyph relative to button Text parameter. If Glyph parameter == string.Empty this parameter is ignored
/// Options: Position.[left,top,right,bottom]
/// Default: Position.left
/// </summary>
[Parameter]
public Position GlyphPosition { get; set; } = Position.Left;
/// <summary>
/// Color for the glyph. If Glyph parameter is empty this parameter is ignored
/// Options: Color.[Core,Primary,Secondary,Success,Info,Warning,Danger,White,Light,Dark]
/// Default: Color.Dark
/// </summary>
[Parameter]
public Color GlyphColor { get; set; } = Color.Dark;
#endregion
}

@ -1,7 +1,6 @@
<a <a class="@LinkClassList"
class="@LinkClassList"
style="@LinkStyleList" style="@LinkStyleList"
href="@Url" href="@Url"
target="@Target" > target="@_target">
@Text @Text
</a> </a>

@ -1,18 +1,47 @@
using Connected.Utilities; using Connected.Enums;
using Connected.Utilities;
using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components;
namespace Connected.Components; namespace Connected.Components;
public partial class Link public partial class Link
{ {
/// <summary>
/// URL of the link
/// Options: Any valid web page adress
/// Default: string.Empty
/// </summary>
[Parameter, EditorRequired] [Parameter, EditorRequired]
public string Url { get; set; } = string.Empty; public string Url { get; set; } = string.Empty;
[Parameter, EditorRequired] /// <summary>
/// Text shown for the link. If this is not provided URL is used
/// Options: Any valid string
/// Default: string.Empty
/// </summary>
[Parameter]
public string Text { get; set; } = string.Empty; public string Text { get; set; } = string.Empty;
[Parameter, EditorRequired] /// <summary>
public string Target { get; set; } = "_self"; /// Target where the link shall open
/// Options: Target.[Self,Parent,Top,Blank]
/// Default: Target.Self
/// </summary>
[Parameter]
public Target Target { get; set; } = Target.Self;
private string _target
{
get
{
return Helper.GetEnumDescription<Target>(Target);
}
}
/// <summary>
/// Class name or multiple classes separated by space
/// Options: Any valid class name or names separated by space
/// Default: string.Empty
/// </summary>
[Parameter] [Parameter]
public string Class { get; set; } = string.Empty; public string Class { get; set; } = string.Empty;
@ -26,6 +55,11 @@ public partial class Link
} }
} }
/// <summary>
/// Style string for the link
/// Options: Any valid CSS style
/// Default: string.Empty
/// </summary>
[Parameter] [Parameter]
public string Style { get; set; } = string.Empty; public string Style { get; set; } = string.Empty;
@ -39,10 +73,13 @@ public partial class Link
} }
} }
protected override async Task OnParametersSetAsync() protected override async Task OnInitializedAsync()
{ {
if (string.IsNullOrEmpty(Text)) Text = Url; //if Text parameter is not provided we set it to match URL
await base.OnParametersSetAsync(); if (string.IsNullOrEmpty(Text))
Text = Url;
await base.OnInitializedAsync();
} }
} }

@ -0,0 +1,25 @@
@using Connected.Models.Modal;
@if (IsVisible)
{
<div class="modal fade show" @onclick="@CloseIfEnabled" @onkeydown="@(e => CheckEscape(e))" tabindex="-1" @ref="@root">
<div class="modal-dialog modal-dialog-scrollable modal-dialog-centered">
<div class="modal-content" @onclick="PreventClose">
@if (!ModalOptions.NoHeader)
{
<div class="modal-header">
<h3 class="modal-title">@Title</h3>
</div>
}
<div class="modal-body">
@Content
</div>
<div class="modal-footer">
@foreach (ModalButton button in buttons)
{
<button type="button" class="btn @button.GetButtonClass" @onclick="@(()=>CloseModal(button))">@button.ButtonText</button>
}
</div>
</div>
</div>
</div>
}

@ -0,0 +1,108 @@
using Connected.Models.Modal;
using Connected.Services;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Web;
namespace Connected.Components;
public partial class ModalDialog : IDisposable
{
[Inject] ModalDialogService? ModalService { get; set; }
protected ElementReference root;
protected bool IsVisible { get; set; }
protected string? Title { get; set; }
protected RenderFragment? Content { get; set; }
protected bool OverlayClickToClose { get; set; } = true;
protected List<ModalButton> buttons { get; set; } = new();
protected ModalOptions? ModalOptions { get; set; }
protected override void OnInitialized()
{
ModalService.OnShow += ShowModal;
ModalService.OnClose += CloseModal;
}
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (IsVisible)
await root.FocusAsync();
}
public void ShowModal(string title, RenderFragment content, List<ModalButton> buttons, ModalOptions options)
{
Title = title;
Content = content;
IsVisible = true;
ModalOptions = options;
this.buttons = buttons;
StateHasChanged();
}
public void CloseModal(ModalButton? button)
{
if (button is not null)
{
if (button.CloseDialogOnClick)
{
CloseModal();
}
button.OnClickEvent.Delegate.DynamicInvoke(button.OnClickEvent.args);
}
StateHasChanged();
}
public void CloseModal()
{
IsVisible = false;
Title = "";
Content = null;
StateHasChanged();
}
public void Dispose()
{
if (ModalService is not null)
{
ModalService.OnShow -= ShowModal;
ModalService.OnClose -= CloseModal;
}
}
public void CheckEscape(KeyboardEventArgs args)
{
if (!ModalOptions.DisableEscKey)
{
var key = args.Key.ToLower();
if (key.Equals("escape"))
{
CloseModal();
}
}
}
public void CloseIfEnabled(MouseEventArgs args)
{
if (!ModalOptions.DisableBackdropClick)
{
if (OverlayClickToClose)
{
CloseModal();
}
}
OverlayClickToClose = true;
}
public void PreventClose(MouseEventArgs args)
{
OverlayClickToClose = false;
}
}

@ -0,0 +1,45 @@
@using Connected.Models;
@inherits InputBase;
<div class="@InputFieldClassList">
<textarea value="@Value"
placeholder="@Placeholder"
disabled="@Disabled"
readonly="@Readonly"
required="@Required"
style="overflow-x: hidden; overflow-y: hidden;"
@oninput=@ChangeValueAsync
@attributes="@InputAttributes" />
<span class="highlight"></span>
<span class="bar"></span>
@if (IsLabel)
{
<label class="label-animated">@Label</label>
}
@if (IsHelperText && !IsError)
{
<div class="input-helper-text">@HelperText</div>
}
@if (IsError)
{
<div class="input-error-text">@ErrorText</div>
}
<span class="input-glyph-wraper">
<span class="input-glyph">
@if (Clearable && !string.IsNullOrEmpty(Value))
{
<span class="input-glyph button" @onclick="Clear">
<Glyph SVG="@Icons.Material.Rounded.Dangerous" />
</span>
}
@if (IsError)
{
<span class="input-glyph error">
<Glyph SVG="@Icons.Material.Outlined.Error" />
</span>
}
</span>
</span>
</div>

@ -0,0 +1,119 @@
using Connected.Models;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Web;
using System.ComponentModel.DataAnnotations;
using System.Security.Cryptography;
namespace Connected.Components;
public partial class MultilineInput : InputBase
{
#region Parameters
private int MinRows { get; set; } = 1;
/// <summary>
/// Number of rows
/// </summary>
[Parameter]
public int Rows
{
get
{
return _numRows;
}
set
{
if (value >= MinRows) _numRows= value;
else _numRows = MinRows;
}
}
private int _numRows = 1;
/// <summary>
/// Value of the TextInput. Used for @bind-Value
/// </summary>
[Parameter]
public string Value { get; set; } = string.Empty;
#endregion
#region Events, Methods
/// <summary>
/// Event triggered when value changes
/// </summary>
[Parameter]
public EventCallback<string> ValueChanged { get; set; }
/// <summary>
/// Method that triggers oninput -> when value inside the component changes
/// </summary>
/// <param name="args"></param>
/// <returns></returns>
private async Task ChangeValueAsync(ChangeEventArgs args)
{
int oldRows = Rows;
await ValueChanged.InvokeAsync(args?.Value?.ToString());
int newRows = GetNumberOfLines(args.Value.ToString());
if (newRows == MinRows)
{
Rows = MinRows;
ChangeAttribute("rows", Rows);
StateHasChanged();
}
else
{
Rows = Math.Max(MinRows, newRows);
if (oldRows < Rows)
{
ChangeAttribute("rows", Rows);
StateHasChanged();
}
}
}
private int GetNumberOfLines(string s)
{
int result = Math.Max(s.Split("\r\n").Length, 1);
result = Math.Max(s.Split("\r").Length, result);
result = Math.Max(s.Split("\n").Length, result);
return result;
}
/// <summary>
/// Clear the value of the TextInput
/// </summary>
/// <returns></returns>
private async Task Clear()
{
await ValueChanged.InvokeAsync(string.Empty);
}
#endregion
#region Lifecycle
private void AddAttribute(string key, object value)
{
if (!InputAttributes.ContainsKey(key))
InputAttributes.Add(key, value);
}
private void ChangeAttribute(string key, object value)
{
if (InputAttributes.ContainsKey(key)) InputAttributes.Remove(key);
InputAttributes.Add(key, value);
}
protected override void OnInitialized()
{
base.OnInitialized();
MinRows = Rows;
AddAttribute("rows", MinRows);
}
#endregion
}

@ -7,13 +7,14 @@
<div class="@InputFieldClassList"> <div class="@InputFieldClassList">
<input type="text" <input type="text"
placeholder="@Placeholder" placeholder="@Placeholder"
step="@_step" step="@Step"
disabled="@Disabled" disabled="@Disabled"
readonly="@Readonly" readonly="@Readonly"
required="@Required"
value="@_value" value="@_value"
@onkeydown=@(args => ChangeValue(args)) @onkeydown=@(args => ChangeValue(args))
@onkeydown:preventDefault="@_preventDefaultAction" @onkeydown:preventDefault="@_preventDefaultAction"
@oninput=@GetValueAsync @oninput=@SetValueAsync
@onmousewheel=@OnMouseWheel @onmousewheel=@OnMouseWheel
@onchange="@Change" @onchange="@Change"
@onwheel="OnMouseWheel" @onwheel="OnMouseWheel"
@ -39,18 +40,16 @@
<Glyph Width=16 Height=16 SVG="@Icons.Material.Outlined.KeyboardArrowUp" Click="StepUp" /> <Glyph Width=16 Height=16 SVG="@Icons.Material.Outlined.KeyboardArrowUp" Click="StepUp" />
<Glyph Width=16 Height=16 SVG="@Icons.Material.Outlined.KeyboardArrowDown" Click="StepDown"></Glyph> <Glyph Width=16 Height=16 SVG="@Icons.Material.Outlined.KeyboardArrowDown" Click="StepDown"></Glyph>
</span> </span>
@if (Clearable && Value.ToString().Length > 0) @if (Clearable && !string.IsNullOrEmpty(Value?.ToString()))
{ {
<span class="input-glyph button" @onclick="Clear"> <span class="input-glyph button" @onclick="Clear">
<Glyph SVG="@Icons.Material.Rounded.Dangerous" /> <Glyph SVG="@Icons.Material.Rounded.Dangerous" />
<!--<i class='bx bx-x-circle'></i>-->
</span> </span>
} }
@if (IsError) @if (IsError)
{ {
<span class="input-glyph error"> <span class="input-glyph error">
<Glyph SVG="@Icons.Material.Outlined.Error" Color="#D10000" /> <Glyph SVG="@Icons.Material.Outlined.Error" />
<!--<i class='bx bx-error-circle'></i>-->
</span> </span>
} }
</span> </span>

@ -7,70 +7,93 @@ using System.Numerics;
namespace Connected.Components; namespace Connected.Components;
public partial class NumberInput<NumberType> : InputBase where NumberType : INumber<NumberType> public partial class NumberInput<NumberType> : InputBase where NumberType : INumber<NumberType>
{ {
/// <summary>
private double _step =1; /// Step for up and down on numeric field
/// Options: Any double number
/// Default: 1
/// </summary>
[Parameter] [Parameter]
public double Step { public double Step { get; set; } = 1;
get
{
return _step;
}
set
{
_step=value;
}
}
/// <summary>
/// Mouse wheel disable to prevent StepUp/StepDown on number filed
/// Options: true, false
/// Default: false
/// </summary>
[Parameter] [Parameter]
public bool DisableMouseWheel public bool DisableMouseWheel { get; set; } = false;
{
get;
set;
} = false;
/// <summary>
/// Increase 'Value' for the 'Step'
/// </summary>
/// <returns>'Value' increased for the 'Step' parameter</returns>
private async Task StepUp() private async Task StepUp()
{ {
try try
{ {
double num = (double)Convert.ChangeType(Value, typeof(double)); var num = Helper.ConvertToType<double>(Value);
num += _step;
num += Step;
if (DecimalPlaces > 0) if (DecimalPlaces > 0)
num = Math.Round(num, DecimalPlaces); num = Math.Round(num, DecimalPlaces);
Value = (NumberType)Convert.ChangeType(num, typeof(NumberType)); Value = Helper.ConvertToType<NumberType>(num);
if (IsError) ErrorText = string.Empty;
if (IsError)
ErrorText = string.Empty;
} }
catch catch
{ {
ErrorText = "Error with step up!"; ErrorText = "Error with step up!";
Value = default(NumberType); Value = default;
} }
await ValueChanged.InvokeAsync(Value); await ValueChanged.InvokeAsync(Value);
} }
/// <summary>
/// Decrease 'Value' for the 'Step'
/// </summary>
/// <returns>'Value' decreased for the 'Step' parameter</returns>
private async Task StepDown() private async Task StepDown()
{ {
try try
{ {
double num = (double)Convert.ChangeType(Value, typeof(double)); var num = Helper.ConvertToType<double>(Value);
num -= Step;
num -= _step;
if (DecimalPlaces > 0) if (DecimalPlaces > 0)
num = Math.Round(num, DecimalPlaces); num = Math.Round(num, DecimalPlaces);
Value = (NumberType)Convert.ChangeType(num, typeof(NumberType));
if (IsError) ErrorText = string.Empty; Value = Helper.ConvertToType<NumberType>(num);
} catch
if (IsError)
ErrorText = string.Empty;
}
catch
{ {
ErrorText = "Error with step down!"; ErrorText = "Error with step down!";
Value = default(NumberType); Value = default;
} }
await ValueChanged.InvokeAsync(Value); await ValueChanged.InvokeAsync(Value);
} }
/// <summary>
/// Event triggered when mouse wheel is activated inside component
/// </summary>
/// <param name="args">WheelEventArgs argument</param>
/// <returns>Doesnt return values just increasing/decreasing values</returns>
protected async Task OnMouseWheel(WheelEventArgs args) protected async Task OnMouseWheel(WheelEventArgs args)
{ {
if (DisableMouseWheel == false) if (DisableMouseWheel)
{ return;
if (args.ShiftKey || Disabled || Readonly) if (args.ShiftKey || Disabled || Readonly)
return; return;
if (args.DeltaY >= 0) if (args.DeltaY >= 0)
{ {
await StepDown(); await StepDown();
@ -79,68 +102,92 @@ public partial class NumberInput<NumberType>:InputBase where NumberType : INumbe
{ {
await StepUp(); await StepUp();
} }
} else
{
return;
}
} }
private string _value; private string? _value;
/// <summary>
/// Value of any numeric type
/// Options: any numeric type variable
/// Default: null
/// </summary>
[Parameter] [Parameter]
[EditorRequired]
public NumberType? Value public NumberType? Value
{ {
get get
{ {
if (string.IsNullOrEmpty(_value)) return default(NumberType); if (string.IsNullOrEmpty(_value))
return (NumberType)Convert.ChangeType(_value, typeof(NumberType)); return default;
else
{
try
{
return Helper.ConvertToType<NumberType>(_value);
} catch
{
return default;
}
}
} }
set set
{ {
_value = value.ToString(); _value = value?.ToString();
} }
} }
/// <summary>
/// Number of decimal places for Value. If set, Value is corrected when input looses focus
/// Options: any integer number greater or equal 0
/// Default: 0
/// </summary>
[Parameter] [Parameter]
public int DecimalPlaces { get; set; } = 0; public int DecimalPlaces { get; set; } = 0;
/// <summary>
/// Value change event
/// </summary>
[Parameter] [Parameter]
public EventCallback<NumberType> ValueChanged { get; set; } public EventCallback<NumberType> ValueChanged { get; set; }
public async Task GetValueAsync(ChangeEventArgs args) public async Task SetValueAsync(ChangeEventArgs args)
{ {
if (args.Value is not null) if (args.Value is not null)
{ {
string newVal = args.Value.ToString(); var newVal = args.Value.ToString()!;
if (!newVal.Equals("0")) if (!newVal.Equals("0"))
{ {
if (newVal.ToString().Contains("-")) if (newVal.ToString().Contains("-"))
newVal = "-" + newVal.ToString().Replace("-", ""); newVal = "-" + newVal.ToString().Replace("-", "");
if (newVal.ToString().ToLower().Contains("e")) if (newVal.ToString().ToLower().Contains("e"))
newVal = "e" + newVal.ToString().Replace("e", ""); newVal = "e" + newVal.ToString().Replace("e", "");
} }
if (string.IsNullOrEmpty(newVal)) if (string.IsNullOrEmpty(newVal))
{ await ValueChanged.InvokeAsync(default);
await ValueChanged.InvokeAsync((NumberType)Convert.ChangeType((NumberType)Convert.ChangeType(null, typeof(NumberType)), typeof(NumberType)));
}
else
{
if (!newVal.Equals(_value)) if (!newVal.Equals(_value))
await ValueChanged.InvokeAsync((NumberType)Convert.ChangeType((NumberType)Convert.ChangeType(newVal, typeof(NumberType)), typeof(NumberType))); await ValueChanged.InvokeAsync(Helper.ConvertToType<NumberType>(newVal));
}
} }
} }
public async Task Change(ChangeEventArgs args) public async Task Change(ChangeEventArgs args)
{ {
if (args.Value is not null) if (args.Value is not null)
{ Value = AdjustDecimalPlaces(Helper.ConvertToType<NumberType>(args.Value));
Value = AdjustDecimalPlaces((NumberType)Convert.ChangeType(args.Value, typeof(NumberType)));
} await ValueChanged.InvokeAsync(Value);
ValueChanged.InvokeAsync(Value);
} }
[Parameter] public EventCallback<KeyboardEventArgs> OnKeyDown { get; set; } /// <summary>
/// On keyboard key press event
/// </summary>
[Parameter]
public EventCallback<KeyboardEventArgs> OnKeyDown { get; set; }
private bool CheckKey(string key) private bool CheckKey(string key)
{ {
@ -176,45 +223,44 @@ public partial class NumberInput<NumberType>:InputBase where NumberType : INumbe
if (args is not null) if (args is not null)
{ {
var key = args.Key.ToString().ToLower(); var key = args.Key.ToString().ToLower();
if (CheckKey(key)) if (CheckKey(key))
{ {
_preventDefaultAction = false; _preventDefaultAction = false;
await OnKeyDown.InvokeAsync(args); await OnKeyDown.InvokeAsync(args);
} }
} else }
else
{ {
args.Key = null; args.Key = null;
} }
} }
private NumberType AdjustDecimalPlaces(NumberType value) /// <summary>
/// Method for adjusting decimal places provided with parameter
/// </summary>
/// <param name="value">Value whose decimal places we want to change</param>
/// <returns>NumberType result with adjusted decimal places</returns>
private NumberType? AdjustDecimalPlaces(NumberType? value)
{ {
var result = value; var result = value;
if (DecimalPlaces > 0) if (DecimalPlaces > 0)
{ {
double converted = Math.Round((double)Convert.ChangeType(result, typeof(double)), DecimalPlaces); double converted = Math.Round(Helper.ConvertToType<double>(result), DecimalPlaces);
return (NumberType)Convert.ChangeType(converted, typeof(NumberType)); return Helper.ConvertToType<NumberType>(converted);
} }
return result; return result;
} }
/// <summary>
/// Clear event for user clear icon click. It clears the Value and set it to
/// </summary>
/// <returns></returns>
private async Task Clear() private async Task Clear()
{ {
_value = string.Empty; var val = Helper.ConvertToType<NumberType>(null);
await ValueChanged.InvokeAsync((NumberType)Convert.ChangeType(0, typeof(NumberType))); await ValueChanged.InvokeAsync(val);
}
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
if (!DecimalPlaces.Equals(Helper.GetDecimalPlaces(Value)))
{
Value = AdjustDecimalPlaces(Value);
StateHasChanged();
}
}
} }
#region Lifecycle #region Lifecycle
@ -222,18 +268,26 @@ public partial class NumberInput<NumberType>:InputBase where NumberType : INumbe
{ {
if (typeof(NumberType).Name.ToLower().Contains("int")) if (typeof(NumberType).Name.ToLower().Contains("int"))
{ {
if (Step - (int)Step > 0) Step = (int)Step; if (Step - (int)Step > 0)
if (Step < 1) Step = 1; Step = (int)Step;
if (Step < 1)
Step = 1;
} }
await base.OnParametersSetAsync(); await base.OnParametersSetAsync();
} }
protected override async Task OnInitializedAsync() protected override void OnAfterRender(bool firstRender)
{
if (firstRender)
{ {
await base.OnInitializedAsync(); if (Value is not null)
if (Required) {
if (!DecimalPlaces.Equals(Helper.GetDecimalPlaces(Value)))
{ {
if (!InputAttributes.ContainsKey("required")) InputAttributes.Add("required", true); Value = AdjustDecimalPlaces(Value);
StateHasChanged();
}
}
} }
} }

@ -2,7 +2,20 @@
@inherits InputBase; @inherits InputBase;
<div class="radio-group"> <label class="radio-group"
<input id="@Id" name="@ParentRadioGroup.Name" type="radio" @onchange="OnChange" @attributes=@InputAttributes> for="@Id">
<label for="@Id" class="radio-label">@Label</label> <input class="@ClassNameList"
</div> id="@Id"
name="@ParentRadioGroup?.Name"
type="radio"
@onchange="OnChange"
@attributes=@InputAttributes
disabled="@Disabled"
readonly="@Readonly"
checked="@Checked">
<div class="radio-fill"></div>
<label for="@Id"
class="@LabelClassNameList">@Label</label>
</label>

@ -1,9 +1,11 @@
using Connected.Models; using Connected.Models;
using Connected.Utilities;
using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components;
namespace Connected.Components; namespace Connected.Components;
public partial class Radio : InputBase public partial class Radio : InputBase
{ {
#region Parameters
[CascadingParameter] [CascadingParameter]
public RadioGroup? ParentRadioGroup { get; set; } public RadioGroup? ParentRadioGroup { get; set; }
@ -11,21 +13,51 @@ public partial class Radio: InputBase
public bool Checked { get; set; } = false; public bool Checked { get; set; } = false;
[Parameter, EditorRequired] [Parameter, EditorRequired]
public string Id { get; set; } public string? Id { get; set; }
#endregion
#region Events
[Parameter]
public EventCallback<bool> CheckedChanged { get; set; }
public async Task OnChange()
{
Checked = !Checked;
await CheckedChanged.InvokeAsync(Checked);
}
#endregion
#region Style
[Parameter] [Parameter]
public EventCallback<bool> CheckedChange { get; set; } public string ClassName { get; set; } = string.Empty;
public async Task OnChange(ChangeEventArgs args)
private string ClassNameList
{
get
{ {
Checked = (bool)args.Value; return new CssBuilder("radio-input")
CheckedChange.InvokeAsync(Checked); .AddClass(ClassName)
.Build();
}
} }
protected override async Task OnInitializedAsync() [Parameter]
public string LabelClassName { get; set; } = string.Empty;
private string LabelClassNameList
{ {
await base.OnInitializedAsync(); get
if (ParentRadioGroup.Disabled) Disabled = true; {
if (!InputAttributes.ContainsKey("disabled")) return new CssBuilder("radio-label")
InputAttributes.Add("disabled", Disabled); .AddClass(LabelClassName)
.Build();
}
} }
#endregion
} }

@ -1,7 +1,5 @@
@using Connected.Models; @using Connected.Models;
@inherits InputBase;
<CascadingValue Value="this"> <CascadingValue Value="this">
<div> <div>
@if (!string.IsNullOrEmpty(Name)) @if (!string.IsNullOrEmpty(Name))

@ -3,10 +3,32 @@
namespace Connected.Components; namespace Connected.Components;
public partial class RadioGroup public partial class RadioGroup
{ {
#region Parameters
/// <summary>
/// Radio group name. Mandatory! Used for proper radio button grouping
/// Options: any string will do
/// Default: 'radiogroup'
/// </summary>
[Parameter, EditorRequired] [Parameter, EditorRequired]
public string Name { get; set; } public string? Name { get; set; } = "radiogroup";
/// <summary>
/// Used for globaly disabling radio button group and all the radios within
/// Options: true or false
/// Default: false
/// </summary>
[Parameter]
public bool Disabled { get; set; } = false;
/// <summary>
/// All the radiobuttons and other components inside radio group
/// </summary>
[Parameter] [Parameter]
public RenderFragment ChildContent { get; set; } public RenderFragment? ChildContent { get; set; }
#endregion
} }

@ -4,19 +4,23 @@
@inherits InputBase; @inherits InputBase;
@if (component_loaded)
{
@if (Items is not null) @if (Items is not null)
{ {
<div class="@InputFieldClassList"> <div class="@InputFieldClassList">
<select type="textarea" style="height:0px;" @attributes=@InputAttributes> <select type="textarea"
</select> style="height:0px;"
@attributes=@InputAttributes></select>
@if (IsLabel) @if (IsLabel)
{ {
<label class="label-animated">@Label</label> <label class="label-animated">@Label</label>
} }
<span class="highlight"></span> <span class="highlight"></span>
<span class="bar">
</span> <span class="bar"></span>
<span class="input-glyph-wraper"> <span class="input-glyph-wraper">
@if (Clearable) @if (Clearable)
{ {
@ -35,7 +39,8 @@
} }
</span> </span>
<div class="drop-down"> <div class="drop-down">
<div class="dropdown-menu p-2" aria-labelledby="dropdownMenuButton"> <div class="dropdown-menu p-2"
aria-labelledby="dropdownMenuButton">
@if (EnableSearch) @if (EnableSearch)
{ {
<input type="text" <input type="text"
@ -43,14 +48,18 @@
class="dropdown-item" class="dropdown-item"
@bind-value="@SearchText" /> @bind-value="@SearchText" />
} }
@foreach (ValueType item in Items) @foreach (ValueType item in FilteredItems)
{ {
@if (item is not null) @if (item is not null)
{ {
<div class="dropdown-item" @onclick=@(()=>SetSelectedItem(@item))>@item.ToString()</div> <div class="dropdown-item"
@onclick=@(()=>SetSelectedItem(@item))>
@item.ToString()
</div>
} }
} }
</div> </div>
</div> </div>
</div> </div>
} }
}

@ -1,21 +1,46 @@
using Connected.Models; using Connected.Models;
using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
namespace Connected.Components; namespace Connected.Components;
public partial class SimpleSelect<ValueType> : InputBase public partial class SimpleSelect<ValueType> : InputBase
{ {
[Parameter] private bool component_loaded = false;
public ValueType Value { get; set; } #region Parameters
/// <summary>
/// Value that is currently selected in the dropdown. Used for @bind-Value
/// </summary>
[Parameter] [Parameter]
public IEnumerable<ValueType> Items { get; set; } public ValueType? Value { get; set; }
/// <summary>
/// Collection of Items to work on (Filter). Filtered result is then shown in dropdown. If no filter is aplied, all the items are shown
/// </summary>
[Parameter, EditorRequired]
public ObservableCollection<ValueType>? Items { get; set; }
public IEnumerable<ValueType> OriginalItems { get; set; } /// <summary>
/// Collection of items from 'Items' filtered with 'SearchText'
/// </summary>
private List<ValueType>? FilteredItems { get; set; }
/// <summary>
/// Enable edit text search box for item filtering
/// Options: true or false
/// Default: true
/// </summary>
[Parameter] [Parameter]
public bool EnableSearch { get; set; } = true; public bool EnableSearch { get; set; } = true;
private string _searchText { get; set; } = string.Empty; private string _searchText { get; set; } = string.Empty;
/// <summary>
/// Search string provided by user
/// Options: any string
/// Default: string.Empty
/// </summary>
public string SearchText public string SearchText
{ {
get get
@ -29,48 +54,92 @@ public partial class SimpleSelect<ValueType> : InputBase
} }
} }
#endregion
#region Events, Methods
/// <summary>
/// Method for setting the item on select
/// </summary>
/// <param name="item">item that will be set as selected</param>
/// <returns>Methot returns nothing</returns>
private async Task SetSelectedItem(ValueType item) private async Task SetSelectedItem(ValueType item)
{ {
//DropDownClassToggle();
await ValueChanged.InvokeAsync(item); await ValueChanged.InvokeAsync(item);
} }
/// <summary>
/// Method for filtering items using 'SearchText' as filter
/// </summary>
private void FilterItems() private void FilterItems()
{
if (Items is not null)
{ {
if (string.IsNullOrEmpty(_searchText)) if (string.IsNullOrEmpty(_searchText))
{ {
Items = OriginalItems; SetItems();
} }
else else
{ {
Items = Items.Where(item => item.ToString().ToLower().Contains(_searchText.ToLower())); FilteredItems = Items.Where(item => item.ToString().ToLower().Contains(_searchText.ToLower())).ToList();
} }
StateHasChanged(); StateHasChanged();
} }
}
/// <summary>
/// Event triggered when value changes
/// </summary>
[Parameter] [Parameter]
public EventCallback<ValueType> ValueChanged { get; set; } public EventCallback<ValueType> ValueChanged { get; set; }
private async Task ChangeValueAsync(ChangeEventArgs args)
/// <summary>
/// Method for setting the FilteredItems collection keeping the original Item collection
/// </summary>
private void SetItems()
{
if (Items is not null)
{ {
await ValueChanged.InvokeAsync((ValueType)Convert.ChangeType(args.Value, typeof(ValueType))); FilteredItems = Items.ToList();
}
} }
protected override async Task OnParametersSetAsync() /// <summary>
/// Event triggered when the provided Items collection changes
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void OriginalItems_CollectionChanged(object? sender, NotifyCollectionChangedEventArgs e)
{ {
SetItems();
OriginalItems = Items; FilterItems();
if (_searchText.Length>0) FilterItems();
await base.OnParametersSetAsync();
} }
#endregion
#region Lifecycle
/// <summary>
/// Initializing Collections and aplying Filters if provided
/// </summary>
/// <returns>Nothing gets returned</returns>
protected override async Task OnInitializedAsync() protected override async Task OnInitializedAsync()
{ {
await base.OnInitializedAsync(); await base.OnInitializedAsync();
if (Required) if (Items is null)
{ {
if (InputAttributes.ContainsKey("required")) InputAttributes.Add("required", true); Items= new ObservableCollection<ValueType>();
} }
SetItems();
if (_searchText.Length > 0)
FilterItems();
Items.CollectionChanged += OriginalItems_CollectionChanged;
component_loaded = true;
StateHasChanged();
} }
#endregion
} }

@ -3,27 +3,15 @@
@inherits InputBase; @inherits InputBase;
<div class="@InputFieldClassList"> <div class="@InputFieldClassList">
@if (NumOfRows==1) <input type="@InputType"
{
<input type="@inputType"
value="@Value" value="@Value"
placeholder="@Placeholder" placeholder="@Placeholder"
disabled="@Disabled" disabled="@Disabled"
readonly="@Readonly" readonly="@Readonly"
required="@Required"
@oninput=@ChangeValueAsync @oninput=@ChangeValueAsync
@attributes="@InputAttributes" /> @attributes="@InputAttributes" />
} else
{
<textarea type="textarea"
rows="@NumOfRows"
value="@Value"
placeholder="@Placeholder"
disabled="@Disabled"
readonly="@Readonly"
@oninput=@ChangeValueAsync
@attributes="@InputAttributes" />
}
<span class="highlight"></span> <span class="highlight"></span>
<span class="bar"></span> <span class="bar"></span>
@ -45,16 +33,15 @@
{ {
<span class="input-glyph button" @onclick="Clear"> <span class="input-glyph button" @onclick="Clear">
<Glyph SVG="@Icons.Material.Rounded.Dangerous" /> <Glyph SVG="@Icons.Material.Rounded.Dangerous" />
<!--<i class='bx bx-x-circle'></i>-->
</span> </span>
} }
@if (IsError) @if (IsError)
{ {
<span class="input-glyph error"> <span class="input-glyph error">
<Glyph SVG="@Icons.Material.Outlined.Error" Color="#D10000" /> <Glyph SVG="@Icons.Material.Outlined.Error" />
<!--<i class='bx bx-error-circle'></i>-->
</span> </span>
} }
</span> </span>
</span> </span>
</div> </div>

@ -4,10 +4,24 @@ using Microsoft.AspNetCore.Components;
namespace Connected.Components; namespace Connected.Components;
public partial class TextInput : InputBase public partial class TextInput : InputBase
{ {
#region Parameters
/// <summary>
/// Setter for the TextInput if input is password field (for hiding characters)
/// Options: true or false
/// Default: false;
/// </summary>
[Parameter] [Parameter]
public bool IsPassword { get; set; } = false; public bool IsPassword { get; set; } = false;
/// <summary>
/// String for the component to use if TextInput is password field
/// </summary>
private string InputType => IsPassword ? "password" : "text";
/// <summary>
/// Number of rows
/// </summary>
[Parameter] [Parameter]
public int NumOfRows public int NumOfRows
{ {
@ -17,52 +31,45 @@ public partial class TextInput: InputBase
} }
set set
{ {
if (value < 1) _numberOfLines = Math.Max(1, value);
{
_numberOfLines = 1;
}
else
{
_numberOfLines = value;
}
} }
} }
private int _numberOfLines = 1; private int _numberOfLines = 1;
/// <summary>
/// Value of the TextInput. Used for @bind-Value
/// </summary>
[Parameter] [Parameter]
public string Value { get; set; } = string.Empty; public string Value { get; set; } = string.Empty;
private string inputType #endregion
{
get #region Events, Methods
{
if (IsPassword) return "password";
return "text";
}
}
/// <summary>
/// Event triggered when value changes
/// </summary>
[Parameter] [Parameter]
public EventCallback<string> ValueChanged { get; set; } public EventCallback<string> ValueChanged { get; set; }
/// <summary>
/// Method that triggers oninput -> when value inside the component changes
/// </summary>
/// <param name="args"></param>
/// <returns></returns>
private async Task ChangeValueAsync(ChangeEventArgs args) private async Task ChangeValueAsync(ChangeEventArgs args)
{ {
await ValueChanged.InvokeAsync(args.Value.ToString()); await ValueChanged.InvokeAsync(args?.Value?.ToString());
} }
/// <summary>
/// Clear the value of the TextInput
/// </summary>
/// <returns></returns>
private async Task Clear() private async Task Clear()
{ {
await ValueChanged.InvokeAsync(string.Empty); await ValueChanged.InvokeAsync(string.Empty);
}
protected override async Task OnInitializedAsync()
{
await base.OnInitializedAsync();
if (Required)
{
if (!InputAttributes.ContainsKey("required")) InputAttributes.Add("required", true);
}
} }
#endregion
} }

@ -0,0 +1,21 @@
@inherits Button
<button type="button"
@onclick="@Clicked"
disabled=@Disabled
style="@StyleList"
class="@ClassList">
<div class="@ContentClassList">
<div style="align-items:center">
@if (GlyphPosition == Position.Top)
{
<Glyph SVG="@Glyph" Color="@GlyphColor" />
}
@ChildContent
@if (GlyphPosition == Position.Bottom)
{
<Glyph SVG="@Glyph" Color="@GlyphColor" />
}
</div>
</div>
</button>

@ -0,0 +1,120 @@
using Connected.Utilities;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Web;
namespace Connected.Components;
public partial class ToggleGlyphButton: Button
{
#region Parameters
/// <summary>
/// Outline type of the button.
/// Options: true, false
/// Default: false
/// </summary>
[Parameter]
public bool Toggled { get; set; } = false;
/// <summary>
/// Glyph (Icon) inside the button.
/// Options: SVG string --> Icons
/// Default: string.Empty
/// </summary>
[Parameter, EditorRequired]
public string Glyph { get; set; } = string.Empty;
/// <summary>
/// Glyph (Icon) inside the button when tge .
/// Options: SVG string --> Icons
/// Default: string.Empty
/// </summary>
[Parameter, EditorRequired]
public string ToggledGlyph { get; set; } = string.Empty;
/// <summary>
/// Position of the glyph relative to button Text parameter. If Glyph parameter == string.Empty this parameter is ignored
/// Options: Position.[left,top,right,bottom]
/// Default: Position.left
/// </summary>
[Parameter]
public Position GlyphPosition { get; set; } = Position.Left;
/// <summary>
/// Color for the glyph. If Glyph parameter is empty this parameter is ignored
/// Options: Color.[Core,Primary,Secondary,Success,Info,Warning,Danger,White,Light,Dark]
/// Default: Color.Dark
/// </summary>
[Parameter]
public Color GlyphColor { get; set; } = Color.Dark;
/// <summary>
/// Color for the glyph. If Glyph parameter is empty this parameter is ignored
/// Options: Color.[Core,Primary,Secondary,Success,Info,Warning,Danger,White,Light,Dark]
/// Default: Color.Dark
/// </summary>
[Parameter]
public Color ToggledGlyphColor { get; set; } = Color.Dark;
#endregion
#region Events
/// <summary>
/// Button click event.
/// Options: any MouseEventCallback event
/// Default: empty
[Parameter]
public EventCallback<bool> ToggledChanged { get; set; }
protected async Task Clicked(MouseEventArgs e)
{
Toggled = !Toggled;
await ToggledChanged.InvokeAsync(Toggled);
}
#endregion
#region Styling
public string StyleList
{
get
{
return new StyleBuilder()
.AddStyle(base.Style)
.Build();
}
}
/// <summary>
/// Generated class list for button based on user parameters
/// </summary>
public string ClassList
{
get
{
return new CssBuilder("btn")
.AddClass("btn-" + Helper.GetEnumDescription<Size>(base.Size))
.AddClass("btn-" + Helper.GetEnumDescription<Color>(base.Color),!base.Outlined)
.AddClass("btn-outline-" + Helper.GetEnumDescription<Color>(base.Color), base.Outlined)
.AddClass(base.Class)
.Build();
}
}
/// <summary>
/// Generated class list for button based on user parameters
/// </summary>
public string ContentClassList
{
get
{
return new CssBuilder("")
.AddClass(base.ContentClass)
.Build();
}
}
#endregion
}

@ -0,0 +1,17 @@
@using Connected.Models;
@inherits InputBase;
<label class="toggle-group" for="@Id">
<input class="toggle-input"
type="checkbox"
name="toggle"
disabled="@Disabled"
id="@Id"
checked="@Checked"
@onchange="@OnChange"
@attributes=@InputAttributes>
<div class="toggle-fill"></div>
<label for="@Id" class="toggle-label">@Label</label>
</label>

@ -0,0 +1,27 @@
using Connected.Models;
using Microsoft.AspNetCore.Components;
namespace Connected.Components;
public partial class ToggleInput: InputBase
{
private bool _checked { get; set; }
[Parameter]
public bool? Checked
{
get => _checked;
set => _checked= (bool)value;
}
[Parameter, EditorRequired]
public string Id { get; set; }
[Parameter]
public EventCallback<bool> CheckedChanged { get; set; }
public async Task OnChange()
{
Checked = !Checked;
await CheckedChanged.InvokeAsync((bool)Checked);
}
}

@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Connected.Enums;
public enum ModalButtonType
{
OkButton,
CancelButton,
RegularButton
}

@ -0,0 +1,18 @@
using System.ComponentModel;
namespace Connected.Enums;
public enum Target
{
[Description("_top")]
Top,
[Description("_parent")]
Parent,
[Description("_blank")]
Blank,
[Description("_self")]
Self,
}

@ -30,16 +30,20 @@ public class InputBase : ComponentBase
[Parameter] [Parameter]
public bool Required { get; set; } = false; public bool Required { get; set; } = false;
public Dictionary<string, object> InputAttributes { get; set; } public Dictionary<string, object> InputAttributes { get; set; } = new();
/// <summary> /// <summary>
/// Show clear button. /// Disable input component
/// Options: true or false
/// Default: false
/// </summary> /// </summary>
[Parameter] [Parameter]
public bool Disabled { get; set; } = false; public bool Disabled { get; set; } = false;
/// <summary> /// <summary>
/// Show clear button. /// Make input component readonly
/// Options: true or false
/// Default: false
/// </summary> /// </summary>
[Parameter] [Parameter]
public bool Readonly { get; set; } = false; public bool Readonly { get; set; } = false;
@ -50,18 +54,11 @@ public class InputBase : ComponentBase
[Parameter] [Parameter]
public bool ShowCharacterCounter { get; set; } public bool ShowCharacterCounter { get; set; }
private string _errorText = string.Empty; /// <summary>
///
/// </summary>
[Parameter] [Parameter]
public string ErrorText { public string ErrorText { get; set; } = string.Empty;
get
{
return _errorText;
}
set
{
_errorText = value;
}
}
public bool IsError public bool IsError
{ {
@ -79,15 +76,16 @@ public class InputBase : ComponentBase
protected virtual async Task SetTextAsync(string text) protected virtual async Task SetTextAsync(string text)
{ {
if (Text != text) if (Text == text)
{ return;
Text = text; Text = text;
await TextChanged.InvokeAsync(text); await TextChanged.InvokeAsync(text);
} }
}
private string _helperText = string.Empty; private string _helperText = string.Empty;
[Parameter] [Parameter]
public string HelperText public string HelperText
{ {
@ -123,7 +121,7 @@ public class InputBase : ComponentBase
[Parameter] [Parameter]
public string Placeholder { get; set; } = string.Empty; public string Placeholder { get; set; } = string.Empty;
protected override async Task OnInitializedAsync() protected override void OnInitialized()
{ {
if (InputAttributes is null) InputAttributes = new(); if (InputAttributes is null) InputAttributes = new();
} }

@ -0,0 +1,36 @@
using Connected.Enums;
using Connected.Services;
namespace Connected.Models.Modal;
public class ModalButton
{
public Event OnClickEvent { get; set; }
public ModalButtonType ModalButtonType { get; set; } = ModalButtonType.RegularButton;
public string ButtonText { get; set; }
public bool CloseDialogOnClick { get; set; } = true;
public ModalButton(Event OnClickEvent, string ButtonText, ModalButtonType ModalButtonType = ModalButtonType.RegularButton, bool CloseDialogOnClick = true)
{
this.OnClickEvent = OnClickEvent;
this.ButtonText = ButtonText;
this.ModalButtonType= ModalButtonType;
this.CloseDialogOnClick = CloseDialogOnClick;
}
public string GetButtonClass
{
get
{
switch (this.ModalButtonType)
{
case ModalButtonType.CancelButton:
return "btn-sm btn-core";
case ModalButtonType.OkButton:
return "btn-sm btn-info";
default:
return "btn-sm btn-secondary";
}
}
}
}

@ -0,0 +1,12 @@
namespace Connected.Models.Modal;
public class Event
{
public Delegate Delegate;
public object[] args;
public Event(Delegate Delegate, object[] Args)
{
this.Delegate = Delegate;
args = Args;
}
}

@ -0,0 +1,10 @@
namespace Connected.Models.Modal;
public class ModalOptions
{
public bool DisableEscKey { get; set; } = false;
public bool DisableBackdropClick { get; set; } = false;
public bool NoHeader { get; set; } = false;
}

@ -1,4 +1,6 @@
using Microsoft.AspNetCore.Components; using Connected.Enums;
using Connected.Utilities;
using Microsoft.AspNetCore.Components;
using Microsoft.JSInterop; using Microsoft.JSInterop;
namespace Connected; namespace Connected;
@ -24,8 +26,9 @@ internal class Navigation
/// Navigates to the specified url. /// Navigates to the specified url.
/// </summary> /// </summary>
/// <param name="url">The destination url (relative or absolute).</param> /// <param name="url">The destination url (relative or absolute).</param>
public async Task NavigateTo(string url, Target target=Target._self) public async Task NavigateTo(string url, Target t=Target.Self)
{ {
string target = Helper.GetEnumDescription<Target>(t);
if (!target.Equals("_self")) if (!target.Equals("_self"))
{ {
if (!url.Equals(_navigationManager.Uri)) if (!url.Equals(_navigationManager.Uri))
@ -110,10 +113,4 @@ internal class Navigation
} }
} }
enum Target
{
_self,
_blank,
_parent,
_top
}

@ -0,0 +1,28 @@
using Connected.Components;
using Connected.Models.Modal;
using Microsoft.AspNetCore.Components;
namespace Connected.Services;
public class ModalDialogService
{
public event Action<string, RenderFragment, List<ModalButton>, ModalOptions> OnShow;
public event Action OnClose;
public void ShowDialog(string title, RenderFragment content, List<ModalButton> buttons, ModalOptions options)
{
OnShow?.Invoke(title, content, buttons, options);
}
public void ShowDialog(string title, MarkupString contentMarkup, List<ModalButton> buttons, ModalOptions options)
{
var content = new RenderFragment(x => x.AddContent(1, contentMarkup));
OnShow?.Invoke(title, content, buttons, options);
}
public void Close()
{
OnClose?.Invoke();
}
}

@ -0,0 +1,9 @@
using Microsoft.Extensions.DependencyInjection;
namespace Connected.Services;
public static class ServiceCollectionExtensions
{
public static IServiceCollection AddModalDialogService(this IServiceCollection services)
=> services.AddScoped<ModalDialogService>();
}

@ -1,4 +1,4 @@
@import 'globals/_index'; @forward 'globals';
@import 'layout/_index'; @forward 'layout';
@import 'components/_index'; @forward 'components';
@import 'util/_index'; @forward 'util';

@ -12,12 +12,12 @@
user-select: none; user-select: none;
background-color: $bg-color; background-color: $bg-color;
border: 1px solid transparent; border: 1px solid transparent;
padding: 0.375rem 1rem; padding: 0.3rem 1.35rem;
font-size: $base-font-size; font-size: $base-font-size;
text-transform: uppercase; text-transform: uppercase;
line-height: $base-font-size * 1.5; line-height: $base-font-size * 1.5;
text-decoration: none; text-decoration: none;
border-radius: $base-border-radius * 20; border-radius: $border-radius-pill;
transition: $transition; transition: $transition;
} }
@ -46,12 +46,12 @@
} }
.btn-outline-#{$key} { .btn-outline-#{$key} {
// @include btn(); // @include btn();
color: $val;
background-color: transparent;
border: 1px solid $val;
&:hover {
color: darken($val, 10); color: darken($val, 10);
background-color: transparent;
border: 1px solid darken($val, 10); border: 1px solid darken($val, 10);
&:hover {
color: darken($val, 30);
border: 1px solid darken($val, 30);
} }
&:focus-visible, &:focus-visible,
&.focus { &.focus {
@ -67,24 +67,24 @@
} }
.btn.btn-sm { .btn.btn-sm {
font-size: $font-size-sm; font-size: .75rem;
line-height: $font-size-sm * 1.5; line-height: $font-size-sm * 1.25;
padding: 0.25rem 0.75rem; padding: 0.4rem 1rem;
border-radius: $base-border-radius; //border-radius: $base-border-radius;
} }
.btn.btn-lg { .btn.btn-lg {
font-size: $font-size-md; font-size: $font-size-md;
line-height: $font-size-md * 1.5; line-height: $font-size-md * 1.5;
padding: 0.5rem 1.25rem; padding: 0.5rem 1.65rem;
border-radius: $base-border-radius * 2.5; //border-radius: $base-border-radius * 2.5;
} }
.btn.btn-block { .btn.btn-block {
font-size: $font-size-md; font-size: $font-size-md;
line-height: $font-size-md * 1.5; line-height: $font-size-md * 1.5;
padding: 0.5rem 1.25rem; padding: 0.5rem 1.5rem;
border-radius: $base-border-radius * 2.5; //border-radius: $base-border-radius * 2.5;
display: block; display: block;
width: 100%; width: 100%;
} }
@ -114,12 +114,12 @@
} }
.btn-outline-core { .btn-outline-core {
color: var(--bg-core-primary) !important;
background-color: transparent !important;
border: 1px solid var(--bg-core-primary) !important;
&:hover {
color: var(--bg-core-primary-darken) !important; color: var(--bg-core-primary-darken) !important;
background-color: transparent !important;
border: 1px solid var(--bg-core-primary-darken) !important; border: 1px solid var(--bg-core-primary-darken) !important;
&:hover {
color: var(--bg-core-primary-dark) !important;
border: 1px solid var(--bg-core-primary-dark) !important;
} }
&:focus-visible, &:focus-visible,
&.focus { &.focus {

@ -1,102 +1,188 @@
$color3: #f4f4f4; $checkbox-primary-color: var(--bg-core-primary-darken);
$color4: var(--bg-core-primary-darken); $checkbox-secondary-color: #f4f4f4;
$checkbox-disabled-color: darken($checkbox-secondary-color, 25%);
.checkbox-group { .checkbox-group {
margin: 0.5rem; --width: 1.25rem;
position:relative; --height: var(--width);
input[type="checkbox"] { --inset: calc(var(--width) / 10);
position: absolute;
opacity: 0;
+ .checkbox-label { margin: 0.75rem 0;
&:before { width: max-content;
content: "";
background: transparent;
border-radius: 0%;
border: 2px solid $color4;
display: inline-block;
width: 1.25em;
height: 1.25em;
position: relative;
top: .15rem;
margin-right: .75em;
vertical-align: top;
cursor: pointer; cursor: pointer;
text-align: center; position:relative;
display: flex;
align-items: center;
gap:.75rem;
z-index: 1; z-index: 1;
transition: all 250ms ease;
} &.reversed{
justify-content: space-between;
width: 100%;
& :nth-child(1) {order:2;}
& :nth-child(2) {order:1;}
} }
&:checked {
+ .checkbox-label {
&:before {
background-color: $color4;
box-shadow: inset 0 0 0 2px $color3;
&.column{
flex-direction: column;
gap:.25rem;
width: 100%;
} }
input[type="checkbox"] {
position: absolute;
opacity: 0;
} }
} }
// &:checked {
// + .checkbox-label {
// &:after {
// background: $color3;
// z-index: 1;
// opacity: 1;
// scale: 0.25;
// clip-path: polygon(14% 44%, 0 65%, 50% 100%, 100% 16%, 80% 0%, 43% 62%);
// } .checkbox-fill {
// } position: relative;
// } display: inline-block;
&:focus { width: var(--width);
+ .checkbox-label { height: var(--height);
&:before { background: transperent;
outline: none; border: 2px solid $checkbox-primary-color;
border-color: $color4; transition: background 0.2s ease-in-out;
} }
.checkbox-input:checked ~ .checkbox-fill {
background: var(--bg-core-primary-darken);
box-shadow: inset 0 0 0 var(--inset) $checkbox-secondary-color;
} }
.checkbox-input:focus-within ~ .checkbox-fill {
outline: 1px solid $checkbox-primary-color;
} }
&:disabled {
+ .checkbox-label { .checkbox-input:disabled ~ .checkbox-fill {
color: darken($color3, 25%); box-shadow: inset 0 0 0 var(--inset) $checkbox-secondary-color;
border-color: $checkbox-disabled-color;
background: $checkbox-disabled-color;
pointer-events: none; pointer-events: none;
&:before {
box-shadow: inset 0 0 0 2px $color3;
border-color: darken($color3, 25%);
background: darken($color3, 25%);
}
}
}
+ .checkbox-label {
&:empty {
&:before {
margin-right: 0;
}
}
}
} }
.checkbox-input:disabled ~ .checkbox-label {
color: $checkbox-disabled-color;
} }
.checkbox-label:after {
.checkbox-fill::before {
content: ""; content: "";
display: inline-block; display: inline-block;
width: 35px; width: calc(var(--width) * 1.8);
height: 35px; height: calc(var(--width) * 1.8);
border-radius: 50%; border-radius: 50%;
background-color: transparent; background-color: transparent;
position: absolute; position: absolute;
left: -8px; z-index: -1;
top: -6px; left: 50%;
top: 50%;
transform: translate(-50%, -50%);
scale: .75; scale: .75;
transition: scale 0.35s cubic-bezier(0.6,-1.25,0.6,2.25); transform-origin: left top;
transition: scale 0.35s cubic-bezier(0.6,-1.25,0.6,2.25), transform 0.2s;
} }
.checkbox-fill:hover::before {
.checkbox-label:hover:after {
background: var(--bg-core-primary-lighten); background: var(--bg-core-primary-lighten);
scale: 1; scale: 1;
opacity: .5; opacity: .5;
} }
// $checkbox-primary-color: var(--bg-core-primary-darken);
// $checkbox-secondary-color: #f4f4f4;
// $checkbox-disabled-color: darken($checkbox-secondary-color, 25%);
// .checkbox-group {
// margin: 0.5rem;
// position:relative;
// input[type="checkbox"] {
// position: absolute;
// opacity: 0;
// + .checkbox-label {
// &:before {
// content: "";
// background: transparent;
// border: 2px solid $checkbox-primary-color;
// display: inline-block;
// width: 1.25em;
// height: 1.25em;
// position: relative;
// top: .15rem;
// margin-right: .75em;
// vertical-align: top;
// cursor: pointer;
// text-align: center;
// z-index: 1;
// transition: all 250ms ease;
// }
// }
// &:checked {
// + .checkbox-label {
// &:before {
// background-color: $checkbox-primary-color;
// box-shadow: inset 0 0 0 2px $checkbox-secondary-color;
// }
// }
// }
// &:focus {
// + .checkbox-label {
// &:before {
// outline: 1px solid $checkbox-primary-color;
// border-color: $checkbox-primary-color;
// }
// }
// }
// &:disabled {
// + .checkbox-label {
// color: darken($checkbox-secondary-color, 25%);
// pointer-events: none;
// &:before {
// box-shadow: inset 0 0 0 2px $checkbox-secondary-color;
// border-color: $checkbox-disabled-color;
// background: $checkbox-disabled-color;
// }
// }
// }
// + .checkbox-label {
// &:empty {
// &:before {
// margin-right: 0;
// }
// }
// }
// }
// }
// .checkbox-label:after {
// content: "";
// display: inline-block;
// width: 35px;
// height: 35px;
// border-radius: 50%;
// background-color: transparent;
// position: absolute;
// left: -8px;
// top: -6px;
// scale: .75;
// transition: scale 0.35s cubic-bezier(0.6,-1.25,0.6,2.25);
// }
// .checkbox-label:hover:after {
// background: var(--bg-core-primary-lighten);
// scale: 1;
// opacity: .5;
// }

@ -0,0 +1,218 @@
@use "../util" as *;
@use "../globals" as *;
/*CHIP*/
/* scroll container */
.horizontal-scroll-container {
display: flex;
position: relative;
flex-wrap: nowrap;
gap: .5rem;
overflow: auto;
scroll-snap-type: both mandatory;
}
/* Hide scrollbar for Chrome, Safari and Opera */
.horizontal-scroll-container::-webkit-scrollbar {
display: none;
}
/* Hide scrollbar for IE, Edge and Firefox */
.horizontal-scroll-container {
-ms-overflow-style: none; /* IE and Edge */
scrollbar-width: none; /* Firefox */
}
.chip-icon {
--height: 2.5rem;
height: var(--height);
aspect-ratio: 1 / 1;
display: flex;
flex: 1 0 auto;
align-items: center;
justify-content: center;
border-radius: 50%;
background-color: var(--bg-core-primary-darken);
overflow: hidden;
cursor: pointer;
transition: all 0.35s cubic-bezier(0.6,-1.25,0.6,2.25);
}
.chip-icon:hover,
.chip-icon:active,
.chip-icon:active {
background-color: var(--bg-core-primary-dark);
}
.chip-icon.float-left {
float: left;
margin: .05rem .5rem .15rem 0;
margin-top: -.25rem;
clear: both;
}
.chip-group {
--height: 1.5rem;
border: 1px solid var(--bg-core-primary);
padding: .15rem;
min-width: max-content;
color: var(--text-core);
border-radius: $border-radius-pill;
background-color: var(--bg-core-primary-light);
display: inline-block;
position:relative;
scroll-snap-align: start;
}
.chip-group-content{
height: var(--height);
display: flex;
align-items: center;
justify-content: center;
}
.chip-leading-icon {
display: flex;
align-items: center;
justify-content: center;
border-radius: $border-radius-pill;
background-color: var(--bg-core-primary-light);
height: var(--height);
aspect-ratio: 1 / 1;
overflow: hidden;
}
.chip-leading-icon img{
object-fit: cover;
height: var(--height);
aspect-ratio: 1 / 1;
}
.chip-cta-icon{
display: flex;
align-items: center;
justify-content: center;
border-radius: $border-radius-pill;
background-color: transparent;
cursor: pointer;
height: var(--height);
aspect-ratio: 1 / 1;
transition: all 0.35s cubic-bezier(0.6,-1.25,0.6,2.25);
}
.chip-label{
font-size: $font-size-sm;
margin:0 .85rem;
}
.chip-cta-icon:hover{
background-color: var(--bg-core-primary-lighten);
}
/*filter*/
.chip-group.filter {
border: 1px solid var(--bg-core-primary);
background-color: var(--bg-core-primary-light);
cursor: pointer;
overflow: hidden;
&:hover{
background-color: var(--bg-core-primary-lighten);
}
&:active,
&.active{
border: 1px solid var(--bg-core-primary);
background-color: var(--bg-core-primary);
}
}
.chip-group.filter .chip-leading-icon{
//display: none;
max-width: 0;
transform: translateX(calc(var(--height) * -1.25));
transition: all 0.35s cubic-bezier(0.6,-1.25,0.6,2.25);
}
.chip-group.filter.active .chip-leading-icon{
display: flex;
align-items: center;
justify-content: center;
border-radius: $border-radius-pill;
background-color: var(--bg-core-primary-light);
height: var(--height);
aspect-ratio: 1 / 1;
transform: translateX(0);
max-width: var(--height);
}
.chip-group.select .chip-cta-icon{
display: none;
}
/*end select*/
/*drop-down*/
/* The container must be positioned relative: */
.custom-select {
position: relative;
font-family: Arial;
}
.custom-select select {
display: none; /*hide original SELECT element: */
}
.select-selected {
background-color: DodgerBlue;
}
/* Style the arrow inside the select element: */
.select-selected:after {
position: absolute;
content: "";
top: 14px;
right: 10px;
width: 0;
height: 0;
border: 6px solid transparent;
border-color: #fff transparent transparent transparent;
}
/* Point the arrow upwards when the select box is open (active): */
.select-selected.select-arrow-active:after {
border-color: transparent transparent #fff transparent;
top: 7px;
}
/* style the items (options), including the selected item: */
.select-items div,.select-selected {
color: #ffffff;
padding: 8px 16px;
border: 1px solid transparent;
border-color: transparent transparent rgba(0, 0, 0, 0.1) transparent;
cursor: pointer;
}
/* Style items (options): */
.select-items {
position: absolute;
background-color: DodgerBlue;
top: 100%;
left: 0;
right: 0;
z-index: 99;
}
/* Hide the items when the select box is closed: */
.select-hide {
display: none;
}
.select-items div:hover, .same-as-selected {
background-color: rgba(0, 0, 0, 0.1);
}
/*end-down*/
/*END CHIP*/

@ -1,3 +1,5 @@
@use "sass:math";
@use "../util" as *; @use "../util" as *;
@use "../globals" as *; @use "../globals" as *;
@ -102,3 +104,250 @@ $colspan: ("1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12");
} }
} }
} }
/*DATA GRID*/
$columns: 12;
@mixin create-selectors($breakpoint: null) {
$infix: if($breakpoint == null, '', '-#{$breakpoint}');
@for $i from 1 through $columns {
.col#{$infix}-#{$i} {
grid-column-end: span $i;
padding: $base-padding;
}
.col-offset#{$infix}-#{$i} {
grid-column-start: $i + 1;
}
.row#{$infix}-#{$i} {
grid-row-end: span $i;
}
.row-offset#{$infix}-#{$i} {
grid-row-start: $i + 1;
}
}
}
.row{
display: grid;
grid-template-columns: repeat($columns, 1fr);
position: relative;
}
@include create-selectors;
@each $breakpoint, $width in $breakpoints-up {
@media (min-width: $width) {
@include create-selectors($breakpoint);
}
}
.data-grid-row-content{
display: grid;
grid-template-columns: auto 1fr auto;
}
.data-grid:not(.data-grid.dense) .data-grid-row-content {
background-color: var(--element-bg-core);
border: 1px solid var(--border-core);
border-radius: $border-radius-lg;
padding: 1rem 1.25rem;
margin-bottom: 1rem;
position: relative;
overflow: hidden;
&:last-child{
margin-bottom: 0;
}
}
/*ACTIVE*/
.data-grid:not(.data-grid.dense) .data-grid-row-content:before {
content: "";
position: absolute;
width: 0;
inset:0;
background: var(--bg-core-primary-lighten);
transition: width 300ms ease-in-out;
}
.data-grid:not(.data-grid.dense) .data-grid-row-content.active:before {
width: calc(100% + 1.25rem * 2);
}
/*END ACTIVE*/
.data-grid.dense {
background-color: var(--element-bg-core);
border: 1px solid var(--border-core);
border-radius: $border-radius-lg;
padding: 1rem 1.25rem;
margin-bottom: 1rem;
overflow: hidden;
&:last-child{
margin-bottom: 0;
}
}
/*DENSE*/
.data-grid.dense .data-grid-row-content {
border-bottom: 1px solid var(--border-core);
padding-bottom: .5rem;
margin-bottom: .5rem;
position: relative;
&:last-child{
border-bottom: 0;
padding-bottom: 0;
margin-bottom: 0
}
}
/*END DENSE*/
/*DENSE ACTIVE*/
.data-grid.dense .data-grid-row-content:before {
content: "";
position: absolute;
width: 0;
inset: -.55rem -1.25rem -1px;
background: var(--bg-core-primary-lighten);
transition: width 300ms ease-in-out;
}
.data-grid.dense .data-grid-row-content.active:before {
width: calc(100% + 1.25rem * 2);
}
.data-grid.dense .data-grid-row-content:first-child:before {
top: -1rem;
bottom: -1px;
}
.data-grid.dense .data-grid-row-content:last-child:before {
top: -10px;
bottom: -1rem;
}
.data-grid.dense .data-grid-row-content:only-child:before {
inset: -1rem -1.25rem ;
}
/*END DENSE ACTIVE*/
.data-grid.select .data-grid-select {
display: block;
margin-top: .5rem;
margin-right: .5rem;
}
.data-grid .data-grid-select,
.data-grid .data-grid-collapse-cta{
display: none;
}
.data-grid label {
font-size: $font-size-sm;
color: $text-core-lc;
}
/*COLLAPSE*/
.data-grid.collapse .data-grid-collapse-cta {
display: block;
margin-top: .5rem;
margin-left: .5rem;
cursor: pointer;
}
.collapsed{
max-height: 0;
overflow: hidden;
padding-top: 0!important;
padding-bottom: 0!important;
border-top: 0px solid transparent;
//opacity: 0;
transition: all 0.5s ease-out;
}
.collapsed.show {
max-height: 25vh;
overflow: auto;
padding-top: initial;
padding-bottom: initial;
border-top: 1px solid var(--bg-core-primary-light);
//opacity: 1;
transition: all 0.5s ease-in;
}
.data-grid .data-grid-collapse-cta i {
transform: rotate(0);
transition: all 0.5s ease-in;
}
.data-grid.show .data-grid-collapse-cta i {
transform: rotate(180deg);
}
/*form-wizard*/
.form-wizard {
background-color: var(--element-bg-core);
border: 1px solid var(--border-core);
border-radius: 0.6rem;
padding: 1rem 1.25rem;
position: relative;
}
.form-outer {
display: flex;
flex-wrap: nowrap;
overflow: hidden;
}
.form-step {
width: 100%;
flex: 1 0 auto;
transition: all 0.5s ease-out;
transform: translateX(0);
}
.form-step.next{
transform: translateX(-100%);
}
.form-step.previous{
transform: translateX(100%);
}
.dots {
--width: .75rem;
--height: var(--width);
position: absolute;
bottom: calc(var(--width) / -2);
left: 50%;
transform: translateX(-50%);
.dot {
width: var(--width);
height: var(--height);
border-radius: 50%;
background-color: var(--bg-core-primary-lighten);
display: inline-block;
outline: 1px solid #fff;
transition: all 300ms ease-in-out;
}
.dot.active,
.dot.next {
background-color: var(--bg-core-primary);
outline: 2px solid var(--bg-core-primary);
outline-offset: 2px;
}
.dot.completed {
background-color: $success;
}
}
/*end form-wizard*/

@ -4,3 +4,6 @@
@forward "radio"; @forward "radio";
@forward "inputs"; @forward "inputs";
@forward "checkbox"; @forward "checkbox";
@forward "toggle";
@forward "chip";
@forward "modal";

@ -10,7 +10,7 @@ $width: 100%;
form{ form{
display: block; display: block;
margin-top: 1rem; //padding-top: 1rem;
} }
.form-group{ .form-group{
@ -36,12 +36,13 @@ form{
width: 100%; width: 100%;
border: none; border: none;
border-radius: 0; border-radius: 0;
border-bottom: 1px solid $border-core; border-bottom: 1px solid var(--border-core);
&:focus { &:focus {
outline: none; outline: none;
} }
&:focus ~ label.label-animated, &:focus ~ label.label-animated,
&:valid ~ label.label-animated { &:valid ~ label.label-animated,
&:disabled ~ label.label-animated {
top: -12px; top: -12px;
font-size: $font-size-sm; font-size: $font-size-sm;
color: var(--bg-core-primary-darken); color: var(--bg-core-primary-darken);
@ -204,29 +205,69 @@ select {
height: auto; height: auto;
max-height: max-content; max-height: max-content;
opacity: 1; opacity: 1;
transition: all $trans-time ease-in-out; pointer-events: initial;
}
&:focus-within ~ .backdrop {
opacity: 1;
display: block;
} }
} }
.drop-down{ .drop-down{
position: absolute; position: fixed;
opacity: 0; top: 50%;
display: flex; left: 50%;
flex-direction: column; transform: translate(-50%, -50%);
top: 46px; min-width: 80%;
left: 0; width: 80%;
min-width: 100%;
height: 0; height: 0;
max-height: 0; max-height: 0;
//padding: $base-padding; display: flex;
flex-direction: column;
opacity: 0;
pointer-events: none;
z-index: 1500; z-index: 1500;
list-style: none; list-style: none;
background-color: #fff; background-color: #fff;
box-shadow: $base-box-shadow; box-shadow: $base-box-shadow;
border-radius: $border-radius-lg;
transition: all $trans-time ease-in-out;
}
.backdrop{
display: none;
opacity: 0;
z-index: 1499;
position: fixed;
top: 0;
right:0;
bottom:0;
left:0;
overflow: hidden;
background-color: rgba(0,0,0,.5);
transition: all $trans-time ease-in-out;
}
@include breakpoint(sm) {
.drop-down{
position: absolute;
top: 46px;
left: 0;
opacity: 0;
min-width: 100%;
width: 100%;
transform: none;
border-radius: 0 0 $border-radius-lg $border-radius-lg; border-radius: 0 0 $border-radius-lg $border-radius-lg;
} }
}
.dropdown-header { .dropdown-header {
@ -253,12 +294,12 @@ select {
.dropdown-item:focus, .dropdown-item:hover { .dropdown-item:focus, .dropdown-item:hover {
color: var(--text-core-hc); color: var(--text-core-hc);
text-decoration: none; text-decoration: none;
background-color: var(--bg-core-primary-lighten); background-color: var(--bg-core-primary-light);
} }
.dropdown-divider { .dropdown-divider {
height: 0; height: 0;
margin: 0.5rem 0; margin: 0.5rem 0;
overflow: hidden; overflow: hidden;
border-top: 1px solid $border-core; border-top: 1px solid var(--bg-core-primary-light);
} }

@ -0,0 +1,229 @@
@use "../util" as *;
@use "../globals" as *;
// stylelint-disable function-disallowed-list
// .modal-open - body class for killing the scroll
.scroll-disabled{
overflow: hidden;
padding-right: 0;
}
// .modal - container to scroll within
// .modal-dialog - positioning shell for the actual modal
// .modal-content - actual modal w/ bg and corners and stuff
// Container that the modal scrolls within
.modal {
--modal-zindex: #{$modal-zindex};
--modal-width: 60vw;
--modal-height: 50vh;
--modal-padding: 1.5rem;
--modal-margin: 1.5rem;
--modal-color: var(--text-core);
--modal-bg: var(--bg-core-primary-light);
--modal-border-color: var(--bg-core-primary-light);
--modal-border-width: 1px;
--modal-border-radius: 1rem;
--modal-box-shadow: 0 0.5rem 1rem rgba(var(--bg-core-primary), 0.15);
--modal-header-padding-x: 1.5rem; //close button
--modal-header-padding-y: 1.5rem; //close button
--modal-header-bg: var(--modal-bg);
--modal-header-padding: 1.5rem;
--modal-header-border-color: var(--bg-core-primary-light);
--modal-header-border-width: 1px;
--modal-footer-bg: var(--modal-bg);
--modal-footer-padding: 1.5rem;
--modal-footer-border-color: var(--bg-core-primary-light);
--modal-footer-border-width: 1px;
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
background-color: rgba(0,0,0,.65);
z-index: var(--modal-zindex);
display: none;
opacity: 0;
width: 100%;
height: 100%;
overflow-x: hidden;
overflow-y: auto;
transition: opacity .15s linear;
// Prevent Chrome on Windows from adding a focus outline. For details, see
// https://github.com/twbs/bootstrap/pull/10951.
outline: 0;
// We deliberately don't use `-webkit-overflow-scrolling: touch;` due to a
// gnarly iOS Safari bug: https://bugs.webkit.org/show_bug.cgi?id=158342
// See also https://github.com/twbs/bootstrap/issues/17695
}
// When fading in the modal, animate it to slide down
.modal.fade {
opacity: 1;
transition: opacity .15s linear;
}
.modal.show{
display: block;
}
// When trying to close, animate focus to scale
.modal.modal-static {
transform:scale(1.1);
}
// Shell div to position the modal with bottom padding
.modal-dialog {
position: relative;
width: auto;
margin: var(--modal-margin);
// allow clicks to pass through for custom click handling to close modal
pointer-events: none;
}
.modal-dialog-scrollable {
height: calc(100% - var(--modal-margin) * 2);
.modal-content {
max-height: 100%;
overflow: hidden;
}
.modal-body {
overflow-y: auto;
}
}
.modal-dialog-centered {
display: flex;
align-items: center;
min-height: calc(100% - var(--modal-margin) * 2);
}
// Actual modal
.modal-content {
position: relative;
display: flex;
flex-direction: column;
width: 100%; // Ensure `.modal-content` extends the full width of the parent `.modal-dialog`
// counteract the pointer-events: none; in the .modal-dialog
color: var(--modal-color);
pointer-events: auto;
background-color: var(--modal-bg);
background-clip: padding-box;
border: var(--modal-border-width) solid var(--modal-border-color);
border-radius: var(--modal-border-radius);
box-shadow: var(--modal-box-shadow);
// Remove focus outline from opened modal
outline: 0;
}
// Modal header
// Top section of the modal w/ title and dismiss
.modal-header {
display: flex;
flex-shrink: 0;
align-items: center;
justify-content: space-between; // Put modal header elements (title and dismiss) on opposite ends
padding: var(--modal-header-padding);
background-color: var(--modal-header-bg);
border-bottom: var(--modal-header-border-width) solid var(--modal-header-border-color);
.btn-close {
padding: calc(var(--modal-header-padding-y) * .5) calc(var(--modal-header-padding-x) * .5);
margin: calc(-.5 * var(--modal-header-padding-y)) calc(-.5 * var(--modal-header-padding-x)) calc(-.5 * var(--modal-header-padding-y)) auto;
}
}
// Title text within header
.modal-title {
margin-bottom: 0;
}
// Modal body
// Where all modal content resides (sibling of .modal-header and .modal-footer)
.modal-body {
position: relative;
// Enable `flex-grow: 1` so that the body take up as much space as possible
// when there should be a fixed height on `.modal-dialog`.
flex: 1 1 auto;
padding: var(--modal-padding);
}
// Footer (for actions)
.modal-footer {
display: flex;
flex-shrink: 0;
flex-wrap: wrap;
align-items: center; // vertically center
justify-content: flex-end; // Right align buttons with flex property because text-align doesn't work on flex items
padding: var(--modal-footer-padding);
background-color: var(--modal-footer-bg);
border-radius: var(--modal-border-radius);
gap: .5rem;
}
// Automatically set modal's width for larger viewports
.modal-dialog {
max-width: 100%;
max-height: 100%;
padding: 0;
@include breakpoint(sm) {
max-width: 75vw;
margin-right: auto;
margin-left: auto;
padding: var(--modal-padding);
}
@include breakpoint(lg) {
max-width: var(--modal-width);
margin-right: auto;
margin-left: auto;
}
}
// // Modal background
// .modal-backdrop {
// opacity: 0;
// display: none;
// position: fixed;
// top: 0;
// left: 0;
// z-index: #{$backdrop-zindex};
// width: 100vw;
// height: 100vh;
// background-color: #000;
// transition: opacity .15s linear;
// }
// .modal-backdrop.fade {
// opacity: .5;
// transition: opacity .15s linear;
// }
// .modal-backdrop.show {
// display: block;
// }

@ -1,86 +1,276 @@
$color1: #f4f4f4; $radio-primary-color: var(--bg-core-primary-darken);
$color2: var(--bg-core-primary-darken); $radio-secondary-color: #f4f4f4;
$radio-disabled-color: darken($radio-secondary-color, 25%);
.radio-group { .radio-group {
margin: 0.5rem; --width: 1.25rem;
position:relative; --height: var(--width);
input[type="radio"] { --inset: calc(var(--width) / 10);
position: absolute;
opacity: 0; margin: 0.75rem 0;
+ .radio-label { width: max-content;
&:before {
content: "";
background: $color1;
border-radius: 100%;
border: 2px solid $color2;
display: inline-block;
width: 1.25em;
height: 1.25em;
position: relative;
top: .15rem;
margin-right: .75em;
vertical-align: top;
cursor: pointer; cursor: pointer;
text-align: center; position:relative;
display: flex;
align-items: center;
gap:.75rem;
z-index: 1; z-index: 1;
transition: all 250ms ease;
} &.reversed{
justify-content: space-between;
width: 100%;
& :nth-child(1) {order:2;}
& :nth-child(2) {order:1;}
} }
&:checked {
+ .radio-label { &.column{
&:before { flex-direction: column;
background-color: $color2; gap:.25rem;
box-shadow: inset 0 0 0 2px $color1; width: 100%;
} }
input[type="radio"] {
position: absolute;
opacity: 0;
} }
} }
&:focus {
+ .radio-label { .radio-fill {
&:before { position: relative;
outline: none; display: inline-block;
border-color: $color2; width: var(--width);
height: var(--height);
border-radius: 50%;
background: transperent;
border: 2px solid $radio-primary-color;
transition: background 0.2s ease-in-out;
} }
.radio-input:checked ~ .radio-fill {
background: var(--bg-core-primary-darken);
box-shadow: inset 0 0 0 var(--inset) $radio-secondary-color;
} }
.radio-input:focus-within ~ .radio-fill {
outline: 1px solid $radio-primary-color;
} }
&:disabled {
+ .radio-label { .radio-input:disabled ~ .radio-fill {
color: darken($color1, 25%); box-shadow: inset 0 0 0 var(--inset) $radio-secondary-color;
border-color: $radio-disabled-color;
background: $radio-disabled-color;
pointer-events: none; pointer-events: none;
&:before {
box-shadow: inset 0 0 0 2px $color1;
border-color: darken($color1, 25%);
background: darken($color1, 25%);
}
}
}
+ .radio-label {
&:empty {
&:before {
margin-right: 0;
}
}
}
} }
.radio-input:disabled ~ .radio-label {
color: $radio-disabled-color;
} }
.radio-label:after {
.radio-fill::before {
content: ""; content: "";
display: inline-block; display: inline-block;
width: 35px; width: calc(var(--width) * 1.8);
height: 35px; height: calc(var(--width) * 1.8);
border-radius: 50%; border-radius: 50%;
background-color: transparent; background-color: transparent;
position: absolute; position: absolute;
left: -8px; z-index: -1;
top: -6px; left: 50%;
top: 50%;
transform: translate(-50%, -50%);
scale: .75; scale: .75;
transition: scale 0.35s cubic-bezier(0.6,-1.25,0.6,2.25); transform-origin: left top;
transition: scale 0.35s cubic-bezier(0.6,-1.25,0.6,2.25), transform 0.2s;
} }
.radio-label:hover:after { .radio-fill:hover::before {
background: var(--bg-core-primary-lighten); background: var(--bg-core-primary-lighten);
scale: 1; scale: 1;
opacity: .5; opacity: .5;
} }
// $checkbox-primary-color: var(--bg-core-primary-darken);
// $checkbox-secondary-color: #f4f4f4;
// $checkbox-disabled-color: darken($checkbox-secondary-color, 25%);
// .checkbox-group {
// margin: 0.5rem;
// position:relative;
// input[type="checkbox"] {
// position: absolute;
// opacity: 0;
// + .checkbox-label {
// &:before {
// content: "";
// background: transparent;
// border: 2px solid $checkbox-primary-color;
// display: inline-block;
// width: 1.25em;
// height: 1.25em;
// position: relative;
// top: .15rem;
// margin-right: .75em;
// vertical-align: top;
// cursor: pointer;
// text-align: center;
// z-index: 1;
// transition: all 250ms ease;
// }
// }
// &:checked {
// + .checkbox-label {
// &:before {
// background-color: $checkbox-primary-color;
// box-shadow: inset 0 0 0 2px $checkbox-secondary-color;
// }
// }
// }
// &:focus {
// + .checkbox-label {
// &:before {
// outline: 1px solid $checkbox-primary-color;
// border-color: $checkbox-primary-color;
// }
// }
// }
// &:disabled {
// + .checkbox-label {
// color: darken($checkbox-secondary-color, 25%);
// pointer-events: none;
// &:before {
// box-shadow: inset 0 0 0 2px $checkbox-secondary-color;
// border-color: $checkbox-disabled-color;
// background: $checkbox-disabled-color;
// }
// }
// }
// + .checkbox-label {
// &:empty {
// &:before {
// margin-right: 0;
// }
// }
// }
// }
// }
// .checkbox-label:after {
// content: "";
// display: inline-block;
// width: 35px;
// height: 35px;
// border-radius: 50%;
// background-color: transparent;
// position: absolute;
// left: -8px;
// top: -6px;
// scale: .75;
// transition: scale 0.35s cubic-bezier(0.6,-1.25,0.6,2.25);
// }
// .checkbox-label:hover:after {
// background: var(--bg-core-primary-lighten);
// scale: 1;
// opacity: .5;
// }
// $radio-primary-color: var(--bg-core-primary-darken);
// $radio-secondary-color: #f4f4f4;
// $radio-disabled-color: darken($radio-secondary-color, 25%);
// .radio-group {
// margin: 0.5rem;
// position:relative;
// input[type="radio"] {
// position: absolute;
// opacity: 0;
// + .radio-label {
// &:before {
// content: "";
// background: transparent;
// border-radius: 50%;
// border: 2px solid $radio-primary-color;
// display: inline-block;
// width: 1.25em;
// height: 1.25em;
// position: relative;
// top: .15rem;
// margin-right: .75em;
// vertical-align: top;
// cursor: pointer;
// text-align: center;
// z-index: 1;
// transition: all 250ms ease;
// }
// }
// &:checked {
// + .radio-label {
// &:before {
// background-color: $radio-primary-color;
// box-shadow: inset 0 0 0 2px $radio-secondary-color;
// }
// }
// }
// &:focus {
// + .radio-label {
// &:before {
// outline: 1px solid $radio-primary-color;
// border-color: $radio-primary-color;
// }
// }
// }
// &:disabled {
// + .radio-label {
// color: darken($radio-secondary-color, 25%);
// pointer-events: none;
// &:before {
// box-shadow: inset 0 0 0 2px $radio-secondary-color;
// border-color: $radio-disabled-color;
// background: $radio-disabled-color;
// }
// }
// }
// + .radio-label {
// &:empty {
// &:before {
// margin-right: 0;
// }
// }
// }
// }
// }
// .radio-label:after {
// content: "";
// display: inline-block;
// width: 35px;
// height: 35px;
// border-radius: 50%;
// background-color: transparent;
// position: absolute;
// left: -8px;
// top: -6px;
// scale: .75;
// transition: scale 0.35s cubic-bezier(0.6,-1.25,0.6,2.25);
// }
// .radio-label:hover:after {
// background: var(--bg-core-primary-lighten);
// scale: 1;
// opacity: .5;
// }

@ -2,28 +2,35 @@
@use '../util/' as *; @use '../util/' as *;
$sidebar-width-open:300px;
$sidebar-width-closed:75px;
$sidebar-right-width-open:300px;
$sidebar-right-width-closed:0px;
.sidebar{ .sidebar{
position: fixed; position: fixed;
padding-inline: 0.75rem;
height: 100vh; height: 100vh;
width: 100%; width: 100%;
color: $text-core; color: $text-core;
background: var(--bg-core-primary); background: var(--bg-core-primary-light);
//margin: -2rem 2rem -2rem -2rem; border-right: 1px solid rgba(0,0,0,.025);
z-index: 100; border-radius: $border-radius-lg 0 0 $border-radius-lg;
z-index: $sidebar-zindex;
transition: all 0.3s ease; transition: all 0.3s ease;
@include breakpoint(sm) { @include breakpoint(sm) {
height: calc(100% + 4rem); height: 100%;
position: relative; position: relative;
width: 300px; width: $sidebar-width-open;
} }
} }
.sidebar.close{ .sidebar.close{
width: 0; width: 0;
transform: translateX(-75px); transform: translateX($sidebar-width-closed);
@include breakpoint(sm) { @include breakpoint(sm) {
width: 75px; width: $sidebar-width-closed;
transform: translateX(0); transform: translateX(0);
} }
} }
@ -31,59 +38,80 @@
.main { .main {
width: calc(100% - 1.5rem) ; width: calc(100% - 1.5rem) ;
margin-inline:auto; margin-inline:auto;
transition: all 0.3s ease;
@include breakpoint (sm) { @include breakpoint (sm) {
width: calc(100% - 300px);; width: calc(100% - $sidebar-width-open - $sidebar-right-width-open);
padding: 2rem; padding: 2rem;
} }
} }
.main.close{ .main.close{
@include breakpoint (sm) { @include breakpoint (sm) {
width: calc(100% - 75px); width: calc(100% - $sidebar-width-closed - $sidebar-width-open);
}
}
.main.close-r{
@include breakpoint (sm) {
width: calc(100% - $sidebar-right-width-open);
}
}
.main.close.close-r{
@include breakpoint (sm) {
width: calc(100% - $sidebar-right-width-closed - $sidebar-width-closed);
} }
} }
//profile //profile
.sidebar .profile-details{ .sidebar .profile-details{
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: center;
color: #fff; padding-top: 0;
background-color: rgba(0,0,0,.6); //color: #fff;
//background-color: var(--bg-core-primary);
border-radius: $border-radius-lg 0 0 0;
transition: all 0.3s ease;
@include breakpoint (sm) {
padding-top: 12px;
}
} }
.sidebar .profile-details .avatar{ .sidebar .profile-details .avatar{
min-width: calc(70px - 1rem); min-width: 50px;
text-align: center; text-align: center;
margin: 1rem 0 1rem 1rem; margin-right: 12px;
} }
.sidebar .profile-details img{ .sidebar .profile-details img{
height: 40px; height: 50px;
width: 40px; width: 50px;
object-fit: cover; object-fit: cover;
border-radius: 50%; border-radius: 50%;
//transition: all 0.5s ease; padding: 5px;
} }
.sidebar .profile-details .name-job{ .sidebar .profile-details .profile-description {
margin-right: auto; margin-right: auto;
} }
.sidebar .profile-details .profile-name{ .sidebar .profile-details .profile-name{
font-weight: 600; font-weight: 600;
white-space: nowrap; white-space: nowrap;
color:var(--text-core-hc)
} }
.sidebar .profile-details .profile-job{ .sidebar .profile-details .profile-job{
font-size: 12px; font-size: 12px;
font-weight: 500; font-weight: 500;
color:var(--text-core-lc)
} }
.sidebar .profile-details i{ .sidebar .profile-details i{
height: 50px; height: 50px;
min-width: 70px; min-width: 50px;
text-align: center; text-align: center;
line-height: 50px; line-height: 50px;
font-size: 20px; font-size: 20px;
@ -96,135 +124,357 @@
display: none; display: none;
} }
//links /*NAV*/
.sidebar .nav-links{ .sidebar nav{
height: 100%; position: sticky;
top: 0;
}
.sidebar .navbar{
height: auto;
//padding: 12px;
padding: 0; padding: 0;
overflow: auto; overflow: auto;
display: flex;
flex-direction: column;
} }
.sidebar.close .nav-links{
.sidebar.close .navbar{
overflow: visible; overflow: visible;
} }
.sidebar .nav-links::-webkit-scrollbar{
.sidebar .navbar::-webkit-scrollbar{
display: none; display: none;
} }
.sidebar .nav-links li{
.sidebar .navbar .navbar-header{
display: block;
padding: 0.5rem 0;
margin-bottom: 0;
font-size: $font-size-sm;
color: var(--text-core-lc);
white-space: nowrap;
}
.sidebar .navbar .navbar-item{
position: relative; position: relative;
list-style: none; list-style: none;
transition: all 0.4s ease; transition: all 0.4s ease;
margin-bottom: 12px;
line-height: 50px;
border-radius: $border-radius-pill;
} }
.sidebar .nav-links li:hover{
.sidebar .navbar .navbar-item:hover,
.sidebar .navbar .navbar-item:active,
.sidebar .navbar .navbar-item.active{
background: var(--bg-core-primary-lighten); background: var(--bg-core-primary-lighten);
} }
.sidebar .nav-links li .iocn-link{
display: flex; .sidebar.close .navbar .navbar-item{
align-items: center; border-radius: 50%;
justify-content: space-between; }
.sidebar .navbar .navbar-item.fab{
background-color:#ffdad9;
border-radius: $border-radius-lg;
margin-bottom: 36px;
transition: all 0.3s ease;
} }
.sidebar.close .nav-links li .iocn-link{
display: block .sidebar .navbar .navbar-item.fab:hover,
.sidebar .navbar .navbar-item.fab:active,
.sidebar .navbar .navbar-item.fab.active{
background-color: #fbc5c3;
} }
.sidebar .nav-links li i{
.sidebar .navbar .navbar-item i{
height: 50px; height: 50px;
min-width: 70px; min-width: 50px;
text-align: center; text-align: center;
line-height: 50px; line-height: 50px;
color: var(--text-core-vc); color: var(--text-core-lc);
font-size: 20px; font-size: 22px;
cursor: pointer; cursor: pointer;
transition: all 0.3s ease; transition: all 0.3s ease;
} }
.sidebar .nav-links li.showMenu i.arrow{
transform: rotate(-180deg); .sidebar .navbar .navbar-item a{
}
.sidebar.close .nav-links i.arrow{
display: none;
}
.sidebar .nav-links li a{
display: flex; display: flex;
align-items: center; align-items: center;
text-decoration: none; text-decoration: none;
} }
.sidebar .nav-links li a .link_name{
.sidebar .navbar .navbar-item a .navbar-link{
flex: 1 0 auto; flex: 1 0 auto;
font-weight: 400; font-weight: $font-weight-400;
color: var(--text-core); color: var(--text-core);
//transition: all 0.4s ease;
}
.sidebar.close .nav-links li a .link_name{
opacity: 0;
pointer-events: none;
} }
.sidebar .navbar .navbar-item a .navbar-link:first-child {
padding-left: 1.5rem;
}
.sidebar.close .navbar .navbar-item a .navbar-link{
opacity: 0;
.sidebar .nav-links li .sub-menu{ pointer-events: none;
padding: 6px 6px 14px 70px;
margin-top: -10px;
background:var(--bg-core-primary-lighten);
display: none; display: none;
} }
.sidebar .nav-links li.showMenu .sub-menu{
display: block;
}
.sidebar .nav-links li .sub-menu a{
color: var(--text-core);
font-size: 15px;
padding: 5px 0;
white-space: nowrap;
transition: all 0.3s ease; .sidebar .navbar .navbar-item a .navbar-link.navbar-link-detail{
flex: 0 0 auto;
font-weight: $font-weight-600;
color: var(--text-core-hc);
text-align: right;
padding-right: 1rem;
} }
.sidebar .nav-links li .sub-menu a:hover{
color: var(--bg-core-primary-darken);
} /*TOOLTIP*/
.sidebar.close .nav-links li .sub-menu{ .sidebar.close .navbar .navbar-item .navbar-tooltip{
position: absolute; position: absolute;
left: 100%; background: #fff;
top: -10px; box-shadow: 0 0 2px rgba(0, 0, 0, 0.3);
width: max-content;
left: calc(100% + 12px);
top: 0;
margin-top: 0; margin-top: 0;
padding: 10px 20px; padding: 10px 20px;
border-radius: 0 6px 6px 0; border-radius: $border-radius-lg;
opacity: 0; opacity: 0;
display: block; display: block;
pointer-events: none; pointer-events: none;
transition: 0s; transition: 0s;
} }
.sidebar.close .nav-links li:hover .sub-menu{
top: 0; .sidebar.close .navbar .navbar-item:hover .navbar-tooltip{
left: calc(100% + 24px);
opacity: 1; opacity: 1;
pointer-events: auto; pointer-events: auto;
transition: all 0.4s ease; transition: all 0.4s ease;
} }
.sidebar .nav-links li .sub-menu .link_name{
display: none; .sidebar.close .navbar .navbar-tooltip {
}
.sidebar.close .nav-links li .sub-menu .link_name{
font-weight: 600;
opacity: 1; opacity: 1;
display: block; display: block;
} }
.sidebar .nav-links li .sub-menu.blank{
opacity: 1; .sidebar .navbar .navbar-tooltip {
display: none;
}
.sidebar-divider {
height: 0;
margin: 0.5rem 0;
overflow: hidden;
border-top: 1px solid var(--border-core-lighten);
}
.badge-label {
border-radius: $base-border-radius;
font-size: $font-size-sm;
color: var(--text-core-hc);
display: flex;
justify-content: center;
align-items: center;
min-width: 20px;
height: 20px;
letter-spacing: 0;
padding: 12px;
pointer-events: auto; pointer-events: auto;
padding: 3px 20px 6px 16px; text-indent: 0;
white-space: nowrap;
background-color: transparent;
transition: .3s cubic-bezier(.25,.8,.5,1);
}
/*BOOTOMBAR*/
@include breakpoint-down(sm) {
.main {
margin-bottom: rem(75);
}
.sidebar.bottombar,
.sidebar.close.bottombar {
position: fixed;
bottom: 0;
transform: translateX(0);
display: flex;
align-items: center;
height: rem(75);
width: 100%;
color: $text-core;
background: var(--bg-core-primary-light);
border-radius: 0;
z-index: $sidebar-zindex;
}
.sidebar.bottombar .profile-description,
.sidebar.close.bottombar .profile-description,
.sidebar.bottombar .profile-details i,
.sidebar.close.bottombar .profile-deteils i {
display: none;
}
.sidebar.bottombar nav,
.sidebar.close.bottombar nav {
position: relative;
width: 100%;
}
.sidebar.bottombar .navbar,
.sidebar.close.bottombar .navbar {
padding: 0;
flex-direction: row;
justify-content: space-around;
}
.sidebar.bottombar .navbar .navbar-item,
.sidebar.close.bottombar .navbar .navbar-item {
margin-bottom: 0;
}
.sidebar.bottombar .navbar-link,
.sidebar.close.bottombar .navbar-link {
display: none;
}
.sidebar.bottombar .navbar .navbar-item .navbar-tooltip,
.sidebar.close.bottombar .navbar .navbar-item .navbar-tooltip {
display: none;
}
.sidebar.bottombar .navbar-item.fab,
.sidebar.close.bottombar .navbar-item.fab {
position: absolute;
right: 1rem;
top: -4rem;
}
.sidebar.bottombar .sidebar-divider,
.sidebar.close.bottombar .sidebar-divider {
display: none;
}
}
/*RIGHT SIDEBAR*/
.sidebar.right{
position: fixed;
top: 0;
right: 0;
height: 100vh;
width: 100%;
color: $text-core;
background: var(--bg-core-primary-lighten);
border-right: 1px solid rgba(0,0,0,.025);
border-radius: 0 $border-radius-lg $border-radius-lg 0;
z-index: $sidebar-right-zindex;
transition: all 0.3s ease;
@include breakpoint(sm) {
height: 100%;
position: relative;
width: $sidebar-right-width-open;
}
}
.sidebar.right.close-r{
width: 0;
transform: translateX($sidebar-right-width-closed);
padding: 0;
@include breakpoint(sm) {
width: $sidebar-right-width-closed;
transform: translateX(0);
z-index: -1;
opacity: 0; opacity: 0;
pointer-events: none; pointer-events: none;
} }
.sidebar .nav-links li:hover .sub-menu.blank{
top: 50%;
transform: translateY(-50%);
} }
.sidebar.right .navbar .navbar-item:hover,
.sidebar.right .navbar .navbar-item:active,
.sidebar.right .navbar .navbar-item.active{
background: var(--bg-core-primary);
}
// .scrollable {
// display: block;
// height: 100%;
// max-height: 100vh;
// min-height: 0;
// }
// .scroll-wrapper {
// position: relative;
// width: 100%;
// height: 100%;
// background-color: turquoise;
// }
// .scroll-container {
// position: relative;
// width: 100%;
// height: 100%;
// touch-action: pan-y;
// overflow-x: hidden;
// overflow-y: auto;
// }
// .scroll-content {
// height: auto;
// transform: none;
// position: relative;
// min-height: 100%;
// }
.scrollable {
width: 100%;
height: 100%;
overflow-x: hidden;
overflow-y: auto;
max-height: calc(100vh - 50px);
}
.scroll-wrapper {
position: relative;
width: auto;
height: 100%;
pointer-events: none;
}
.scroll-container {
position: relative;
display: flex;
flex-direction: column;
width: 100%;
max-height: 100%;
overflow: hidden;
pointer-events: auto;
background-clip: padding-box;
}
.scroll-content {
position: relative;
overflow-y: auto;
flex: 1 1 auto;
}

@ -0,0 +1,107 @@
@use "../globals/" as *;
@use "../util/" as *;
$toggle-primary-color: var(--bg-core-primary-darken);
$toggle-secondary-color: #ddd;
$toggle-disabled-color: darken($toggle-secondary-color, 25%);
.toggle-group {
--width: 42px;
--height: calc(var(--width) / 2);
--border-radius: calc(var(--height) / 2);
margin: 0.75rem 0;
width: max-content;
cursor: pointer;
position:relative;
display: flex;
align-items: center;
gap:.75rem;
&.reversed{
justify-content: space-between;
width: 100%;
& :nth-child(1) {order:2;}
& :nth-child(2) {order:1;}
}
&.column{
flex-direction: column;
gap:.25rem;
width: 100%;
}
input[type="checkbox"] {
position: absolute;
opacity: 0;
}
}
.toggle-fill {
position: relative;
width: var(--width);
height: var(--height);
border-radius: var(--border-radius);
background: $toggle-secondary-color;
//margin-right: .75rem;
transition: background 0.2s ease-in-out;
}
.toggle-input:checked ~ .toggle-fill {
background: var(--bg-core-primary-darken);
}
.toggle-input:focus-within ~ .toggle-fill {
outline: 1px solid $toggle-primary-color;
}
.toggle-input:disabled ~ .toggle-fill {
background: $toggle-disabled-color;
pointer-events: none;
}
.toggle-input:disabled ~ .toggle-label {
color: $toggle-disabled-color;
}
.toggle-fill::after {
content: "";
position: absolute;
top: 2px;
left: 2px;
height: calc(var(--height) - 4px);
width: calc(var(--height) - 4px);
background: #ffffff;
border-radius: var(--border-radius);
transition: transform 0.2s;
}
.toggle-input:checked ~ .toggle-fill::after {
transform: translateX(var(--height));
}
.toggle-fill::before {
content: "";
display: inline-block;
width: calc(var(--height) * 1.8);
height: calc(var(--height) * 1.8);
border-radius: 50%;
background-color: transparent;
position: absolute;
left: calc(30% - var(--height));
top: calc(60% - var(--height));
scale: .75;
transform-origin: center;
transition: scale 0.35s cubic-bezier(0.6,-1.25,0.6,2.25), transform 0.2s;
}
.toggle-fill:hover::before {
background: var(--bg-core-primary-lighten);
scale: 1;
opacity: .5;
}
.toggle-input:checked ~ .toggle-fill::before {
transform: translateX(var(--height));
}

@ -39,4 +39,43 @@ margin-bottom: 1rem;
} }
/*ICONS*/
.icon-default {
color: var(--bg-core-primary);
}
.disabled {
.icon-root, .svg-icon, .icon-default {
color: var(--bg-core-primary-light);
}
}
.icon-root {
width: 1em;
height: 1em;
display: inline-block;
transition: fill 200ms cubic-bezier(0.4, 0, 0.2, 1) 0ms;
flex-shrink: 0;
user-select: none;
&:focus {
outline: none;
}
&.svg-icon {
fill: currentColor;
}
}
.icon-size-small {
font-size: 1.25rem;
}
.icon-size-medium {
font-size: 1.5rem;
}
.icon-size-large {
font-size: 2.25rem;
}

@ -1,7 +1,5 @@
/* Box sizing rules */ /* Box sizing rules */
*, *, *::before, *::after {
*::before,
*::after {
box-sizing: border-box; box-sizing: border-box;
} }
@ -48,7 +46,13 @@ a:not([class]) {
text-decoration-skip-ink: auto; text-decoration-skip-ink: auto;
} }
a, a:hover { a {
text-decoration: none;
transition: color 0.15s ease-in-out;
}
a:hover {
text-decoration: none; text-decoration: none;
transition: color 0.15s ease-in-out; transition: color 0.15s ease-in-out;
} }

@ -157,6 +157,27 @@ p,
text-overflow: ellipsis; text-overflow: ellipsis;
} }
.text-hc {
color: var(--text-core-hc);
}
.text-lc {
color: var(--text-core-lc);
}
a.text-link{
color: var(--bg-core-primary-dark);
border-bottom:1px dotted;
transition: all 0.15s ease-in-out;
}
a.text-link:hover{
color: var(--bg-core-primary-darken);
border-bottom:none;
}
// $fs: ( // $fs: (
// "font-size": ( // "font-size": (
// "prefix": "fs", // "prefix": "fs",

@ -1,8 +1,8 @@
@use "sass:math"; @use "sass:math";
//theme colors //theme colors
$bg-core-primary: hsl(225, 68%, 85%); // body-background; //$bg-core-primary: hsl(225, 68%, 85%); // body-background;
$bg-core-start: $bg-core-primary; //$bg-core-start: $bg-core-primary;
$bg-core-end: #fafafa; $bg-core-end: #fafafa;
$text-core-hc: #212121; //title $text-core-hc: #212121; //title
@ -10,67 +10,112 @@ $text-core: #525252; //text
$text-core-lc: #7d7d80; //metadata $text-core-lc: #7d7d80; //metadata
$text-core-vc: #969699; //ikona-text $text-core-vc: #969699; //ikona-text
$border-core: lighten($bg-core-primary, 7%); //border //$border-core: lighten($bg-core-primary, 7%); //border
$element-bg-core: rgba(255, 255, 255, 0.5); // elements-background $element-bg-core: rgba(255, 255, 255, 0.5); // elements-background
$element-fg-core: rgba(255, 255, 255, 0.25); // elements-foreground $element-fg-core: rgba(255, 255, 255, 0.25); // elements-foreground
:root { :root {
--bg-core-primary: #{$bg-core-primary}; // body-background; $blue-50: #f2f4fd;
--bg-core-primary-lighten: hsl(225, 68%, 90%); // lighten $blue-100: #e5eafa;
--bg-core-primary-darken: hsl(225, 68%, 75%); // darken; $blue-200: #cbd6f5;
--bg-core-start: #{$bg-core-primary}; $blue-300: #b2c1f1;
--bg-core-end: #{$bg-core-end}; $blue-400: #98adec;
$blue-500: #7e98e7;
$blue-600: #657ab9;
$blue-700: #4c5b8b;
$blue-800: #323d5c;
$blue-900: #191e2e;
--bg-core-primary: #{$blue-300}; // body-background;
--bg-core-primary-light: #{$blue-50}; // light
--bg-core-primary-lighten: #{$blue-200}; // lighten
--bg-core-primary-darken: #{$blue-400}; // darken;
--bg-core-primary-dark: #{$blue-600}; // dark;
--bg-core-start: #{$blue-300}; // body-background
--bg-core-end: #{$bg-core-end}; // body-background
--text-core-hc: #{$text-core-hc}; //title --text-core-hc: #{$text-core-hc}; //title
--text-core: #{$text-core}; //text --text-core: #{$blue-800}; //text
--text-core-lc: #{$text-core-lc}; //metadata --text-core-lc: #{$text-core-lc}; //metadata
--text-core-vc: #{$text-core-vc}; //ikona-text --text-core-vc: #{$text-core-vc}; //ikona-text
--bg-core-primary-lighter: hsl(225, 68%, 90%); //hover --border-core-lighten:#{$blue-100}; //border-lighten
--border-core: #{$border-core}; //border --border-core: #{$blue-200}; //border
--element-bg-core: #{$element-bg-core}; // elements-background --element-bg-core: #{$element-bg-core}; // elements-background
--element-fg-core: #{$element-fg-core}; // elements-foreground --element-fg-core: #{$element-fg-core}; // elements-foreground
} }
.pink,
:root:has(pink:checked) { .pink {
--bg-core-primary: hsl(310 50% 90%); $violet-50: #f0eef6;
--bg-core-primary-lighten: hsl(310 50% 95%); //lighten $violet-100: #e1dced;
--bg-core-primary-darken: hsl(310 50% 85%); //darken $violet-200: #c2b9db;
--element-bg-core: hsl(310 50% 100% / 50%); $violet-300: #a496c8;
--text-core: hsl(310 50% 15%); $violet-400: #8573b6;
--border-core: hsl(310 50% 90%); $violet-500: #6750a4;
$violet-600: #524083;
$violet-700: #3e3062;
$violet-800: #151021;
$violet-900: #212529;
--bg-core-primary: #{$violet-300}; // body-background;
--bg-core-primary-light: #{$violet-50}; // light
--bg-core-primary-lighten: #{$violet-200}; // lighten
--bg-core-primary-darken: #{$violet-400}; // darken;
--bg-core-primary-dark: #{$violet-600}; // dark;
--bg-core-start: #{$violet-200}; // body-background
--bg-core-end: #{$bg-core-end}; // body-background
--text-core-hc: #{$text-core-hc}; //title
--text-core: #{$violet-800}; //text
--text-core-lc: #{$text-core-lc}; //metadata
--text-core-vc: #{$text-core-vc}; //ikona-text
--border-core-lighten:#{$violet-100}; //border-lighten
--border-core: #{$violet-200}; //border
--element-bg-core: #{$element-bg-core}; // elements-background
--element-fg-core: #{$element-fg-core}; // elements-foreground
} }
.dark,
:root:has(dark:checked) {
.dark {
--bg-core-primary: hsl(0 0% 10% / 100%); // body-background; --bg-core-primary: hsl(0 0% 10% / 100%); // body-background;
--bg-core-primary-lighten: hsl(0 0% 15% / 100%); // lighten --bg-core-primary-light: hsl(0 0% 15% / 100%); // light
--bg-core-primary-darken: hsl(0 0% 5% / 100%); // darken; --bg-core-primary-lighten: hsl(0 0% 17% / 100%); // lighten
--bg-core-start: var(--bg-core-primary); --bg-core-primary-darken: hsl(0 0% 7% / 100%); // darken;
--bg-core-end: hsl(0 0% 15% / 100%); --bg-core-primary-dark: hsl(0 0% 5% / 100%); // dark;
--bg-core-start: hsl(0 0% 10% / 100%); // body-background
--bg-core-end: hsl(0 0% 15% / 100%); // body-background
--text-core-hc: hsl(0 0% 97% / 100%); //title --text-core-hc: hsl(0 0% 97% / 100%); //title
--text-core: hsl(0 0% 73% / 100%); //text --text-core: hsl(0 0% 73% / 100%); //text
--text-core-lc: hsl(0 0% 53% / 100%); //metadata --text-core-lc: hsl(0 0% 53% / 100%); //metadata
--text-core-vc: hsl(0 0% 60% / 100%); //ikona-text --text-core-vc: hsl(0 0% 60% / 100%); //ikona-text
--border-core: hsl(0 0% 27% / 100%); //border --border-core-lighten:hsl(0 0% 17% / 100%); //border-lighten
--border-core: hsl(0 0% 20% / 100%); //border
--element-bg-core: hsl(0 0% 13% / 100%); // elements-background --element-bg-core: hsl(0 0% 13% / 100%); // elements-background
--element-fg-core: hsl(0 0% 20% / 100%); // elements-foreground --element-fg-core: hsl(0 0% 15% / 100%); // elements-foreground
} }
// colors // colors
$blue: #0d6efd; // $blue: #0d6efd;
$indigo: #6610f2; // $indigo: #6610f2;
$purple: #6f42c1; // $purple: #6f42c1;
$pink: #d63384; // $pink: #d63384;
$red: #dc3545; // $red: #dc3545;
$orange: #fd7e14; // $orange: #fd7e14;
$yellow: #ffc107; // $yellow: #ffc107;
$green: #00c851; //#198754; // $green: #00c851; //#198754;
$teal: #20c997; // $teal: #20c997;
$cyan: #0dcaf0; // $cyan: #0dcaf0;
$white: #fff; $white: #fff;
$gray-100: #f8f9fa; $gray-100: #f8f9fa;
@ -84,13 +129,20 @@ $gray-800: #343a40;
$gray-900: #212529; $gray-900: #212529;
$black: #000; $black: #000;
$blue: #0dbcf0c4;
$red: #ff7f78;
$yellow: #ffb480;
$green: #8fcaa3;
$cyan: #729fe9;
$primary: $blue; $primary: $blue;
$secondary: $gray-600; $secondary: $gray-400;
$success: $green; $success: $green;
$info: $cyan; $info: $cyan;
$warning: $yellow; $warning: $yellow;
$danger: $red; $danger: $red;
$light: $gray-400; $light: $gray-300;
$dark: $gray-900; $dark: $gray-900;
//color palette //color palette
@ -138,9 +190,16 @@ $font-weight-800: 800; // extra bold
$base-border-radius: 0.3rem; $base-border-radius: 0.3rem;
$border-radius-sm: math.div($base-border-radius, 2); $border-radius-sm: math.div($base-border-radius, 2);
$border-radius-lg: $base-border-radius * 2; $border-radius-lg: $base-border-radius * 2;
$border-radius-pill: 100vw;
// box-shadow // box-shadow
$base-box-shadow: 0 0.125rem 0.25rem rgb(0 0 0 / 10%) !default; $base-box-shadow: 0 0.125rem 0.25rem rgb(0 0 0 / 10%) !default;
// transition // transition
$transition: all 0.15s ease-in-out; $transition: all 0.15s ease-in-out;
//z-index
$sidebar-zindex: 899;
$sidebar-right-zindex: 898;
$backdrop-zindex: 999;
$modal-zindex: 10000;

@ -1,16 +1,21 @@
@use "../globals" as *; @use "../globals" as *;
.color-picker-container {
margin-bottom: 1rem;
}
.color-picker > fieldset { .color-picker > fieldset {
border: 0; border: 0;
display: flex; display: flex;
flex-direction: column; //flex-direction: column;
gap: 2rem; gap: 1.5rem;
width: fit-content; width: fit-content;
//background: #fff; //background: #fff;
padding: 1rem 3rem; padding: 0.5rem 1.5rem;
position: fixed; //position: fixed;
top: 1rem; //top: 1rem;
right: 0; //right: 0;
border-radius: 0 0 1rem 1rem; border-radius: 0 0 1rem 1rem;
} }
@ -31,14 +36,15 @@
background-color: var(--radio-color); background-color: var(--radio-color);
} }
.color-picker input[type="radio"]light { .color-picker input[type="radio"] {
--radio-color: hsl(225, 68%, 85%); --radio-color: hsl(225, 68%, 85%);
} }
.color-picker input[type="radio"]pink {
--radio-color: pink; .color-picker input[type="radio"] {
--radio-color: rebeccapurple;
} }
.color-picker input[type="radio"]dark { .color-picker input[type="radio"] {
--radio-color: #232323; --radio-color: #232323;
} }
@ -58,8 +64,9 @@
background: var(--element-fg-core); background: var(--element-fg-core);
border: 1px solid; border: 1px solid;
border-color: var(--border-core); border-color: var(--border-core);
color: inherit; //color: inherit;
border-radius: $border-radius-lg; border-radius: $border-radius-lg;
} }

@ -20,6 +20,10 @@
//test-sidebar //test-sidebar
.document-container {
background-color: var(--element-bg-core);
}
.document-container { .document-container {
//padding: rem(32); //padding: rem(32);
@ -33,7 +37,8 @@
border-radius: $border-radius-lg; border-radius: $border-radius-lg;
// padding: rem(32); // padding: rem(32);
box-shadow: $base-box-shadow; box-shadow: $base-box-shadow;
overflow: hidden; //overflow: hidden;
overflow-x: clip;
} }
} }

@ -2,7 +2,8 @@
$breakpoints-up: ( $breakpoints-up: (
"": "", "": "1",
//'xs': rem(1),
'sm': rem(576), 'sm': rem(576),
'md': rem(768), 'md': rem(768),
'lg': rem(992), 'lg': rem(992),
@ -11,7 +12,8 @@ $breakpoints-up: (
// 639px, 1149px, 1399px // 639px, 1149px, 1399px
$breakpoints-down: ( $breakpoints-down: (
"": "", "": "0",
//'xs': rem(0),
'sm': rem(575), 'sm': rem(575),
'md': rem(767), 'md': rem(767),
'lg': rem(991), 'lg': rem(991),

@ -58,8 +58,7 @@
} }
//change --bg-core-primary for dark //change --bg-core-primary for dark
.dark, .dark {
:root:has(dark:checked) {
$val: hsl(216 100% 70%); $val: hsl(216 100% 70%);
.text-core { .text-core {

@ -8,7 +8,7 @@
// change text color based on background color - set-color(color-value) // change text color based on background color - set-color(color-value)
@function set-color($color) { @function set-color($color) {
@if (lightness($color) > 55) { @if (lightness($color) > 74) {
@return #333; @return #333;
} }
@else { @else {

@ -160,6 +160,35 @@
} }
} }
//Position classes
$positionProps: (
"absolute",
"fixed",
"inherit",
"initial",
"relative",
"revert",
"static",
"sticky",
"unset",
);
@each $pos in $positionProps {
@if $breakName != "" {
@media (min-width: $breakValue) {
.position-#{$breakName}-#{$pos} {
position: #{$pos} !important;
}
}
} @else {
.position-#{$pos} {
position: #{$pos} !important;
}
}
}
//Display classes //Display classes
$displayProps: ( $displayProps: (
"block", "block",

@ -135,12 +135,24 @@ public static class Helper
} }
} }
public static T? ConvertToType<T>(object variable)
{
try
{
if (variable is not null)
return (T)Convert.ChangeType(variable, typeof(T));
return default;
} catch
{
return default;
}
}
public static bool IsNumeric(string input) public static bool IsNumeric(string input)
{ {
try try
{ {
var number = Double.Parse(input); return Double.TryParse(input, out var number);
return true;
} }
catch catch
{ {

Loading…
Cancel
Save