{"id":22343539,"url":"https://github.com/datajuggler/datajuggler.blazor.components","last_synced_at":"2025-10-06T13:44:35.929Z","repository":{"id":62915628,"uuid":"235187619","full_name":"DataJuggler/DataJuggler.Blazor.Components","owner":"DataJuggler","description":"This project includes a Text Box, Grid, Combo Box, Check Box, Checked List Box, Image Button, Combo Box, Checked List Box, Time Component, Toggle Component, Label and Calendar.","archived":false,"fork":false,"pushed_at":"2025-09-26T18:19:31.000Z","size":2762,"stargazers_count":9,"open_issues_count":0,"forks_count":1,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-09-26T20:37:52.279Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"CSS","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/DataJuggler.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"License/License.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2020-01-20T19:59:13.000Z","updated_at":"2025-09-26T18:19:36.000Z","dependencies_parsed_at":"2023-11-15T12:31:07.622Z","dependency_job_id":"3e131ace-f695-488c-8f77-255b5c56654c","html_url":"https://github.com/DataJuggler/DataJuggler.Blazor.Components","commit_stats":{"total_commits":197,"total_committers":2,"mean_commits":98.5,"dds":0.1116751269035533,"last_synced_commit":"aaf1e3b08f824abfc2852088bdb659c1c96a3a22"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/DataJuggler/DataJuggler.Blazor.Components","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DataJuggler%2FDataJuggler.Blazor.Components","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DataJuggler%2FDataJuggler.Blazor.Components/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DataJuggler%2FDataJuggler.Blazor.Components/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DataJuggler%2FDataJuggler.Blazor.Components/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/DataJuggler","download_url":"https://codeload.github.com/DataJuggler/DataJuggler.Blazor.Components/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DataJuggler%2FDataJuggler.Blazor.Components/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":278621844,"owners_count":26017253,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-06T02:00:05.630Z","response_time":65,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-12-04T08:16:20.370Z","updated_at":"2025-10-06T13:44:35.922Z","avatar_url":"https://github.com/DataJuggler.png","language":"CSS","funding_links":[],"categories":[],"sub_categories":[],"readme":"News\r\n\r\nRequest: This project has been stuck on 9 stars for a long time. \r\nPlease take 1 minute and leave a star: https://github.com/DataJuggler/DataJuggler.Blazor.Components\r\n\r\n10.2.2025: I added a way to add ColumnHeaders via markup\r\n\r\nInside a Grid Definition, add a GridColumns Fragment like shown below.\r\nIt's important you add LastColumn=\"true\" on the last field. This is how\r\nthe grid knows you are done adding columns and converts them to Columns for\r\nthe Header for now. Later I will add a way to display rows from a datasource of \r\ntype\u003cT\u003e and use the Column info. Baby steps. \r\n\r\n    \u003cGrid\u003e\r\n        \u003cGridColumns\u003e\r\n            \u003cGridColumn Parent=\"@ClientsGrid\" Caption=\"Name\" Name=\"Name\"\r\n                        Index=\"0\" ColumnNumber=\"1\" Width=\"240\" Height=\"16\"                                    \r\n                        ClassName=\"displayinlineblock textdonotwrap width240 colorwhite textalignleft right16 down4 fontsize12\" /\u003e\r\n            \u003cGridColumn Parent=\"@ClientsGrid\" Caption=\"Active\" Name=\"Active\"\r\n                        Index=\"1\" ColumnNumber=\"2\" Width=\"64\" Height=\"16\"\r\n                        LastColumn=\"true\"\r\n                        ClassName=\"displayinlineblock textdonotwrap width64 colorwhite textalignleft down4 right16 fontsize12\" /\u003e\r\n        \u003c/GridColumns\u003e\r\n    \u003c/Grid\u003e\r\n\r\n10.1.2025: I added height: auto to DataJuggler.Blazor.CSS\r\n\r\n9.30.2025: I added a property to the Grid called StickyHeader. If true, the grid header\r\nshould stay in place when the grid scrolls. Testing now, so use at your own risk.\r\n\r\n9.29.2025: I am redoing the TextBoxComponent. The Label is now a LabelComponent. \r\nHopeing this will solve some of the issues of properties not applying. The Label works well.\r\nI should have done this a while back. I added a method to the grid RefreshAsync\r\n\r\n9.28.2025: I updated some more Color properties to be colors, not strings. Possible breaking\r\nchanges to CheckBoxes, Calendars, TextBox, Label, and ComboBoxes. Sorry for the breaking \r\nchange, it is just better to obe consistent. I searched this time for Color = \" and should have\r\nfound them all. Still testing today. I also added some properties to the Grid BorderColor\r\nand Borderwidth, and EnableDoubleClick.\r\n\r\n9.26.2025: I updated the Label component to have a new class called TextStyle. The font wasn't working\r\nwith the font in ControlStyle, so I moved TextAlign, FontSize, FontName and Color properties to the new\r\nCSS (BlazorStyled) class. \r\n\r\n7.8.2025: Microsoft (NuGet) informed me Microsoft.Identity.Client 4.6.3 has a vulnerability.\r\nI don't use Identity in this project, but I updated DataJuggler.NET9 which did reference\r\nMicrosoft.Data.SqlClient, which does reference Microsoft.Identity.Client. This project uses\r\nDataJuggler.Excelerate, which uses DataJuggler.NET9. This should fix any vulnerability warnings\r\nif VS starts showing them, update this package to 9.17.2 should fix it.\r\n\r\n7.6.2025: I created a new SaveCancelComponent. You can either set ImageUrl, which will\r\nset botht the CancelButton and SaveButton to the same image, or you can use a different image\r\nby setting SaveButtonImageUrl or CancelButtonImageUrl. There is also a Text property or\r\nyou can select a Theme which will set both buttons. Here is the list of Themes so far.\r\n\r\n    public enum ButtonThemeEnum : int\r\n    {\r\n        NotSet = 0,\r\n        BlackButton = 1,\r\n        BlackButtonWide = 2,        \r\n        OrangeStone = 3,\r\n        PurpleStone = 4,\r\n        RedGlass = 5,\r\n        TanButton = 6,\r\n        BlueButton = 7\r\n    }\r\n\r\n    \u003cSaveCancelComponent Name=\"SaveCancel\" Parent=this\r\n        Left=\"0\" Top=\"0\" ButtonTheme=@ButtonThemeEnum.BlackButton\r\n        OnSavedCallback=\"@OnSave\" OnCancelledCallback=\"@OnCancel\"\r\n        SaveButtonleft=\"-8\" FontSize=\"16\"\u003e\r\n    \u003c/SaveCancelComponent\u003e\r\n\r\nI am also very close to releasing a new feature to my Visual Studio package Regionizer 2022.\r\nI added a new Blazor Templates Form, and you will soon be able to click a button and add \r\nnew components to a form and wire up all the code. It's pretty cool.\r\n\r\n7.2.2025: Hopefully no one is upsert, but I have another minor breaking change. I refactored any property\r\ncalled TextColor that was a string to be a System.Drawing.Color. I am trying to be consistent. Half were strings\r\nand half were Colors, so I went with Colors. Forgive me. Something cool is coming for UI Biulding and its not AI\r\nit's me!\r\n\r\n6.20.2025: Version 9.16.2: Small breaking change. I delted FontUnit from the CheckedListBox. I was using FontSize + FontUnit\r\nbut FontSize + Unit is enough control. Too confusing having more than two units.\r\n\r\n6.18.2025: Version 9.16.0 - I cleaned up a bunch of things. The ComboBox, CheckedListBox and Calendar all\r\nhad pretty major updates. I probably broke a few things, but I have a new Visual Studio Toolbar coming to \r\nmake it easier to create and wire up components. Hopefully as soon as this weekend.\r\n\r\n6.16.2025: Breaking Change!!!! - There are 6 components in this library that have the property LabelColor.\r\n                  \r\nCalendarComponent, CheckBoxComponent, ComboBox, TextBoxComponent, TimeComponent, ToggleComponent\r\n\r\n3 had LabelColor as a System.Drawing.Color and 3 had LabelColor as a String. I made them all a Color.\r\nSorry for the breaking change, but I am code generating components in a toolbar and its easier if they are all\r\nthe same.\r\n\r\n6.16.2025: I added two new properties to the ComboBox - OverfloxX and OverflowY.\r\n                  OverFlowX defaults to Hidden and OverFloxY defaults to Auto.\r\n\r\n6.15.2025B: I added new properties to the ImageButton for BorderWidth and BorderColor and new Properties\r\nto the ComboBox and Calendar for ButtonBorderWidth and ButtonBorderColor.\r\nv9.15.2\r\n\r\n6.15.2025: I added some new properties to the Calendar to allow positioning of the month and year navigation buttons:\r\n\r\n   PreviousMonthButtonLeft\r\n   PreviousMonthButtonTop\r\n   PreviousYearButtonLeft\r\n   PreviousYearButtonTop\r\n   BottomNavButtonsTop\r\n\r\n6.14.2025: I added a Parameter property TextBoxTop to the Calendar and the ComboBox\r\nv9.14.9      Added FontSize to the Calendar which sets both the Label and TextBox FontSize\r\n\r\n6.5.2025: I added two properties to the ImageButton TextOffsetX and TextOffsetY. This allows you to position the text.\r\nAlso ClassName on the ImageButton wasn't being used. Now it is.\r\n\r\n6.3.2025: Added CookieService\r\n\r\nAdded a CookieService that uses JavaScript Interop to set, retrieve, and delete cookies.\r\n\r\nHow to Use\r\n\r\n1. Register the service in Program.cs\r\n\r\n    builder.Services.AddScoped\u003cCookieService\u003e();\r\n\r\n2. Inject the service into your component\r\n\r\n    @inject CookieService CookieService\r\n\r\n3. Use it in your .razor.cs or @code block\r\n\r\n    protected override async Task OnInitializedAsync()\r\n    {\r\n        await CookieService.SetCookieAsync(\"MyApp.UserTheme\", \"Dark\", 30); // Set for 30 days\r\n        var theme = await CookieService.GetCookieAsync(\"MyApp.UserTheme\"); // Retrieve\r\n        await CookieService.DeleteCookieAsync(\"MyApp.UserTheme\");          // Delete\r\n    }\r\n\r\n\r\n5.9.2025: I added a new LinkButton. It's essentially the same code as the ImageButton, just formatted as link.\r\nI broke two properties. ButtonTextAlign and ButtonText are now just TextAlign and Text. \r\n\r\n5.8.2025: I removed TextSize from the ImageButton and added FontSize. Trying to stay consistent among controls.\r\nI realized today the ClassName property of the TextBox was not being used. It is not used at the top.\r\nI added another property, AllowWrapping. If AllowWrapping is true, TextWrapping = \"donotwrap\" (a class name\r\nin DataJuggler.Blazor.Components.css) else TextWrapping = \"\". AllowWrapping defaults to False.\r\n\r\n    @if (Visible)\r\n    {  \r\n        \u003cdiv class=\"@TextBoxControlStyle @ClassName @TextWrapping\"\u003e\r\n\r\n5.7.2025: I added a ContentTop and ContentTop to the GridComponent. I also removed Flex from the Grid.\r\nAI is flex happy when you ask for assistance. \r\n\r\n5.6.2025: I added TextBoxLeft and TextBoxTop to the TextBoxComponent. TextBoxLeft defaults to 8 (pixels)\r\nThis adds a little gap between the Label and the TextBox.\r\n\r\n    \u003cTextBoxComponent Name=\"UserNameControl\" Parent=\"this\" Caption=\"UserName\"\u003e\u003c/TextBoxComponent\u003e\r\n\r\n5.4.2025 - Removing static web assets. Wasn't needed it after all.\r\n\r\n2.11.2025: I added a property ListItemMarginBottom to the ComboBox.\r\nThis property defaults to 2 pixels.\r\n\r\n2.10.2025: I added a SetTextColor method to the Label component.\r\n\r\nThe ComboBox still has an issue with z-index.\r\n\r\nI tried to fix this all weekend. The only solution I found is when you add the combo box,\r\nAdd a class above it.\r\n\r\n    \u003cdiv class=\"row row2 zindex400\"\u003e\r\n        \u003cComboBox Name=\"TargetFrameworkComboBox\" Parent=\"this\" LabelText=\".NET Framework:\"\r\n        LabelColor=\"Color.GhostWhite\" Theme=\"ThemeEnum.BlueGold\" ListItemLeft=\"0\"            \r\n        ListItemTop=\"0\" ListContainerPosition=\"absolute\" ZIndex=\"100\"\r\n        LabelFontName=\"Calibri\" LabelFontSize=\"14\" ButtonHeight=\"24\"\u003e\r\n        \u003c/ComboBox\u003e\r\n    \u003c/div\u003e\r\n\r\n2.9.2025: The ComboBox has been fixed. The Z-Index wasn't working.\r\nLeaving myself a note, for some reason ListItemWidth has to be set in OnAfterRenderAsync.\r\n\r\n    ListItemWidth = GlobalDefaults.TextBoxWidth;\r\n\r\n12.17.2024: Updates to the Calendar, Label and Time Comonents.\r\n\r\nTo get the JS working for the Label, set the FadeValue to the miliseconds such as:\r\n\r\n\t\u003cLabel Name=\"StatusLabel\" Parent=\"this\" Unit=\"vw\" FadeValue=\"2500\"\r\n\t\tTextColor=\"Coral\" FontSize=\"20\" TextAlign=\"center\" ClientId=\"statuslabel\"\r\n\t\tWidth=\"20\" Visible=\"@ShowStatusMessage\"\u003e\u003c/Label\u003e\r\n\r\nAdd this JS reference to App.razor:\r\n\r\n    \u003cscript src=\"_content/DataJuggler.Blazor.Components/_content/Blazor.JavaScriptInterop/BlazorJSInterop.js\"\u003e\u003c/script\u003e\r\n\r\n12.8.2024: Breaking changes for the LabelComponent. I didn't like having so much clutter that\r\nwasn't used. I cleaned up and made a bunch of changes:\r\n1. LabelColor became TextColor\r\n2. LabelClassName became ClassName\r\n3. Anything property named Label became Caption or was removed\r\n4. There is no longer a FontSize and LabelFontSize. Too confusing.\r\n \r\nSorry to break things, but trying to be consistent and simple.\r\n\r\n11.27.2024: I added a new property called TextBoxTextColor to the TextBoxComponent.\r\n\r\n11.17.2024: New Toggle Component. The Toggle Component makes it simple to place a Label and Toggle Component\r\non a page. Here is an example of using the Toggle Component.\r\n\r\nFrom Open Source Project NTouch\r\nhttps://github.com/DataJuggler/NTouch\r\n\r\n    \u003cToggleComponent Parent=\"this\" Width=\"60\" CircleColor=\"@Color.Orange\"\r\n        CircleWidth=\"12\" CircleHeight=\"12\" Caption=\"Subscriber: \" OvalWidth=\"24\"\r\n        BackgroundColorOn=\"Color.CornflowerBlue\" BackgroundColorOff=\"@Color.Gray\"\u003e\u003c/ToggleComponent\u003e\r\n\r\nYou can customize the Oval Size and Color for the on state and color for the off state.\r\nNote the OvalWidth is the OvalWidth + (Oval End Width x 2) = 56.   24 + (16 * 2) in this case.                                       \r\n\r\nOther notable properties include\r\n1. OvalEndWidth which defaults to 16.\r\n2. OvalRadius which defaults to 50%\r\n3. OvalPosition - defaults to relative\r\n4. OvalLeft - Increase this value to move the oval container to the right\r\n\r\nNote - I recently built a new project called Doc Gen, which reads a Visual Studio solution and will help me build\r\nbetter documentation, coming soon.\r\n\r\n\r\n11.13.2024: This project has been updated to .NET 9. Also, EPPPlus has been removed from\r\nDataJuggler.Excelerate, so the package vunlernabilities are gone.\r\n\r\n10.4.2024: A new video was published\r\n\r\nDataJuggler.Blazor.Components Grand Update\r\nhttps://youtu.be/ybihE8udW-w\r\n\r\n10.2.2024: Version 8.11.7 was published and the ComboBox when in CheckedListMode now displays\r\nthe selections. \r\n\r\n# 200,000 Installs\r\n10.1.2024: DataJuggler.Blazor.Components recently passed 200,000 installs on NuGet. Sadly, out of 200,000 installs \r\nthere are only 7 likes on this project. Please take a second and like this project as I work hundreds of hours \r\nper year on it.\r\n\r\nPlease leave a star if you think this project is worth the price.\r\nhttps://github.com/DataJuggler/DataJuggler.Blazor.Components\r\n\r\n# Upcoming News\r\nI will start testing the previews for .NET 9, so I expect to have a working version for .NET 9 by release date\r\nin Mid November or soon thereafter.\r\n\r\n# New Website Coming\r\nI plan on building a new site just for this project, so you can find the information you need faster about each component.\r\n\r\n# Major Update Version 8.11.0\r\n10.1.2024: This release contains a few major updates, and one breaking change, but it's an easy fix in most cases.\r\n\r\n# New Time Component\r\nI created a new Time Component, and you type in the hours or minutes and double click on the AM / PM label to toggle it.\r\nIf you set the property TimeType to Hours24, than the AM / PM label does not appear.\r\n\r\n# New Delegate OnTextChange(string text)\r\n\r\nA new delegate was created in DataJuggler.Blazor.Components.Delegates called OnTextChange, and you can create\r\na method that receives a string parameter to get a call back when a text box value changes. This is how the TimeComponent\r\nturns red if you type in an invalid time.\r\n\r\n    public delegate void OnTextChange(string text);\r\n\r\n# InformationBoxComponent - New Property: BodyContent\r\nI learned something new recently thanks to Bing Chat (Copilot). I wanted the user to be able to host their own \r\ncomponents on an InformationBoxComponent, and you can do so with a property called RenderFragment.\r\nSo in the InformationBoxComponent, you can do this:\r\n\r\n    \u003cInformationBox Name=\"TestScheduleInfoBox\" Parent=\"this\" Title=\"Test Schedule\"\r\n        Column1Width=\"200\" Column2Width=\"120\" Column1Left=\"0\" Gap=\"8\" ListItemTop=\"-2\"\r\n        Column1ClassName=\"textalignright\" Column2ClassName=\"textalignleft\"\r\n        HeaderFontWeight=\"bold\" HeaderFontSize=20\r\n        ListItemLeft=\"0\" ImageTop=\"1\" Height=\"164\" Width=\"300\" FontSize=16\r\n        Left=\"-112\" Theme=\"@ThemeEnum.Blue\" BorderColor=\"Color.Gray\" HeaderHeight=\"32\"\r\n        HeaderTextVerticalOffset=\"3\" Scale=\"85\"\u003e\r\n        \u003cBodyContent\u003e\r\n            \u003cdiv class=\"down8 right8\"\u003e\r\n                \u003cTimeComponent Name=\"StartTimeComponent\" Parent=\"this\"\r\n\t\t\t\t\tColumn1Width=\"40\" Caption=\"Start Time\" FontSize=\"16\"\r\n\t\t\t\t\tHoursTextBoxLeft=\"-2\" MinutesTextBoxWidth=\"20\"\r\n\t\t\t\t\tMinutesTextBoxLeft=\"0\"\u003e\u003c/TimeComponent\u003e\r\n\t\t\t\u003c/div\u003e\r\n\t\t\u003c/BodyContent\u003e\r\n    \u003c/InformationBox\u003e\r\n\r\n# ValidationComponent is Gone\r\nThe ValidationComponent confused people I have discovered. Instead of having one component that could be\r\na CheckBox, a Multiline TextBox or a TextBox, I broke this up into two new components.\r\n\r\nCheckBoxComponent\r\nTextBoxComponent\r\n\r\nEverything that used be on the ValidationComponent, is now called TextBoxComponent. The only parts that are missing\r\nare the parts related to a CheckBoxMode. This should help with the confusion, since everyone knows what a TextBox is.\r\n\r\nThe other part that changed is the ComboBox in CheckedListMode now uses the CheckBox for each item instead of the\r\nValidationComponents.\r\n\r\n# CalendarComponent Now Has A Year Selector\r\nBy default the year selector is turned off. Set the property AllowYearSelector to true and the year selector appears.\r\n\r\n    AllowYearSelector=\"true\"\r\n\r\nThe Year Selector has decades at the top and the selected decade's year appear below. Select a Year to close the\r\nYear Selector or click the Date Title (Month Year) on the Calendar to toggle it On/ off.\r\n\r\n9.24.2024: Breaking Changing! Easy Fix. I renamed the ValidationComponent to TextBoxComponent, \r\nremoved the CheckBoxMode and created a new CheckBoxComponent. Unless you were using the \r\nCheckedBoxMode of the ValidationComponent, the only thing you should have to do is rename\r\nValidationComponent to TextBoxComponent. I think it confused a lot of people on what the\r\nValidationComponent is. Everyone knows what a TextBox is, so simple is better.\r\n \r\n9.12.2024: Working on a new TimeComponent. \r\n\r\n9.11.2024: I updated DataJuggler.Excelerate. I also fixed a bug with ListItemTop and ListItemLeft,\r\nas they were only applied to Column2. i removed method FindChildByName from IBlazorComponent interface.\r\n\r\n9.9.2024: I added two new properties HeaderFontSize and HeaderFontWeight, which defaults to bold.\r\nI also expanded the InformationBox with a RenderFragment property, allowing a user to put custom content\r\nsuch as text, HTML, Blazor Components or images inside an InformationBox object.\r\nAlso a new enum was created to specifiy ItemsOnly, ItemsOnTop (default) or ItemsOnBottom, and the users\r\ncustom content will render with the Items (if it works, untested yet)\r\n\r\n9.5.2024: I added a Scale property to the Information Box.\r\n\r\n9.1.2024: I added Column1Width and Column2 Width and Column1TextAlign and Column2TextAlign properties\r\nto the the Information Box. Testing now\r\n\r\n8.27.2024: I added some properties to customize the position of items in the Information Box.\r\n\r\n8.13.2024: DataJuggler.UltimateHelper was updated.\r\n\r\n5.30.2024: I created a new component called an InformationBox. This component is used for creating dashboards or reports.\r\n\r\n\u003cimg src=https://github.com/DataJuggler/SharedRepo/blob/master/Shared/Images/SampleInformationBox.png height=215 width=356\u003e\r\n\r\n    \u003cInformationBox Parent=\"this\" Title=\"Summary\" Height=\"204\" Width=\"340\"\r\n        Column1Width=\"180\" Column2Width=\"152\" Column1Left=\"0\" Gap=\"8\"\r\n        Left=\"256\" Theme=\"@ThemeEnum.Blue\" BorderColor=\"Color.Gray\" HeaderHeight=\"32\"\r\n        HeaderTextVerticalOffset=\"3\" Name=\"Summary\"\u003e\r\n    \u003c/InformationBox\u003e\r\n\r\nThe InformationBox is loaded via code. Here is a sample for how to load an InformationBox\r\n\r\nI create a private variable for the InformationBox\r\n\r\n    private InformationBox infoBox;\r\n\r\nAnd from this I create a property. It's optional, but I use Visual Studio package Regionizer2022\r\n\r\nRegionizer2022\r\nhttps://github.com/DataJuggler/Regionizer2022\r\n\r\nMake sure your code file has a Properties region, and select one or more private variables - Click the \r\nCreate Properties button\r\n\r\nA property is created\r\n\r\n    #region InfoBox\r\n    /// \u003csummary\u003e\r\n    /// This property gets or sets the value for 'InfoBox'.\r\n    /// \u003c/summary\u003e\r\n    public InformationBox InfoBox\r\n    {\r\n        get { return infoBox; }\r\n        set { infoBox = value; }\r\n    }\r\n    #endregion\r\n\r\nTo create a HasProperty, I select the word InfoBox, in the line public InformationBox InfoBox\r\nand in Regionizer 2022, I click 'Create Has Property'.\r\n\r\nThis creates a read only property that is a simple method of testing for null\r\n\r\n    #region HasInfoBox\r\n    /// \u003csummary\u003e\r\n    /// This property returns true if this object has an 'InfoBox'.\r\n    /// \u003c/summary\u003e\r\n    public bool HasInfoBox\r\n    {\r\n        get\r\n        {\r\n            // initial value\r\n            bool hasInfoBox = (this.InfoBox != null);\r\n            \r\n            // return value\r\n            return hasInfoBox;\r\n        }\r\n    }\r\n    #endregion\r\n\r\nThen in the Register method of the page or component hosting the InformationBox, make sure the\r\ncomponent implements IBlazorComponentParent. If you have more than one InformationBox on a page\r\nor component, you can refer to them by name to store each component. The example below only has\r\none InformationBox on the page.\r\n\r\nIn the register method, store the object\r\n\r\n    if (component is InformationBox)\r\n    {\r\n        // Store\r\n        InfoBox = component as InformationBox;\r\n        \r\n        // test only\r\n        List\u003cItem\u003e items = CreateSampleInfoBoxItems();\r\n        \r\n        // if the value for HasInfoBox is true\r\n        if (HasInfoBox)\r\n        {\r\n            // Set the Items\r\n            InfoBox.SetItems(items);\r\n            \r\n            // Update the UI\r\n            InfoBox.Refresh();\r\n        }\r\n    }\r\n\r\nAnd this method CreateSampleInfoBoxItems demonstrates how to load a list of items\r\n\r\nTip: Notice the code for the image for the first item. You can place an image on the left or right of text,\r\nby selecting the ImageAlignment.\r\n\r\n    #region CreateSampleInfoBoxItems()\r\n    /// \u003csummary\u003e\r\n    /// returns a list of Sample Info Box Items\r\n    /// \u003c/summary\u003e\r\n    public List\u003cItem\u003e CreateSampleInfoBoxItems()\r\n    {\r\n        // initial value\r\n        List\u003cItem\u003e items = new List\u003cItem\u003e();\r\n        \r\n        // Create a new instance of an 'Item' object.\r\n        Item item = new Item();\r\n        item.Caption = \"Acceptable Pressure Test?\";\r\n        item.Text = \"Yes\";\r\n        \r\n        // image\r\n        item.IncludeImage = true;\r\n        item.ImageAlignment = ImageAlignmentEnum.ImageOnLeftOfText;\r\n        item.ImageWidth = 16;\r\n        item.ImageHeight = 16;\r\n        item.ImageUrl = \"../Images/GreenCircle.png\";\r\n        \r\n        // Add this item\r\n        items.Add(item);\r\n        \r\n        // Create a new instance of an 'Item' object.\r\n        item = new Item();\r\n        item.Caption = \"PSI Loss to Leak?\";\r\n        item.Text = \"30.1 psi\";\r\n        \r\n        // Add this item\r\n        items.Add(item);\r\n        \r\n        // Create a new instance of an 'Item' object.\r\n        item = new Item();\r\n        item.Caption = \"Total Test Time\";\r\n        item.Text = \"8 Hours 0 Minutes\";\r\n        \r\n        // Add this item\r\n        items.Add(item);\r\n        \r\n        // Create a new instance of an 'Item' object.\r\n        item = new Item();\r\n        item.Caption = \"Min Test Duration Met?\";\r\n        item.Text = \"Yes\";\r\n        \r\n        // Add this item\r\n        items.Add(item);\r\n        \r\n        // Create a new instance of an 'Item' object.\r\n        item = new Item();\r\n        item.Caption = \"Min Test Pressure Met?\";\r\n        item.Text = \"Yes\";\r\n        \r\n        // Add this item\r\n        items.Add(item);\r\n        \r\n        // Create a new instance of an 'Item' object.\r\n        item = new Item();\r\n        item.Caption = \"MAOP Verified By Test\";\r\n        item.Text = \"452 psi\";\r\n        \r\n        // Add this item\r\n        items.Add(item);\r\n        \r\n        // Create a new instance of an 'Item' object.\r\n        item = new Item();\r\n        item.Caption = \"Desired MAOP\";\r\n        item.Text = \"400 psi\";\r\n        \r\n        // Add this item\r\n        items.Add(item);\r\n        \r\n        // Create a new instance of an 'Item' object.\r\n        item = new Item();\r\n        item.Caption = \"Test Within Pressure Bounds?\";\r\n        item.Text = \"Yes\";\r\n        \r\n        // Add this item\r\n        items.Add(item);\r\n        \r\n        // return value\r\n        return items;\r\n    }\r\n    #endregion\r\n\r\n5.24.2024\r\n8.8.8: New Properties were added to the ComboBox to control the height of the TextBox for the CalendarComponent\r\n\r\n# Update 5.18.2024\r\n\r\nNew Video:\r\n\r\nFirst Ever Opensource Saturday - Sunday Edition\r\nhttps://youtu.be/uxa1xR6xpzk\r\n\r\n5.8.2024: I spent a week refactoring the Combo Box. I realized my first combobox wasn't a standard combobox.\r\nNow, if you are in regular mode (not checklist mode), you can type T twice for Texas in a States list, for example.\r\nI have a new sample project called 'NTouch', that demonstrates the ComboBox and the Calendar.\r\n\r\nNTouch\r\nhttps://github.com/DataJuggler/NTouch/\r\n\r\n# Example using the Combobox in regular mode (not CheckListMode)\r\n\r\n    \u003cComboBox Name=\"StateComboBox\" Theme=ThemeEnum.Blue Unit=\"px\" HeightUnit=\"px\" Height=\"32\" ZIndex=\"80\"\r\n        LabelText=\"State:\" Width=\"224\" Parent=\"this\" ButtonHeight=24 ButtonWidth=24 ControlHeight=\"32\"\r\n        DropdownClassName=\"container2 border1gray textdonotwrap\" TextBoxLeft=\"0\" ButtonTop=-5 ButtonLeft=-26\r\n        ListItemWidth=\"120\" ListZIndex=80 ListItemTop=24\r\n        Column2Width=\"128\" Position=\"relative\" Top=\"0\" LabelClassName=\"down4 right2\" TextBoxWidth=\"124\"\u003e\r\n    \u003c/ComboBox\u003e\r\n\r\nNotice the attribute Parent=this on Line 2. This is how the ComboBox registers with its parent. To use this feature, you probably \r\nhave to supress the warning BL0007 in the project properties. Microsoft doesn't like code in Setters, but this is how all\r\nIBlazorComponents and IBlazorComponentParents talk to each other. \r\n\r\nNew video coming soon.\r\n\r\nHere is the css you must put in the client project that uses the ComboBox. Notice line 3 DropDownClassName\r\n\r\nUpdate 6.22.2025: This class has been added to DataJuggler.Blazor.Components.css file.\r\n\r\n    .combobox-container\r\n    {\r\n        position: absolute;               \r\n    }\r\n\r\nFeel free to adjust the height and width as needed. The position absolute is the key to the Drop Down showing, without\r\nmoving other content (spent a while on this). Border1Gray is shown below.\r\n\r\n# Example using the Combobox in CheckListMode\r\n\r\n    \u003cComboBox Name=\"TargetFrameworkComboBox\" Theme=ThemeEnum.Blue Unit=\"px\" HeightUnit=\"px\" Height=\"32\"\r\n        LabelText=\"Target:\" Width=\"224\" Parent=\"this\" ButtonHeight=24 ButtonWidth=24 \r\n        CheckedListClassName=\"combobox-container border1gray textdonotwrap\" TextBoxLeft=\"1\" ButtonTop=-5 ButtonLeft=-4\r\n        Column2Width=\"128\" Position=\"relative\" Top=\"4\" LabelClassName=\"down4 right2\" TextBoxWidth=\"124\" \r\n        CheckListMode=true CheckedListUnit=\"vw\" CheckedListHeightUnit=\"vh\" CheckedListheight=\"4\" ListItemHeight=\"2.4\"\r\n        CheckedListItemLeft=\"2\" CheckedListItemTop=1 ListItemBackgroundColor=Color.White\r\n        CheckBoxX=\"-3.2\" CheckBoxY=\".4\" CheckBoxTextX=\"-3\"  CheckBoxTextY=\"0\" \r\n        CheckedListWidth=8 CheckedListTop=\"24\" CheckedListLeft=\"48\" ListItemWidth=10\u003e\r\n    \u003c/ComboBox\u003e\r\n\r\nIt is important to note the CheckedListClassName on line 3. I have two CSS classes set in an External project, that are the key\r\nto making the Z-Index work. I tried using an internal CSS Class, and haven't had much luck. Will try again later.\r\n\r\n    .border1\r\n    {\r\n        border-width: 1px;\r\n        border-style: solid;\r\n        border-color: black;\r\n    }\r\n    .border1gray\r\n    {\r\n        border-width: 1px;\r\n        border-style: solid;\r\n        border-color: gray;\r\n    }\r\n    .container\r\n    {\r\n        display: inline-block;\r\n        height: 16vh;\r\n        min-height: 16vh;\r\n        max-height: 16vh;\r\n        width: 16vw  !important;\r\n        max-width: 16vw  !important;\r\n        min-width: 16vw !important; \r\n        position: relative;\r\n        left: 0vw;\r\n        overflow: visible !important;\r\n        z-index: 200 !important;\r\n        background-color: white;    \r\n    }\r\n\r\n5.1.2024: I added a ZIndex property to the Calendar. If you have two calendar components near each other, the first one can't type.\r\nWill work on a solution later, but the ZIndex should allow a fix.\r\n\r\n4.30.2024: Version 8.6.22 fixes the textbox and button jumping around when the calendar showed, by adding min-height and max-height\r\nproperties to the ContainerStyle BlazorStyled class.\r\n\r\n4.29.2024: I added few more tweaks to the CalendarComponent, to make it easier to use. \r\nI think a good future feature might be if you click on the Year label, a combobox opens with a selection of years.\r\nFor things like Birthday, scrolling dozens of years isn't worth it. You can always type it, but a year selector might\r\nbe worth exploring.\r\n\r\n4.27.2024: Eureka! I have done it. I built a working CalendarComponent, and being it has been tested by all of 1 person in all\r\nof 1 project(s), I am pretty excited. If this doesn't make it worth the price, and make you willing to leave a star on GitHub\r\nor Subscribe to my YouTube channel, nothing will. \r\n\r\n\u003cimg src=https://github.com/DataJuggler/SharedRepo/blob/master/Shared/Images/Calendar.png height=219 width=336\u003e\r\n\r\n# Calendar Example\r\n\r\n   \u003cCalendarComponent Name=\"OrderDateControl\" Parent=\"this\" Caption=\"Start Date:\" TextBoxHeight=\"21\" CalendarTop=\"-28\"\r\n    DayRowLeft=\"0\" DayButtonContainerLeft=\"2\" CellWidth=28 DayButtonWidth=32 DayRowTextColor=\"Color.GhostWhite\"\r\n    LabelColor=\"Color.Coral\" LabelFontName=\"Calibri\" LabelFontSize=\"18\" DayRowColor=\"Color.Firebrick\"\r\n    LabelClassName=\"down4 right2\" ButtonLeft=\"-6\" CalendarLeft=\"260\" Top=\"24\" Left=\"-16\" \r\n    TextBoxWidth=\"124\" ZIndex=\"160\"\u003e\u003c/CalendarComponent\u003e          \r\n\r\nI created a new repository for a project called NTouch. You can run NTouch now and see an example.\r\n\r\nNTouch\r\nhttps://github.com/DataJuggler/NTouch\r\n\r\n4.24.2024: To celebrate the coming milestone of 200,000 installs coming up this summer, I am working on a Calendar Component.\r\nThe Calendar Component is in this release (8.5.0), but it is far from being to use. What I am testing now is the text box shows up,\r\nthe button shows up, and if you click the button, the pop up calendar div shows and goes away as you toggle the button.\r\nSoon I will add buttons for the calendar. Baby steps.\r\n\r\n4.23.2024: I had some problems running the Blazor Server App projects in .NET 8. The problem was browsers (Chrome) are depreciating \r\nPage Unload events, and blazor.server.js is the culprit. I switched to a web app and things work.\r\nThe one important thing I noticed, linking to a CSS class like this seems to not work in a Blazor Web Project (not Blazor Server App Template)\r\n\r\n    \u003clink href=\"~/_content/DataJuggler.Blazor.Components/css/DataJuggler.Blazor.Components.css\" rel=\"stylesheet\" /\u003e\r\n\r\nRemoving the Tilde seems to work.\r\n\r\n    \u003clink href=\"/_content/DataJuggler.Blazor.Components/css/DataJuggler.Blazor.Components.css\" rel=\"stylesheet\" /\u003e\r\n\r\n4.18.2024: The conversion to using BlazorStyled again has completed. Testing in progress, but seems to work.\r\n\r\n4.17.2024: I added back BlazorStyled, but I forked the project and created a NuGet package DataJuggler.BlazorStyled.\r\nI didn't make any code changes, all I did was upgrade the component to .NET 8 and the dependencies.\r\n\r\n4.8.2024: I modified the grid with a new property 'NotifyParentOnDoubleClick'. You can set\r\nan ExternalId and ExternalIdDescription when you create the rows. \r\nI also added an EnableClick function for a Grid row. The Click does work. Testing the DoubleClick now.\r\nthe parent object will receive a message. Optionally, Set the ExternalId and ExternalId Description.\r\n\r\n4.5.2024: ImageButton does not have a ClassName property.\r\n\r\n4.4.2024: I removed the dependency on Blazor Styled. Blazor Styled hasn't been updated since \r\n.NET Core 3.1, and I found you can create a Style section on any razor page and do the same thing\r\nwithout Blazor Styled, and with better results it seems of late.\r\n\r\n12.30.2023: I updated the CheckBox to send a message to its Parent when it's value changes.\r\nI added SetLabelColor method to the TextBoxComponent.\r\n\r\nI created a new project that uses these controls.\r\n\r\nSnow Creator\r\nhttps://github.com/DataJuggler/SnowCreator\r\n\r\nLive Demo:\r\nhttps://snowcreator.datajuggler.com \r\n\r\n12.28.2023: I fixed a bug with the CheckedListBox where the ListItemHeight was wrong.\r\n\r\n12.27.2023: I added the !important attribute to the ListItemZIndex CSS and ListItemHeight and CheckedListHeight.\r\n\r\n12.26.2023: I updated DataJuggler.NET8 and DataJuggler.Excelerate Nuget packages.\r\n\r\n12.18.2023 I fixed a bug with the TextBoxComponent\r\nIf is valid is true, I set the label to the invalid label color. This is now fixed.\r\n\r\n11.15.2023 I updated the project to .NET 8\r\n\r\nFor .NET 7, use a 7.x version.\r\n\r\n11.10.2023: I added a Label\r\n\r\nThe Label provides a simple way to display text.\r\n\r\n11.8.2023 New Video For 100,000 Installs\r\n\r\nVersion 7.13.7\r\n\r\nHow To Use DataJuggler.Blazor.Components Grid\r\nhttps://youtu.be/_qDo9pNT5a8\r\n\r\nVersion 7.13.5\r\nNovermber 7, 2023: DataJuggler.Blazor.Components passed 100,000 Downloads\r\nI updated the Grid and created a new sample project to demo the Grid.\r\n\r\nThe sample project is called BubbleReportWeb\r\nhttps://github.com/DataJuggler/BubbleReportWeb\r\n\r\nVersion 7.12.8\r\nNovember 2, 2023: I added a ClassName parameter to the Grid\r\n\r\nAugust 29, 2023: \r\n\r\nNew Video: DataJuggler.Blazor.Components reaches 75,000 Installs\r\nhttps://youtu.be/WkcwQ9kOfw4\r\nIn this short video I show a demo of code generating classes from Blazor Excelerate.\r\n\r\nAugust 26, 2023: In celebration of 75,000 NuGet installs, I added two new features.\r\nFirst, I created a CheckedListBox component. I also added a new feature to the ComboBox,\r\nand that new features is a CheckedListMode. The combobox now supports check boxes and \r\nmultiple selections.\r\n\r\nJuly 22, 2023: More updates  to NuGet package DataJuggler.Excelerate, and I need this update for my project \r\nBlazor Excelerate\r\n\r\nJuly 21, 2023: I updated NuGet package DataJuggler.Excelerate, and I need this update for my project \r\nBlazor Excelerate\r\n\r\nJuly 18, 2023: I fixed the checkbox component. The binding wasn't working when I thought I fixed it last time.\r\n\r\nJuly 9, 2023: I removed floats from the ComboBox component. I was having trouble \"stacking\" a TextBoxComponent\r\nbelow a ComboBox, so hopefully this fixes it. I also added a ComboBoxWidth parameter property on the ComboBox.\r\n\r\nJuly 6, 2023: I added an AutoComplete property, which defaults to false.\r\nThe reason for this is browsers like to fill in values, and the browser is confusing Email Address and User Name fields.\r\n\r\nJuly 2, 2023: I removed the floats from the TextBoxComponent. This will probably break\r\nsome existing users, but I am trying to make the control more consistant to work with.\r\nI also added a MarginBottom property. Use this in conjunction with the HeightUnit, which\r\ndefaults to px (pixels) and the MarginBottom is set to 8 by default. \r\n\r\nJune 21, 2023: I updated DataJuggler.UltimateHelper.\r\n\r\nJune 3, 2023 B: I updated the Sprite component to have a SetVisible and optional parameter for Hide\r\nwhen you call Stop.\r\n\r\nJune 3, 2023: My first attempt at Disabled for the Validation Component was wrong. I think my fix will work. Testing now.\r\n\r\nJune 2, 2023: I added an Enabled property and a method SetEnabled to the validation component.\r\nIf Enabled is false, disabled will appear in the input objects and be read only.\r\n\r\n5.8.2023: Nuget package DataJuggler.Blazor.Components reached 50,000 installs today.\r\n\r\n3.8.2023: Nuget package DataJuggler.Blazor.Components reached 40,000 installs today.\r\n\r\n# Sample Projects\r\n\r\nI created a new project that uses the TextBoxComponent.\r\n\r\n# Blazor Gallery\r\n\r\nLive Demo\r\n\r\nBlazor Gallery\u003cbr\u003e\r\nhttps://blazorgallery.com \r\n\r\nBlazor Gallery Source\u003cbr\u003e\r\nhttps://github.com/DataJuggler/BlazorGallery\r\n\r\n# Video\r\nBlazor Gallery Deserves A Star\u003cbr\u003e\r\n[![Blazor Gallery Deserves A Star Video](https://img.youtube.com/vi/HAMgeaCuvHY/0.jpg)](https://www.youtube.com/watch?v=HAMgeaCuvHY)\r\n\r\n# Blazor Excelerate\r\n\r\nLive Demo\r\n\r\nBlazor Excelerate\r\nhttps://excelerate.datajuggler.com \r\nCode Generate C# Classes From Excel Header Rows\r\n\r\nBlazor Excelerate Source\r\nhttps://github.com/DataJuggler/Blazor.Excelerate\r\n\r\nGetting Started:\r\n\r\n# Important\r\n\r\nThis project has a dependency on DataJuggler.BlazorStyled (a port of BlazorStyled by chanan. Both will work, but \r\nthe forked version has been upgraded for .NET8.)\r\n\r\nAdd the following to program.cs:\r\n\r\nusing DataJuggler.BlazorStyled;\r\n\r\nbuilder.Services.AddBlazorStyled();\r\n    \r\n# New Video - 50,000 NuGet Installs\r\n\r\nBuildCopy https://github.com/DataJuggler/BuildCopy\r\n\r\nBuildCopy will copy the files from a Visual Studio solution to an output folder. In this case, the output folder is ProjectTemplates\\Working\\Templates. BuildCopy also allows you to set ignore folders, so I do not copy the .vs, .git, .bin, .obj, .templateconfig and a few others.\r\n\r\nHere is a video showing you how to setup this project, build the data tier for Blazor Gallery, and build your own DataTier.Net projects.\r\n\r\nHow To Create A NuGet Package For A Blazor Site\r\nhttps://youtu.be/K5WbNKUPDGs\r\n\r\nWant To Help Contribute to this project?\r\nVolunteer to take the instructions from the video and write them out as step by step. Bonus with images and screen shots.\r\n\r\nIf you think this project is worth the price, please leave a star and / or subscribe to my YouTube channel: https://youtube.com/DataJuggler\r\n\r\nThanks\r\n\r\nOne of my favorite parts of this project is the DataJuggler.Blazor.Componets.css file.\r\n\r\nAfter adding nuget package DataJuggler.Blazor.Componets Nuget package, add the folloing line to\r\nyour _layout.cshtml file in your Blazor project:\r\n\r\n    \u003clink href=\"_content/DataJuggler.Blazor.Components/css/DataJuggler.Blazor.Components.css\" rel=\"stylesheet\" /\u003e\r\n\r\nView the full CSS here:\r\nhttps://github.com/DataJuggler/DataJuggler.Blazor.Components/blob/master/wwwroot/css/DataJuggler.Blazor.Components.css\r\n\r\nThe CSS file has values to make it easy to position and style components.\r\n\r\nCSS classes can be combined using spaces like:\r\n\r\n    \u003cdiv class=\"width16 backgroundcolorskyblue marginleft8 down12\"\u003e\u003c/div\u003e\r\n\r\nbackground(color name) \r\nExample: backgroundlemonchiffon\u003cbr\u003e\r\nSet the background color to a .NET named color.\r\n\r\nSet Colors:\r\nhttps://learn.microsoft.com/en-us/dotnet/api/system.windows.media.colors?view=windowsdesktop-7.0\r\n\r\ncolor(color name)\r\nExample: colormidnightblue.\r\nSet the forecolor to a .NET named color.\r\n\r\ndisplayblock, displayinline, displaylineblock, displaynone.\r\n\r\ndown(0 - 1000)\r\nExample: down16\r\nMove the element 16 pixels down. (CSS is top: 16px).\r\n\r\nheight(0 - 1000)\r\nExample: height18\r\nSet the height, minheight and maxheight to 18 pixels.\r\n\r\nleft(0 - 1000)\r\nExample: left40\r\nMove the element 40 pixels to the left (Css is right: 40px).\r\n\r\nmarginbottom(0 - 600)\r\nExample: marginbottom200\r\nGive the element a bottom margin of 200 pixels.\r\n\r\nmarginleft(0 - 600)\r\nExample: marginleft24\r\nGive the element a left margin of 24 pixels.\r\n\r\nmarginright(0 - 600)\r\nExample: marginright64\r\nGive the element a right margin of 64 pixels.\r\n\r\nmargintop(0 - 600)\r\nExample: margintop90\r\nGive the element a top margin of 90 pixels.\r\n\r\nright(0 - 1000)\r\nExample: right128\r\nMove the element 128 pixels to the right (Css is left: 128px).\r\n\r\nup(0 - 1000)\r\nExample: up12\r\nMove the element up 12 pixels. (Css is bottom: 12px)\r\n\r\nwidth(0 - 1000)\r\nExample: width640\r\nSet the width, min-width and max-width in pixels. In this example 640.\r\n\r\n## TextBoxComponent\r\n\r\n### Example\r\n\r\n    \u003cTextBoxComponent Name=\"ResultsControl\" Caption=\"Results:\" Parent=\"this\" Unit=\"px\" Column1Width=\"64\" Column2Width=\"480\" TextBoxWidth=\"480\" \r\n        LabelClassName=\"down8\" Left=\"0\" MarginLeft=\"4\" Multiline=true HeightUnit=\"vh\" Height=\"20\" Top=0 LabelFontSizeUnit=\"em\" \r\n        LabelFontSize=\".8\"\u003e\u003c/TextBoxComponent\u003e\r\n\r\nThis componet can serve as a CheckBox, a TextBox or a TextArea.\r\n\r\nRegister the componet by setting the parent=this, and your parent needs to implement\r\nIBlazorComponentParent interface.\r\n\r\nAdd the following line in your parent component.\r\n\r\nusing DataJuggler.Blazer.Components.Interfaces;\r\n\r\nTip: Use partial classes for your components. To do this, in your project add a CS class with the same name\r\nas your component. Name your class such as this:\r\n\r\nExample: \r\nGrid.razor\r\nGrid.razor.cs (partial class)\r\n\r\npublic partial class Grid : ComponentBase, IBlazorComponent, IBlazorComponentParent\r\n\r\nAs you can see above, the Grid implements IBlazorComponet and IBlazorComponentParent.\r\n\r\nVisual Studio makes it easy to implement interfaces. Right click the interface name, and select\r\nQuick Actions and Refactoring \u003e Implement Interface.\r\n\r\nThis will stub out the properties and methods needed to implement the interface.\r\n\r\nTo see an example of registering components, see the project Blazor Excelerate linked\r\nat the top of this document. Look for a method called Register. Once registered then your\r\ncomponents can talk to each other using the ReceiveData method and by passing Message objects.\r\n\r\n# Update 11.7.2023: I just published a new project to Demo Grids\r\nhttps://github.com/DataJuggler/BubbleReportWeb\r\n\r\nThis is a sample mark up for a grid. The parent of the grid must implement DataJuggler.Blazor.IComponentParent\r\n\r\n    \u003cGrid Name=\"TopStreaksStockGrid\" ClassName=\"grid\" Unit=\"px\" Width=\"310\" HeightUnit=\"px\" Height=278\r\n        ShowHeader=\"true\" HeaderText = \"Top Streak Stocks\" HeaderClassName = \"width320 textaligncenter\"\r\n        ShowColumnHeaders=true Parent=\"this\" Left=\"40\" Top=-24 FontSize=\"12\"\u003e\u003c/Grid\u003e\r\n\r\nNotice the property Parent=\"this\" on the bottom line. This is how the grid is registered with the parent.\r\n\r\nView the code for the BubbleReportWeb above, and view the code for Index.razor.cs. The Register method has multiple grid properties.\r\n\r\n    private Grid topStreakGrid;\r\n\r\n    /// \u003csummary\u003e\r\n    /// This property gets or sets the value for 'TopStreakGrid'.\r\n    /// \u003c/summary\u003e\r\n    public Grid TopStreakGrid\r\n    {\r\n        get { return topStreakGrid; }\r\n        set { topStreakGrid = value; }\r\n    }\r\n\r\nOne important thing to note, is the grid works best when you register DataJuggler.Blazor.Components.css in your project like this:\r\n    \r\n    \u003clink href=\"/_content/DataJuggler.Blazor.Components/css/DataJuggler.Blazor.Components.css\" rel=\"stylesheet\" /\u003e\r\n\r\nRemoving the tilde seems necessary for Blazor Web Apps (latest .NET8 Template). I will do more testing when I get a chance and confirm this works in both.\r\n\r\nThe above CSS class is included with NuGet package DataJuggler.Blazor.Components\r\n\r\nThe grid can be loaded via code in the OnAfterRenderAsync event:\r\n\r\n    protected async override Task OnAfterRenderAsync(bool firstRender)\r\n    {\r\n        // if the TopStreakGrid exists\r\n        if (HasTopStreakGrid)\r\n        {\r\n            // create the rows\r\n            List\u003cRow\u003e rows = CreateRowsForTopStreakStocks();\r\n            \r\n            // Set the Row\r\n            TopStreakGrid.Rows = rows;\r\n            \r\n            // Refresh the Grid\r\n            TopStreakGrid.Refresh();\r\n        }\r\n    }\r\n\r\n# Loading Grid Rows and Columns\r\n\r\nIn this example, I added two using statements to avoid the conflict between DataJuggler.Excelerate.Row and DataJuggler.Excelerate.Column\r\nOfficeOpenXml.Row and OfficeOpenXml.Column. DataJuggler.Blazor.Excelerate is installed when you add DataJuggler.Blazor.Components\r\nto a project via NuGet.\r\n\r\nNote: The Gateway class listed below is created when you create a project via DataTier.Net. You can use EntityFramework or another ORM\r\nif you prefer. I like DataTier.Net because it uses all stored procedures.\r\n\r\nDataTier.Net (Optional)\r\nhttps://github.com/DataJuggler/DataTier.Net\r\n\r\n    using Row = DataJuggler.Excelerate.Row;\r\n    using Column = DataJuggler.Excelerate.Column;\r\n\r\n    /// \u003csummary\u003e\r\n    /// returns a list of Rows For Top Streak Stocks\r\n    /// \u003c/summary\u003e\r\n    public List\u003cRow\u003e CreateRowsForTopStreakStocks()\r\n    {\r\n        // initial value\r\n        List\u003cRow\u003e rows = new List\u003cRow\u003e();\r\n        \r\n        // Load the Gateway\r\n        Gateway gateway = new Gateway(Connection.Name);\r\n        \r\n        // Load the topStocks\r\n        List\u003cTopStreakStocks\u003e topStocks = gateway.LoadTopStreakStocks();\r\n        \r\n        // If the topStocks collection exists and has one or more items\r\n        if (ListHelper.HasOneOrMoreItems(topStocks))\r\n        {\r\n            // Create Column and set properties\r\n            Column column = new Column();\r\n            column.Caption = \"Symbol\";\r\n            column.ColumnName = \"Symbol\";\r\n            column.Index = 0;\r\n            column.ColumnNumber = 1;\r\n            column.ColumnText = \"Symbol\";\r\n            column.Width = 48;\r\n            column.Height = 16;\r\n            column.ClassName = \"displayinlineblock width48 colorwhite textalignleft down4 right16 fontsize12\";\r\n            \r\n            // Add this column\r\n            TopStreakGrid.Columns.Add(column);\r\n            \r\n            // Create Column and set properties\r\n            Column column2 = new Column();\r\n            column2.Caption = \"Name\";\r\n            column2.ColumnName = \"Name\";\r\n            column2.Index = 1;\r\n            column2.ColumnNumber = 2;\r\n            column2.ColumnText = column2.Caption;\r\n            column2.Width = 140;\r\n            column2.Height = 16;\r\n            column2.ClassName = \"displayinlineblock width140 colorwhite textalignleft down4 right16 fontsize12\";\r\n            \r\n            // Add Column 2 to the header row\r\n            TopStreakGrid.Columns.Add(column2);\r\n            \r\n            // Create Column and set properties\r\n            Column column3 = new Column();\r\n            column3.Caption = \"Last\";\r\n            column3.ColumnName = \"LastClose\";\r\n            column3.Index = 2;\r\n            column3.ColumnNumber = 3;\r\n            column3.ColumnText = column3.Caption;\r\n            column3.Width = 48;\r\n            column3.Height = 16;\r\n            column3.ClassName = \"displayinlineblock width48 colorwhite textalignleft down4 right30 fontsize12\";\r\n            \r\n            // Add this column\r\n            TopStreakGrid.Columns.Add(column3);\r\n            \r\n            // Create Column and set properties\r\n            Column column4 = new Column();\r\n            column4.Caption = \"Streak\";\r\n            column4.ColumnName = \"Streak\";\r\n            column4.Index = 3;\r\n            column4.ColumnNumber = 4;\r\n            column4.ColumnText = column4.Caption;\r\n            column4.Width = 48;\r\n            column4.Height = 16;\r\n            column4.ClassName = \"displayinlineblock width48 colorwhite textalignleft down4 right16 fontsize12\";\r\n            \r\n            // Add this column\r\n            TopStreakGrid.Columns.Add(column4);\r\n            \r\n            foreach (TopStreakStocks topStock in topStocks)\r\n            {\r\n                // Create a row\r\n                DataJuggler.Excelerate.Row row = new DataJuggler.Excelerate.Row();\r\n                row.ClassName = \"textdonotwrap width448 height16 marginbottom0 down8\";\r\n                \r\n                // Create Column and set properties\r\n                column = new Column();\r\n                column.Caption = \"Symbol\";\r\n                column.ColumnName = \"Symbol\";\r\n                column.Index = 0;\r\n                column.ColumnNumber = 1;\r\n                column.ColumnText = topStock.Symbol;\r\n                column.Unit = \"px\";\r\n                column.Width = 48;\r\n                column.Height = 16;\r\n                column.ClassName = \"displayinlineblock width48 colorwhite textalignleft right16 fontsize12\";\r\n                \r\n                // Add this column\r\n                row.Columns.Add(column);\r\n                \r\n                // Create Column and set properties\r\n                column2 = new Column();\r\n                column2.Caption = \"Name\";\r\n                column2.ColumnName = \"Name\";\r\n                column2.Index = 1;\r\n                column2.ColumnNumber = 2;\r\n                column2.ColumnText = topStock.ShortName.ToString();\r\n                column2.Width = 140;\r\n                column2.Height = 16;\r\n                column2.ClassName = \"displayinlineblock width140 colorwhite textalignleft right16 fontsize12\";\r\n                \r\n                // Add this column\r\n                row.Columns.Add(column2);\r\n                \r\n                // Create Column and set properties\r\n                column3 = new Column();\r\n                column3.Caption = \"Last Close\";\r\n                column3.ColumnName = \"LastPrice\";\r\n                column3.Index = 2;\r\n                column3.ColumnNumber = 3;\r\n                column3.ColumnText = topStock.LastClose.ToString(\"C\");\r\n                column3.Width = 48;\r\n                column3.Height = 16;\r\n                column3.ClassName = \"displayinlineblock width48 colorwhite textalignright right8 fontsize12\";\r\n                \r\n                // Add this column\r\n                row.Columns.Add(column3);\r\n                \r\n                // Create Column and set properties\r\n                column4 = new Column();\r\n                column4.Caption = \"Streak\";\r\n                column4.ColumnName = \"Streak\";\r\n                column4.Index = 3;\r\n                column4.ColumnNumber = 4;\r\n                column4.ColumnValue = topStock.Streak;\r\n                column4.ColumnText = topStock.Streak.ToString();\r\n                column4.Width = 48;\r\n                column4.Height = 16;\r\n                column4.ClassName = \"displayinlineblock width48 colorwhite textaligncenter right16 fontsize12\";\r\n                \r\n                // Add this column\r\n                row.Columns.Add(column4);\r\n                \r\n                // Add this row\r\n                rows.Add(row);\r\n            }\r\n        }\r\n        \r\n        // return value\r\n        return rows;\r\n    }\r\n\r\nIf you have any questions, please feel free to ask on Git Hub:\r\nhttps://github.com/DataJuggler/DataJuggler.Blazor.Components/Issues\r\n\r\n# DataJuggler.Blazor.Components\r\nThis class consists of an ImageButton, ProgressBar, Sprite, TextBoxComponent, ComboBox,\r\nCheckedListBox and a Grid.\r\n\r\n# CheckedListBox\r\n\r\nUpdate 8.26.2023: If you need to hide the CheckedListBox, before hiding you need to store\r\nthe selections. Look at the code for the ComboBox.ButtonClickedEvent to see an example where\r\nit calls StoreSelections. This checks the Items in memory if the checkboxes have been checked.\r\nI have tried doing this dynamically as the items are checked, and had numeroius problems.\r\n\r\n\r\nUpdate 11.8.2022: This project has been updated to .NET 7.\r\n\r\nDataJuggler.Excelerate has been added to add Rows and Columns for the Grid.\r\n\r\nI also added a new CSS file:\r\n\r\n# DataJuggler.Blazor.Components.css\r\n\r\nhttps://github.com/DataJuggler/DataJuggler.Blazor.Components/blob/master/wwwroot/css/DataJuggler.Blazor.Components.css\r\n\r\nDataJuggler.Blazor.Components.css has classes that I find useful in styling blazor components.\r\n\r\nTo use this file, after adding Nuget package DataJuggler.Blazor.Components, add the following link to your _layout.cshtml file:\r\n\r\n    \u003clink href=\"~/_content/DataJuggler.Blazor.Components/css/DataJuggler.Blazor.Components.css\" rel=\"stylesheet\" /\u003e\r\n    \r\nThis will make all the classes in the file available to your project.\r\n\r\n# Examples:\r\n\r\n# Background Color\r\nBackground color is in the format backgroundcolor + the known color name.\r\n\r\n    .backgroundcolorskyblue\r\n    {\r\n        background-color: skyblue;\r\n    }\r\n\r\n# Foreground Color\r\nBackground color is in the format color + the known color name.\r\n\r\n    .colorforestgreen\r\n    {\r\n        color: forestgreen;\r\n    }\r\n\r\n# Height\r\nHeight is in the format height + the height value in pixels\r\n\r\nHeight values range from 0 - 1,000.\r\n\r\n    .height75\r\n    {\r\n        height: 75px;\r\n        min-height: 75px;\r\n        max-height: 75px;\r\n    }\r\n\r\n# Width\r\nWidth is in the format width + the width value in pixels\r\n\r\nWidth values range from 0 - 1,000.\r\n\r\n    .width596\r\n    {\r\n        width: 596px;\r\n        min-width: 596px;\r\n        max-width: 596px;\r\n    }\r\n\r\n# Margin\r\nMargin is in the format margin + direction (top, left, bottom, right) + the margin value in pixels:\r\n\r\nMargin ranges from 0 - 600\r\n\r\n    .marginleft200\r\n    {\r\n        margin-left: 200px;\r\n    }\r\n\r\n    .marginright12\r\n    {\r\n        margin-right: 12px;\r\n    }\r\n\r\nA few extras:\r\n\r\n    .textalignleft\r\n    {\r\n        text-align: left;\r\n    }\r\n    .textalignright\r\n    {\r\n        text-align: right;\r\n    }\r\n    .textaligncenter\r\n    {\r\n        text-align: center;\r\n    }\r\n    .textdonotwrap\r\n    {\r\n        white-space: nowrap !important;\r\n    }\r\n\r\nI find these classes useful for Blazor components, because you can combine them and it saves creating inline styles.\r\n\r\n    # Excample of multiple classes applied to an element.\r\n    column2.ClassName = \"width120 textalignleft marginleft4 colorwhite\";\r\n\r\n\r\nUpdate 10.22.2021:\r\n\r\nI just released a full working sample here:\r\nhttps://github.com/DataJuggler/Blazor.Excelerate\r\n\r\nAnd a live example is here:\r\nhttps://excelerate.datajuggler.com\r\n\r\nBlazor Excelerate is used to code generate C# classes from an Excel header row.\r\n\r\n--\r\n\r\nThe TextBoxComponent is a multi-use component that allows you to build data entry\r\nscreens quickly. \r\n\r\nBelow is a quick sample to get you started using it.\r\n\r\nInstall Package DataJuggler.Blazor.Components\r\n\r\n# Directly on a .razor page or component:\r\n@using DataJuggler.Blazor.Components\r\n@using DataJuggler.Blazor.Components.Interfaces;\r\n\r\n# Partial Class (code behind)\r\nusing Microsoft.AspNetCore.Components;\u003cbr\u003e\r\nusing DataJuggler.Blazor.Components;\u003cbr\u003e\r\nusing DataJuggler.Blazor.Components.Interfaces;\u003cbr\u003e\r\n\r\n# Component in a razor app\r\n\u003cProgressBar Subscriber=this Increment=\"5\" Interval=\"50\"\r\n    Continuous=\"false\" HideWhenFinished=\"true\"\u003e\u003c/ProgressBar\u003e\r\n    \r\nThe hosting page or component must implement the IProgressSubscriber interface.\r\n\r\n# Implementing IProgressSubscriber Interface\r\nThis interface contains two simple methods and one property.\r\n\r\npublic partial class Index : IProgressSubscriber\r\n{\r\n   ...\r\n}\r\n\r\n# IProgressSubscriber Interface Methods\r\n\r\n# Refresh\r\n\r\n    /// \u003csummary\u003e\r\n    /// This method is called by the ProgressBar when as it refreshes.\r\n    /// \u003c/summary\u003e\r\n    public void Refresh(string message)\r\n    {\r\n        // Update the UI\r\n        InvokeAsync(() =\u003e\r\n        {\r\n            StateHasChanged();\r\n        });\r\n    }\r\n\r\n# Register\r\n\r\n    /// \u003csummary\u003e\r\n    /// This method Registers the ProgressBar with this app.\r\n    /// \u003c/summary\u003e\r\n    public void Register(ProgressBar progressBar)\r\n    {\r\n        // store the ProgressBar\r\n        this.ProgressBar = progressBar;\r\n    }\r\n\r\n# Blazor Styled Has Been Removed\r\n\r\n# Use Cases\r\n\r\nFor now, the progress bar is meant to show the user something is happening during a long running process.\r\n\r\nThe sample project demonstrates using a Timer and on every refresh the progress bar increases the fill width by the increment value\r\nin pixels, up to the Max value. To use the timer, call the Start method on the Progress bar.\r\nIn theory, and I will update this once I know it works, you should also be able to manually increase the FillWidth value, which in turn sets the FillWidthPixels string value\r\n\r\nExample: FillWidth = 100\r\n         FillWidthPixels = 100px\r\n         \r\nThe FillWidthPixels is used by the CSS for the inner graph.\r\n\r\n# Progress Bar Events\r\n\r\n    private void Timer_Elapsed(object sender, ElapsedEventArgs e)\r\n    {\r\n       ...\r\n    }\r\n    \r\nThis is the Tick event the Timer calls on every cycle. This method increments the FillWidth by the Increment value.\r\nIf the value for Max is encountered, either the app will close if HideWhenFinished is true or reset if continuous is true.\r\n\r\n# ProgressBar Methods\r\n\r\n# Init\r\n\r\nThis method is called by the Constructor of the ProgressBar and sets the DefaultValues.\r\n\r\n# Start\r\n\r\nCall this method to Start the timer. This is used where the graph increments on a regular basis based upon the interval set.\r\n\r\npublic void Start(int startAtValue = 0)\r\n\r\n# Stop\r\n\r\nThis method stops the timer and all future events (already in progress events may finish before stopping)\r\n\r\n# ProgressBar Properties\r\n\r\n# CurrentValue\r\n\r\n    [Parameter]\r\n    public int CurrentValue { get; set; }\r\n    \r\nThe CurrentValue also sets the FillWidth. This property might be removed as FillWidth controls FillWidthPixels, and is what the display goes by.\r\n\r\n# Display\r\n\r\n    public string Display { get; set; }\r\n    \r\n\r\nThe display is managed by the ProgressBar.Visible property, but you can change it if needed (I think).\r\n\r\nVisible = true - Display = inline-block\r\nVisible = false - Display = none\r\n\r\nFrom Progressbar.razor:\r\ndisplay: @Display;\r\n\r\n# FillWidth\r\n\r\n    public int FillWidth { get; set; }\r\n\r\nThe FillWidth is the number of pixels displayed up to the Max value.\r\n\r\nSetting the FillWidth sets the FillWidthPixels CSS Property.\r\n\r\nFillWidth = 90;\r\nFillWidthPixels = 90px\r\n\r\n# FillWidthPixels\r\n\r\n    public int FillWidthPixeels { get; set; }\r\n\r\nAs described above, a property that is the CSS value for how many pixels to display.\r\nSet this property by setting the FilWidth integer value else you are in uncharted waters.\r\n\r\n# HasSubscriber\r\n\r\n    public bool HasSubscriber { get; }\r\n\r\nThis read only property returns true if the ProgressBar has a Subscriber.\r\n\r\n# Increment\r\n\r\n    [Parameter]\r\n    public bool Increment { get; set; }\r\n    \r\nThis value sets how many pixels left the next bubble will be.\r\n\r\nThis value is set by the Increment times the number of times Refresh was called.\r\n\r\n# Interval\r\n\r\n    [Parameter]\r\n    public int Interval { get; set; }\r\n    \r\nThis is the value in milliseconds for how often the Timer event will fire. The default value is 100 if not set.\r\n\r\n# Max\r\n\r\n    [Parameter]\r\n    public int Max { get; set; }\r\n    \r\nThis is the maximum value the ProgressBar inner fill can go to.\r\nThe Default Value is 552.\r\n\r\n# NotificationInProgress\r\n\r\n    public bool NotificationInProgress { get; set; }\r\n    \r\nThis property is used internally by the ProgressBar to make sure only one thread of notifications is sent to the Client at a time.\r\nThis is also useful for debugging as it keeps the message chain down to single threads.\r\n\r\n# Position\r\n\r\n    public string Position { get; set; }\r\n    \r\nThis property is set on the CSS Class for position. Fixed, Absolute and Relative are the 3 I know, there may be more.\r\n\r\n# ProgressBackground\r\n\r\n    public string ProgressBackground { get; set; }\r\n    \r\nThis is the string property bound to the CSS styles for the ProgressBar div.\r\nIn future versions I imagine themes or other styles, or even an option to display the innter graph without the background.\r\n\r\n\u003cimg src=\"https://github.com/DataJuggler/DataJuggler.Blazor.Components/blob/master/wwwroot/Images/RedProgressBase.png\"\u003e\r\n\r\n# Scale\r\n\r\nI added a double value for Scale that allows to control how big the ProgressBar displays. The default is .5.\r\n\r\n# Started\r\n\r\n    public bool Started { get; set; }\r\n\r\nThis property is managed internally the by the ProgressBar when Start and Stop are called.\r\n\r\n# Subscriber\r\n\r\n    [Parameter]\r\n    public IProgressSubscriber Subscriber\r\n\r\nThis property registers the parent with the ProgressBar, which enables the ProgressBar to register with the host.\r\n\r\n    \u003cProgressBar Subscriber=this\u003e\u003c/ProgressBar\u003e\r\n\r\n# Timer\r\n\r\n    public Timer Timer { get; set; }\r\n\r\nThe System.Timer Timer that is started when the Start method is called.\r\n\r\n# Visible\r\n\r\n    [Parameter]\r\n    public bool Visible { get; set; }\r\n    \r\nThis property sets the @Display value to either inline-block if true (visible), or none if false (invisible).\r\n\r\n# Sprite Component\r\n\r\nI created a new Sprite component that allows you to set properties for images.\r\n\r\n# Sprite Methods\r\n\r\n    # Init\r\n    \r\n    The Init method sets the Default values for the control\r\n    \r\n    # Start\r\n    \r\n    The Start method starts the Timer and sets the Elapsed event.\r\n    \r\n    # Stop\r\n    \r\n    Stops the timer and future messages.\r\n    \r\nI have another project planned for Animation called DataJuggler.Blazor.Animation. In that class I have speced out an AnimationManager in my mind, but for now I only create a Timer on one Sprite, and I use the Refresh messages to move Sprites around.\r\n\r\nEventually I would like this to be more automated where you give it a Start X,Y and an End X,Y position and a path could be firued out, but baby steps.\r\n\r\n# Sprite Properties\r\n\r\nMany of the properties are identical to the ProgressBar, only the differences are listed here.\r\n\r\n# Height\r\n\r\n    [Parameter]\r\n    public int Height { get; set; }\r\n\r\nThe height in pixels.\r\n\r\n# HeightPixels\r\n\r\n    public string HeightPixels { get; set; }\r\n    \r\nThis value is set by the setter for Height. The string px is appended to the end.\r\n\r\nExample: Height: 80\r\nHeightPixels: 80px.\r\n\r\n# ImageUrl\r\n\r\n    [Parameter]\r\n    public string ImageUrl\r\n    \r\n This value is set as the background image for the Div.\r\n\r\n# Name\r\n \r\n    [Parameter]\r\n    public string Name\r\n    \r\nThe name helps distinquish Sprites from other Sprites.\r\n\r\n# Width\r\n\r\n    [Parameter]\r\n    public int Width { get; set; }\r\n    \r\nThis property sets the WidthPixels property, which in turns sets the Width of the component.\r\n\r\n# WidthPixels\r\n\r\n    public string WidthPixels { get; set; }\r\n    \r\nThis value is set when you set the Width property.\r\n\r\nExample: \u003cbr\u003e\r\nWidth: 900\r\nWidthPixels: 900px;\r\n\r\n## ComboBox Example\r\n\r\n    \u003cComboBox Name=\"ComboBoxControl\" Parent=\"this\" Unit=\"px\" Width=\"160\" HeightUnit=\"vh\" Height=\"3.6\" LabelText=\"Select:\" LabelWidth=54 ZIndex=20\r\n        Left=\"10\" Theme=\"ThemeEnum.Brown\" LabelLeft=\"-16\" LabelColor=\"Color.Black\" ButtonTextColor=\"Color.LemonChiffon\" ButtonLeft=36 ButtonTop=-2.8\r\n        TextSize=\"TextSizeEnum.SmallMedium\" ListItemLeft=\"56\" ListItemTop=\"0\"\u003e\u003c/ComboBox\u003e\r\n\r\n\r\n\r\n\r\n# ProgressBar\r\nIt took me 3 attempts to get a progress bar I actually like, and I owe thanks to Percentage Circle CSS:\r\n\r\n    CSS Percentage Circle\r\n    Author: Andre Firchow\r\n    \r\n    http://circle.firchow.net/\r\n    \r\n\r\n    \r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdatajuggler%2Fdatajuggler.blazor.components","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdatajuggler%2Fdatajuggler.blazor.components","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdatajuggler%2Fdatajuggler.blazor.components/lists"}