├── .gitattributes ├── .github └── workflows │ └── deploy.yml ├── .gitignore ├── BCSS.Test ├── BCSS.Test.csproj ├── CoreTests │ ├── BunitTest.cs │ ├── ConverterTests.cs │ └── RenderTests.cs ├── GlobalUsings.cs └── UnitTest1.cs ├── BCSS.sln ├── BCSS ├── BCSS.csproj ├── BCSS.jpg ├── Component │ ├── BlazorCssProvider.razor │ └── BlazorCssProvider.razor.cs ├── Extensions │ └── ServiceCollectionExtensions.cs ├── Models │ └── BcssInfo.cs ├── Services │ ├── BcssService.cs │ └── BlazorCssConverter.cs ├── _Imports.razor ├── bundleconfig.json └── wwwroot │ ├── Bcss.js │ └── Bcss.min.js ├── BCSSViewer.Docs ├── BCSSViewer.Docs.csproj ├── Components │ ├── BcssCard.razor │ ├── CodeBlock.razor │ └── PageBottomRouting.razor ├── Pages │ ├── Configuration │ │ ├── BreakpointPage.razor │ │ ├── PerformanceModePage.razor │ │ └── SpacingPage.razor │ ├── Content │ │ └── ContentGeneralPage.razor │ ├── DevTools │ │ ├── BenchmarkPage.razor │ │ └── QuickDebugPage.razor │ ├── GettingStarted │ │ ├── HowItWorksPage.razor │ │ ├── InstallationPage.razor │ │ └── WhatPage.razor │ ├── Index.razor │ ├── SpecialContent │ │ ├── FilterPage.razor │ │ ├── FlexboxPage.razor │ │ ├── ShadowPage.razor │ │ ├── TransformPage.razor │ │ └── TransitionPage.razor │ └── Syntax │ │ ├── AdvancedSyntaxPage.razor │ │ ├── BasicSyntaxPage.razor │ │ ├── CaseInsensitivePage.razor │ │ ├── CustomClassesPage.razor │ │ ├── CustomValuesPage.razor │ │ ├── DoubleDashPage.razor │ │ ├── PrefixesPage.razor │ │ ├── UnifiedClassPage.razor │ │ ├── UnitMeasurementPage.razor │ │ └── VendorPrefixesPage.razor ├── Shared │ └── MainLayout.razor ├── _Imports.razor └── wwwroot │ └── background.png ├── BCSSViewer.Wasm ├── App.razor ├── BCSSViewer.Wasm.csproj ├── Program.cs ├── Properties │ └── launchSettings.json ├── _Imports.razor └── wwwroot │ ├── cbsmall.png │ ├── css │ └── app.css │ └── index.html ├── BCSSViewer ├── App.razor ├── BCSSViewer.csproj ├── Pages │ └── _Host.cshtml ├── Program.cs ├── Properties │ └── launchSettings.json ├── _Imports.razor ├── appsettings.Development.json ├── appsettings.json └── wwwroot │ ├── cbsmall.png │ └── css │ └── site.css ├── LICENSE.txt └── README.md /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /.github/workflows/deploy.yml: -------------------------------------------------------------------------------- 1 | on: 2 | push: 3 | workflow_dispatch: 4 | name: 🚀 Deploy website on push 5 | jobs: 6 | web-deploy: 7 | name: 🎉 Deploy 8 | runs-on: ubuntu-latest 9 | steps: 10 | - name: 🚚 Get latest code 11 | uses: actions/checkout@v4 12 | - name: Setup .NET Core 13 | uses: actions/setup-dotnet@v4 14 | with: 15 | dotnet-version: | 16 | 8.0.x 17 | 9.0.x 18 | - name: Install dependencies 19 | run: dotnet restore 20 | - name: Build with dotnet 21 | run: dotnet build --configuration Release --no-restore 22 | - name: Publish 23 | run: dotnet publish /home/runner/work/BCSS/BCSS/BCSSViewer.Wasm/BCSSViewer.Wasm.csproj -c Release -f net9.0 --output ./Release 24 | 25 | - name: 📂 Sync files 26 | if: ${{ github.repository_owner == 'CodeBeamOrg' }} 27 | uses: SamKirkland/FTP-Deploy-Action@v4.3.4 28 | with: 29 | server: ${{ secrets.ftp_server }} 30 | username: ${{ secrets.ftp_username }} 31 | password: ${{ secrets.ftp_password }} 32 | local-dir: ./Release/wwwroot/ 33 | server-dir: ./bcss/ 34 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 5 | 6 | # User-specific files 7 | *.rsuser 8 | *.suo 9 | *.user 10 | *.userosscache 11 | *.sln.docstates 12 | 13 | # User-specific files (MonoDevelop/Xamarin Studio) 14 | *.userprefs 15 | 16 | # Mono auto generated files 17 | mono_crash.* 18 | 19 | # Build results 20 | [Dd]ebug/ 21 | [Dd]ebugPublic/ 22 | [Rr]elease/ 23 | [Rr]eleases/ 24 | x64/ 25 | x86/ 26 | [Ww][Ii][Nn]32/ 27 | [Aa][Rr][Mm]/ 28 | [Aa][Rr][Mm]64/ 29 | bld/ 30 | [Bb]in/ 31 | [Oo]bj/ 32 | [Oo]ut/ 33 | [Ll]og/ 34 | [Ll]ogs/ 35 | 36 | # Visual Studio 2015/2017 cache/options directory 37 | .vs/ 38 | # Uncomment if you have tasks that create the project's static files in wwwroot 39 | #wwwroot/ 40 | 41 | # Visual Studio 2017 auto generated files 42 | Generated\ Files/ 43 | 44 | # MSTest test Results 45 | [Tt]est[Rr]esult*/ 46 | [Bb]uild[Ll]og.* 47 | 48 | # NUnit 49 | *.VisualState.xml 50 | TestResult.xml 51 | nunit-*.xml 52 | 53 | # Build Results of an ATL Project 54 | [Dd]ebugPS/ 55 | [Rr]eleasePS/ 56 | dlldata.c 57 | 58 | # Benchmark Results 59 | BenchmarkDotNet.Artifacts/ 60 | 61 | # .NET Core 62 | project.lock.json 63 | project.fragment.lock.json 64 | artifacts/ 65 | 66 | # ASP.NET Scaffolding 67 | ScaffoldingReadMe.txt 68 | 69 | # StyleCop 70 | StyleCopReport.xml 71 | 72 | # Files built by Visual Studio 73 | *_i.c 74 | *_p.c 75 | *_h.h 76 | *.ilk 77 | *.meta 78 | *.obj 79 | *.iobj 80 | *.pch 81 | *.pdb 82 | *.ipdb 83 | *.pgc 84 | *.pgd 85 | *.rsp 86 | *.sbr 87 | *.tlb 88 | *.tli 89 | *.tlh 90 | *.tmp 91 | *.tmp_proj 92 | *_wpftmp.csproj 93 | *.log 94 | *.vspscc 95 | *.vssscc 96 | .builds 97 | *.pidb 98 | *.svclog 99 | *.scc 100 | 101 | # Chutzpah Test files 102 | _Chutzpah* 103 | 104 | # Visual C++ cache files 105 | ipch/ 106 | *.aps 107 | *.ncb 108 | *.opendb 109 | *.opensdf 110 | *.sdf 111 | *.cachefile 112 | *.VC.db 113 | *.VC.VC.opendb 114 | 115 | # Visual Studio profiler 116 | *.psess 117 | *.vsp 118 | *.vspx 119 | *.sap 120 | 121 | # Visual Studio Trace Files 122 | *.e2e 123 | 124 | # TFS 2012 Local Workspace 125 | $tf/ 126 | 127 | # Guidance Automation Toolkit 128 | *.gpState 129 | 130 | # ReSharper is a .NET coding add-in 131 | _ReSharper*/ 132 | *.[Rr]e[Ss]harper 133 | *.DotSettings.user 134 | 135 | # TeamCity is a build add-in 136 | _TeamCity* 137 | 138 | # DotCover is a Code Coverage Tool 139 | *.dotCover 140 | 141 | # AxoCover is a Code Coverage Tool 142 | .axoCover/* 143 | !.axoCover/settings.json 144 | 145 | # Coverlet is a free, cross platform Code Coverage Tool 146 | coverage*.json 147 | coverage*.xml 148 | coverage*.info 149 | 150 | # Visual Studio code coverage results 151 | *.coverage 152 | *.coveragexml 153 | 154 | # NCrunch 155 | _NCrunch_* 156 | .*crunch*.local.xml 157 | nCrunchTemp_* 158 | 159 | # MightyMoose 160 | *.mm.* 161 | AutoTest.Net/ 162 | 163 | # Web workbench (sass) 164 | .sass-cache/ 165 | 166 | # Installshield output folder 167 | [Ee]xpress/ 168 | 169 | # DocProject is a documentation generator add-in 170 | DocProject/buildhelp/ 171 | DocProject/Help/*.HxT 172 | DocProject/Help/*.HxC 173 | DocProject/Help/*.hhc 174 | DocProject/Help/*.hhk 175 | DocProject/Help/*.hhp 176 | DocProject/Help/Html2 177 | DocProject/Help/html 178 | 179 | # Click-Once directory 180 | publish/ 181 | 182 | # Publish Web Output 183 | *.[Pp]ublish.xml 184 | *.azurePubxml 185 | # Note: Comment the next line if you want to checkin your web deploy settings, 186 | # but database connection strings (with potential passwords) will be unencrypted 187 | *.pubxml 188 | *.publishproj 189 | 190 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 191 | # checkin your Azure Web App publish settings, but sensitive information contained 192 | # in these scripts will be unencrypted 193 | PublishScripts/ 194 | 195 | # NuGet Packages 196 | *.nupkg 197 | # NuGet Symbol Packages 198 | *.snupkg 199 | # The packages folder can be ignored because of Package Restore 200 | **/[Pp]ackages/* 201 | # except build/, which is used as an MSBuild target. 202 | !**/[Pp]ackages/build/ 203 | # Uncomment if necessary however generally it will be regenerated when needed 204 | #!**/[Pp]ackages/repositories.config 205 | # NuGet v3's project.json files produces more ignorable files 206 | *.nuget.props 207 | *.nuget.targets 208 | 209 | # Microsoft Azure Build Output 210 | csx/ 211 | *.build.csdef 212 | 213 | # Microsoft Azure Emulator 214 | ecf/ 215 | rcf/ 216 | 217 | # Windows Store app package directories and files 218 | AppPackages/ 219 | BundleArtifacts/ 220 | Package.StoreAssociation.xml 221 | _pkginfo.txt 222 | *.appx 223 | *.appxbundle 224 | *.appxupload 225 | 226 | # Visual Studio cache files 227 | # files ending in .cache can be ignored 228 | *.[Cc]ache 229 | # but keep track of directories ending in .cache 230 | !?*.[Cc]ache/ 231 | 232 | # Others 233 | ClientBin/ 234 | ~$* 235 | *~ 236 | *.dbmdl 237 | *.dbproj.schemaview 238 | *.jfm 239 | *.pfx 240 | *.publishsettings 241 | orleans.codegen.cs 242 | 243 | # Including strong name files can present a security risk 244 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 245 | #*.snk 246 | 247 | # Since there are multiple workflows, uncomment next line to ignore bower_components 248 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 249 | #bower_components/ 250 | 251 | # RIA/Silverlight projects 252 | Generated_Code/ 253 | 254 | # Backup & report files from converting an old project file 255 | # to a newer Visual Studio version. Backup files are not needed, 256 | # because we have git ;-) 257 | _UpgradeReport_Files/ 258 | Backup*/ 259 | UpgradeLog*.XML 260 | UpgradeLog*.htm 261 | ServiceFabricBackup/ 262 | *.rptproj.bak 263 | 264 | # SQL Server files 265 | *.mdf 266 | *.ldf 267 | *.ndf 268 | 269 | # Business Intelligence projects 270 | *.rdl.data 271 | *.bim.layout 272 | *.bim_*.settings 273 | *.rptproj.rsuser 274 | *- [Bb]ackup.rdl 275 | *- [Bb]ackup ([0-9]).rdl 276 | *- [Bb]ackup ([0-9][0-9]).rdl 277 | 278 | # Microsoft Fakes 279 | FakesAssemblies/ 280 | 281 | # GhostDoc plugin setting file 282 | *.GhostDoc.xml 283 | 284 | # Node.js Tools for Visual Studio 285 | .ntvs_analysis.dat 286 | node_modules/ 287 | 288 | # Visual Studio 6 build log 289 | *.plg 290 | 291 | # Visual Studio 6 workspace options file 292 | *.opt 293 | 294 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 295 | *.vbw 296 | 297 | # Visual Studio LightSwitch build output 298 | **/*.HTMLClient/GeneratedArtifacts 299 | **/*.DesktopClient/GeneratedArtifacts 300 | **/*.DesktopClient/ModelManifest.xml 301 | **/*.Server/GeneratedArtifacts 302 | **/*.Server/ModelManifest.xml 303 | _Pvt_Extensions 304 | 305 | # Paket dependency manager 306 | .paket/paket.exe 307 | paket-files/ 308 | 309 | # FAKE - F# Make 310 | .fake/ 311 | 312 | # CodeRush personal settings 313 | .cr/personal 314 | 315 | # Python Tools for Visual Studio (PTVS) 316 | __pycache__/ 317 | *.pyc 318 | 319 | # Cake - Uncomment if you are using it 320 | # tools/** 321 | # !tools/packages.config 322 | 323 | # Tabs Studio 324 | *.tss 325 | 326 | # Telerik's JustMock configuration file 327 | *.jmconfig 328 | 329 | # BizTalk build output 330 | *.btp.cs 331 | *.btm.cs 332 | *.odx.cs 333 | *.xsd.cs 334 | 335 | # OpenCover UI analysis results 336 | OpenCover/ 337 | 338 | # Azure Stream Analytics local run output 339 | ASALocalRun/ 340 | 341 | # MSBuild Binary and Structured Log 342 | *.binlog 343 | 344 | # NVidia Nsight GPU debugger configuration file 345 | *.nvuser 346 | 347 | # MFractors (Xamarin productivity tool) working folder 348 | .mfractor/ 349 | 350 | # Local History for Visual Studio 351 | .localhistory/ 352 | 353 | # BeatPulse healthcheck temp database 354 | healthchecksdb 355 | 356 | # Backup folder for Package Reference Convert tool in Visual Studio 2017 357 | MigrationBackup/ 358 | 359 | # Ionide (cross platform F# VS Code tools) working folder 360 | .ionide/ 361 | 362 | # Fody - auto-generated XML schema 363 | FodyWeavers.xsd -------------------------------------------------------------------------------- /BCSS.Test/BCSS.Test.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net9.0 5 | enable 6 | enable 7 | 8 | false 9 | true 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /BCSS.Test/CoreTests/BunitTest.cs: -------------------------------------------------------------------------------- 1 | using BCSS.Services; 2 | using Bunit; 3 | using MudBlazor.Services; 4 | using MudExtensions.Services; 5 | 6 | namespace BCSS.Test.Core 7 | { 8 | public abstract class BunitTest 9 | { 10 | protected Bunit.TestContext Context { get; private set; } 11 | 12 | [SetUp] 13 | public virtual void Setup() 14 | { 15 | Context = new(); 16 | Context.JSInterop.Mode = JSRuntimeMode.Loose; 17 | Context.Services.AddMudServices(options => 18 | { 19 | options.SnackbarConfiguration.ShowTransitionDuration = 0; 20 | options.SnackbarConfiguration.HideTransitionDuration = 0; 21 | }); 22 | Context.Services.AddMudExtensions(); 23 | Context.Services.AddBcss(); 24 | //Context.AddTestServices(); 25 | } 26 | 27 | [TearDown] 28 | public void TearDown() 29 | { 30 | try 31 | { 32 | Context.Dispose(); 33 | } 34 | catch (Exception) 35 | { 36 | /*ignore*/ 37 | } 38 | } 39 | 40 | protected async Task ImproveChanceOfSuccess(Func testAction) 41 | { 42 | for (int i = 0; i < 10; i++) 43 | { 44 | try 45 | { 46 | await testAction(); 47 | return; 48 | } 49 | catch(Exception) { /*we don't care here*/ } 50 | } 51 | await testAction(); 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /BCSS.Test/CoreTests/ConverterTests.cs: -------------------------------------------------------------------------------- 1 | using FluentAssertions; 2 | using BCSS.Services; 3 | 4 | namespace BCSS.Test.Core 5 | { 6 | [TestFixture] 7 | public class ConverterTests : BunitTest 8 | { 9 | [Test] 10 | public void BasicConvertTest() 11 | { 12 | BcssService service = new BcssService(); 13 | service.Decode("w-200").Should().Be("w-200"); 14 | BlazorCssConverter.Convert("w-200").Should().Be("width:200px"); 15 | BlazorCssConverter.Convert("bg-yellow").Should().Be("background:yellow"); 16 | } 17 | 18 | [Test] 19 | public void DoubleDashTest() 20 | { 21 | BcssService service = new BcssService(); 22 | service.Decode("w--200").Should().Be("w--200"); 23 | BlazorCssConverter.Convert("w--200").Should().Be("width:200px"); 24 | BlazorCssConverter.Convert("bg--yellow").Should().Be("background:yellow"); 25 | 26 | BlazorCssConverter.Convert("d-inline-flex").Should().Be("display:inline-flex"); 27 | BlazorCssConverter.Convert("d--inline-flex").Should().Be("display:inline-flex"); 28 | 29 | BlazorCssConverter.Convert("box-sizing--border-box").Should().Be("box-sizing:border-box"); 30 | } 31 | 32 | [Test] 33 | public void AdvancedConvertTest() 34 | { 35 | BcssService service = new BcssService(); 36 | BlazorCssConverter.PostProcess(BlazorCssConverter.Convert("transition-color-1s-ease+in+out")).Should().Be("transition:color 1s ease-in-out"); 37 | BlazorCssConverter.PostProcess(BlazorCssConverter.Convert("transition-color*1s*ease+in+out")).Should().Be("transition:color 1s ease-in-out"); 38 | BlazorCssConverter.PostProcess(BlazorCssConverter.Convert("transition--color-1s-ease+in+out")).Should().Be("transition:color 1s ease-in-out"); 39 | BlazorCssConverter.PostProcess(BlazorCssConverter.Convert("transition--color*1s*ease+in+out")).Should().Be("transition:color 1s ease-in-out"); 40 | 41 | } 42 | 43 | [Test] 44 | public void SpacedResultTest() 45 | { 46 | BcssService service = new BcssService(); 47 | BlazorCssConverter.PostProcess(BlazorCssConverter.Convert("transition-color-1-ease-in-out")).Should().Be("transition:ease-in-out color 1s"); 48 | BlazorCssConverter.PostProcess(BlazorCssConverter.Convert("transition-color-1s-ease-in")).Should().Be("transition:ease-in color 1s"); 49 | //Wrong example 50 | BlazorCssConverter.PostProcess(BlazorCssConverter.Convert("transition-color-1-easein-out")).Should().Be("transition:color 1s easein out"); 51 | } 52 | 53 | [Test] 54 | public void UnitMeasurementTest() 55 | { 56 | BcssService service = new BcssService(); 57 | service.Decode("w-200").Should().Be("w-200"); 58 | BlazorCssConverter.Convert("w-200").Should().Be("width:200px"); 59 | 60 | service.Decode("w-200%").Should().Be("w-200a"); 61 | BlazorCssConverter.Convert("w-200%").Should().Be("width:200%"); 62 | 63 | service.Decode("w-2.0").Should().Be("w-2s0"); 64 | BlazorCssConverter.Convert("w-2.0").Should().Be("width:2.00rem"); 65 | service.Decode("w-20.").Should().Be("w-20s"); 66 | BlazorCssConverter.Convert("w-20.").Should().Be("width:20.0rem"); 67 | service.Decode("w-2rem").Should().Be("w-2rem"); 68 | BlazorCssConverter.Convert("w-2rem").Should().Be("width:2rem"); 69 | 70 | service.Decode("w-2,0").Should().Be("w-2t0"); 71 | BlazorCssConverter.Convert("w-2,0").Should().Be("width:2.00em"); 72 | service.Decode("w-20,").Should().Be("w-20t"); 73 | BlazorCssConverter.Convert("w-20,").Should().Be("width:20.0em"); 74 | service.Decode("w-2em").Should().Be("w-2em"); 75 | BlazorCssConverter.Convert("w-2em").Should().Be("width:2em"); 76 | 77 | service.Decode("h-2vh").Should().Be("h-2vh"); 78 | BlazorCssConverter.Convert("h-2vh").Should().Be("height:2vh"); 79 | service.Decode("w-20vw").Should().Be("w-20vw"); 80 | BlazorCssConverter.Convert("w-20vw").Should().Be("width:20vw"); 81 | 82 | service.Decode("rotate-20").Should().Be("rotate-20"); 83 | BlazorCssConverter.Convert("rotate-20").Should().Be("transform:rotate(20deg)"); 84 | } 85 | 86 | [Test] 87 | public void CustomValuesTest() 88 | { 89 | BcssService service = new BcssService(); 90 | service.Decode("bg-[#123456]").Should().Be("bg-r123456"); 91 | BlazorCssConverter.Convert("bg-[#123456]").Should().Be("background:rgba(18,52,86,255)"); 92 | 93 | service.Decode("bg-[--mud-palette-primary]").Should().Be("bg---mud-palette-primary"); 94 | BlazorCssConverter.Convert("bg-[--mud-palette-primary]").Should().Be("background:var(--mud-palette-primary)"); 95 | 96 | service.Decode("bgimage-[/paper.png]").Should().Be("bgimage-wpaperspng"); 97 | BlazorCssConverter.Convert("bgimage-[/paper.png]").Should().Be("background-image:url(paper.png)"); 98 | 99 | service.Decode("bg-[49,59,114]").Should().Be("bg-49t59t114"); 100 | BlazorCssConverter.Convert("bg-[49,59,114]").Should().Be("background:rgba(49,59,114)"); 101 | 102 | service.Decode("bg-[49,59,114,0.8]").Should().Be("bg-49t59t114t0s8"); 103 | BlazorCssConverter.Convert("bg-[49,59,114,0.8]").Should().Be("background:rgba(49,59,114,0.8)"); 104 | } 105 | 106 | [Test] 107 | public void CaseInsensitiveTest() 108 | { 109 | BcssService service = new BcssService(); 110 | service.Decode("bG-Yellow").Should().Be("bg-yellow"); 111 | BlazorCssConverter.Convert("bG-Yellow").Should().Be("background:yellow"); 112 | 113 | service.Decode("BG-YELLOW").Should().Be("bg-yellow"); 114 | BlazorCssConverter.Convert("BG-YELLOW").Should().Be("background:yellow"); 115 | 116 | service.Decode("Bg-[--Mud-paLette-pRimary]").Should().Be("bg---mud-palette-primary"); 117 | BlazorCssConverter.Convert("Bg-[--Mud-paLette-pRimary]").Should().Be("background:var(--mud-palette-primary)"); 118 | 119 | //On Url values, property name should be lowercase, but value not. 120 | service.Decode("bgiMage-[/Paper.Png]").Should().Be("bgimage-wpaperspng"); 121 | BlazorCssConverter.Convert("bgiMage-[/Paper.Png]").Should().Be("background-image:url(Paper.Png)"); 122 | } 123 | 124 | [Test] 125 | public void PrefixesTest() 126 | { 127 | BcssService service = new BcssService(); 128 | service.Decode("hover:bg-yellow").Should().Be("hoverqbg-yellow"); 129 | BlazorCssConverter.Convert("hover:bg-yellow").Should().Be("background:yellow"); 130 | 131 | service.Decode("h:bg-yellow").Should().Be("hqbg-yellow"); 132 | BlazorCssConverter.Convert("h:bg-yellow").Should().Be("background:yellow"); 133 | 134 | service.Decode("w:bg-yellow").Should().Be("wqbg-yellow"); 135 | BlazorCssConverter.Convert("w:bg-yellow").Should().Be("background:yellow"); 136 | 137 | service.Decode("sm:w:bg-yellow").Should().Be("smqwqbg-yellow"); 138 | BlazorCssConverter.Convert("sm:w:bg-yellow").Should().Be("background:yellow"); 139 | 140 | service.Decode("sm:bg-yellow").Should().Be("smqbg-yellow"); 141 | BlazorCssConverter.Convert("sm:bg-yellow").Should().Be("background:yellow"); 142 | } 143 | 144 | } 145 | } 146 | -------------------------------------------------------------------------------- /BCSS.Test/CoreTests/RenderTests.cs: -------------------------------------------------------------------------------- 1 | using BCSSViewer.Docs.Pages; 2 | using FluentAssertions; 3 | 4 | namespace BCSS.Test.Core 5 | { 6 | [TestFixture] 7 | public class RenderTests : BunitTest 8 | { 9 | [Test] 10 | public void IndexPageRenderTest() 11 | { 12 | var comp = Context.RenderComponent(); 13 | comp.Markup.Should().NotBeNullOrEmpty(); 14 | } 15 | 16 | [Test] 17 | public void BreakpointPageRenderTest() 18 | { 19 | var comp = Context.RenderComponent(); 20 | comp.Markup.Should().NotBeNullOrEmpty(); 21 | } 22 | 23 | [Test] 24 | public void PerformanceModePageRenderTest() 25 | { 26 | var comp = Context.RenderComponent(); 27 | comp.Markup.Should().NotBeNullOrEmpty(); 28 | } 29 | 30 | [Test] 31 | public void SpacingPageRenderTest() 32 | { 33 | var comp = Context.RenderComponent(); 34 | comp.Markup.Should().NotBeNullOrEmpty(); 35 | } 36 | 37 | [Test] 38 | public void ContentGeneralPageRenderTest() 39 | { 40 | var comp = Context.RenderComponent(); 41 | comp.Markup.Should().NotBeNullOrEmpty(); 42 | } 43 | 44 | [Test] 45 | public void BenchmarkPageRenderTest() 46 | { 47 | var comp = Context.RenderComponent(); 48 | comp.Markup.Should().NotBeNullOrEmpty(); 49 | } 50 | 51 | [Test] 52 | public void QuickDebugPageRenderTest() 53 | { 54 | var comp = Context.RenderComponent(); 55 | comp.Markup.Should().NotBeNullOrEmpty(); 56 | } 57 | 58 | [Test] 59 | public void HowItWorksPageRenderTest() 60 | { 61 | var comp = Context.RenderComponent(); 62 | comp.Markup.Should().NotBeNullOrEmpty(); 63 | } 64 | 65 | [Test] 66 | public void InstallationPageRenderTest() 67 | { 68 | var comp = Context.RenderComponent(); 69 | comp.Markup.Should().NotBeNullOrEmpty(); 70 | } 71 | 72 | [Test] 73 | public void WhatPageRenderTest() 74 | { 75 | var comp = Context.RenderComponent(); 76 | comp.Markup.Should().NotBeNullOrEmpty(); 77 | } 78 | 79 | [Test] 80 | public void FilterPageRenderTest() 81 | { 82 | var comp = Context.RenderComponent(); 83 | comp.Markup.Should().NotBeNullOrEmpty(); 84 | } 85 | 86 | [Test] 87 | public void FlexboxPageRenderTest() 88 | { 89 | var comp = Context.RenderComponent(); 90 | comp.Markup.Should().NotBeNullOrEmpty(); 91 | } 92 | 93 | [Test] 94 | public void ShadowPageRenderTest() 95 | { 96 | var comp = Context.RenderComponent(); 97 | comp.Markup.Should().NotBeNullOrEmpty(); 98 | } 99 | 100 | [Test] 101 | public void TransformPageRenderTest() 102 | { 103 | var comp = Context.RenderComponent(); 104 | comp.Markup.Should().NotBeNullOrEmpty(); 105 | } 106 | 107 | [Test] 108 | public void BasicSyntaxPageRenderTest() 109 | { 110 | var comp = Context.RenderComponent(); 111 | comp.Markup.Should().NotBeNullOrEmpty(); 112 | } 113 | 114 | [Test] 115 | public void CaseInsensitivePageRenderTest() 116 | { 117 | var comp = Context.RenderComponent(); 118 | comp.Markup.Should().NotBeNullOrEmpty(); 119 | } 120 | 121 | [Test] 122 | public void CustomValuesPageRenderTest() 123 | { 124 | var comp = Context.RenderComponent(); 125 | comp.Markup.Should().NotBeNullOrEmpty(); 126 | } 127 | 128 | [Test] 129 | public void DoubleDashPageRenderTest() 130 | { 131 | var comp = Context.RenderComponent(); 132 | comp.Markup.Should().NotBeNullOrEmpty(); 133 | } 134 | 135 | [Test] 136 | public void PrefixesPageRenderTest() 137 | { 138 | var comp = Context.RenderComponent(); 139 | comp.Markup.Should().NotBeNullOrEmpty(); 140 | } 141 | 142 | [Test] 143 | public void UnitMeasurementPageRenderTest() 144 | { 145 | var comp = Context.RenderComponent(); 146 | comp.Markup.Should().NotBeNullOrEmpty(); 147 | } 148 | 149 | [Test] 150 | public void VendorPrefixesPageRenderTest() 151 | { 152 | var comp = Context.RenderComponent(); 153 | comp.Markup.Should().NotBeNullOrEmpty(); 154 | } 155 | 156 | } 157 | } 158 | -------------------------------------------------------------------------------- /BCSS.Test/GlobalUsings.cs: -------------------------------------------------------------------------------- 1 | global using NUnit.Framework; -------------------------------------------------------------------------------- /BCSS.Test/UnitTest1.cs: -------------------------------------------------------------------------------- 1 | namespace BCSS.Test 2 | { 3 | public class Tests 4 | { 5 | [SetUp] 6 | public void Setup() 7 | { 8 | } 9 | 10 | [Test] 11 | public void Test1() 12 | { 13 | Assert.Pass(); 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /BCSS.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.6.33815.320 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BCSS", "BCSS\BCSS.csproj", "{45998C7D-6BC9-43F4-840F-A3CAFD0113B4}" 7 | EndProject 8 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BCSSViewer", "BCSSViewer\BCSSViewer.csproj", "{9C7AE5DE-B388-4B4C-854C-6A6EEA496F41}" 9 | ProjectSection(ProjectDependencies) = postProject 10 | {45998C7D-6BC9-43F4-840F-A3CAFD0113B4} = {45998C7D-6BC9-43F4-840F-A3CAFD0113B4} 11 | {837AA5FF-99D6-41CD-A38B-DFE148A8A205} = {837AA5FF-99D6-41CD-A38B-DFE148A8A205} 12 | EndProjectSection 13 | EndProject 14 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BCSSViewer.Docs", "BCSSViewer.Docs\BCSSViewer.Docs.csproj", "{837AA5FF-99D6-41CD-A38B-DFE148A8A205}" 15 | ProjectSection(ProjectDependencies) = postProject 16 | {45998C7D-6BC9-43F4-840F-A3CAFD0113B4} = {45998C7D-6BC9-43F4-840F-A3CAFD0113B4} 17 | EndProjectSection 18 | EndProject 19 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BCSSViewer.Wasm", "BCSSViewer.Wasm\BCSSViewer.Wasm.csproj", "{C26FD032-E5A7-45A2-8333-285E9F126BA9}" 20 | EndProject 21 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BCSS.Test", "BCSS.Test\BCSS.Test.csproj", "{96483B78-466E-4CCE-B82A-6180888A8D76}" 22 | EndProject 23 | Global 24 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 25 | Debug|Any CPU = Debug|Any CPU 26 | Release|Any CPU = Release|Any CPU 27 | EndGlobalSection 28 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 29 | {45998C7D-6BC9-43F4-840F-A3CAFD0113B4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 30 | {45998C7D-6BC9-43F4-840F-A3CAFD0113B4}.Debug|Any CPU.Build.0 = Debug|Any CPU 31 | {45998C7D-6BC9-43F4-840F-A3CAFD0113B4}.Release|Any CPU.ActiveCfg = Release|Any CPU 32 | {45998C7D-6BC9-43F4-840F-A3CAFD0113B4}.Release|Any CPU.Build.0 = Release|Any CPU 33 | {9C7AE5DE-B388-4B4C-854C-6A6EEA496F41}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 34 | {9C7AE5DE-B388-4B4C-854C-6A6EEA496F41}.Debug|Any CPU.Build.0 = Debug|Any CPU 35 | {9C7AE5DE-B388-4B4C-854C-6A6EEA496F41}.Release|Any CPU.ActiveCfg = Release|Any CPU 36 | {9C7AE5DE-B388-4B4C-854C-6A6EEA496F41}.Release|Any CPU.Build.0 = Release|Any CPU 37 | {837AA5FF-99D6-41CD-A38B-DFE148A8A205}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 38 | {837AA5FF-99D6-41CD-A38B-DFE148A8A205}.Debug|Any CPU.Build.0 = Debug|Any CPU 39 | {837AA5FF-99D6-41CD-A38B-DFE148A8A205}.Release|Any CPU.ActiveCfg = Release|Any CPU 40 | {837AA5FF-99D6-41CD-A38B-DFE148A8A205}.Release|Any CPU.Build.0 = Release|Any CPU 41 | {C26FD032-E5A7-45A2-8333-285E9F126BA9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 42 | {C26FD032-E5A7-45A2-8333-285E9F126BA9}.Debug|Any CPU.Build.0 = Debug|Any CPU 43 | {C26FD032-E5A7-45A2-8333-285E9F126BA9}.Release|Any CPU.ActiveCfg = Release|Any CPU 44 | {C26FD032-E5A7-45A2-8333-285E9F126BA9}.Release|Any CPU.Build.0 = Release|Any CPU 45 | {96483B78-466E-4CCE-B82A-6180888A8D76}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 46 | {96483B78-466E-4CCE-B82A-6180888A8D76}.Debug|Any CPU.Build.0 = Debug|Any CPU 47 | {96483B78-466E-4CCE-B82A-6180888A8D76}.Release|Any CPU.ActiveCfg = Release|Any CPU 48 | {96483B78-466E-4CCE-B82A-6180888A8D76}.Release|Any CPU.Build.0 = Release|Any CPU 49 | EndGlobalSection 50 | GlobalSection(SolutionProperties) = preSolution 51 | HideSolutionNode = FALSE 52 | EndGlobalSection 53 | GlobalSection(ExtensibilityGlobals) = postSolution 54 | SolutionGuid = {26FB81CE-CAB7-45B7-ABF7-2F90FF5FDEA3} 55 | EndGlobalSection 56 | EndGlobal 57 | -------------------------------------------------------------------------------- /BCSS/BCSS.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net8.0;net9.0 5 | enable 6 | enable 7 | MIT 8 | 1.0.1 9 | CodeBeam 10 | CodeBeam OpenSource MIT 11 | Blazor; CSS; Style; Generate 12 | Runtime CSS generator for Blazor. 13 | CodeBeam.BCSS 14 | BCSS.jpg 15 | https://github.com/CodeBeamOrg/BCSS 16 | CodeBeam.BCSS 17 | http://bcss.codebeam.org 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | <_ContentIncludedByDefault Remove="bundleconfig.json" /> 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | <_Parameter1>BCSS.Test 45 | 46 | 47 | 48 | 49 | 50 | True 51 | \ 52 | 53 | 54 | 55 | 56 | 57 | 58 | -------------------------------------------------------------------------------- /BCSS/BCSS.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeBeamOrg/BCSS/dd1657245b2114b7baa15054ac630ec51e6fa0b0/BCSS/BCSS.jpg -------------------------------------------------------------------------------- /BCSS/Component/BlazorCssProvider.razor: -------------------------------------------------------------------------------- 1 | @namespace BCSS 2 | @using BCSS.Services 3 | @inherits ComponentBase 4 | @inject BcssService BcssService 5 | 6 | 22 | 23 | 26 | 27 | 30 | 31 | 34 | 35 | 38 | 39 | 42 | -------------------------------------------------------------------------------- /BCSS/Component/BlazorCssProvider.razor.cs: -------------------------------------------------------------------------------- 1 | using BCSS.Services; 2 | using Microsoft.AspNetCore.Components; 3 | using Microsoft.JSInterop; 4 | 5 | namespace BCSS 6 | { 7 | public partial class BlazorCssProvider : ComponentBase 8 | { 9 | [Inject] IJSRuntime JSRuntime { get; set; } 10 | 11 | protected List _bcssInfos = new(); 12 | 13 | protected internal Dictionary? UnifiedClasses { get; set; } 14 | 15 | /// 16 | /// If true, BCSS skips the validation checks and increase performance. 17 | /// 18 | [Parameter] 19 | public bool PerformanceMode { get; set; } 20 | 21 | /// 22 | /// If true, deletes and overrides all other same CSS properties when new value is added. Default is false. 23 | /// 24 | [Parameter] 25 | public bool KeepSingleValue { get; set; } 26 | 27 | /// 28 | /// The spacing multiplier for px measured CSS properties like padding, margin, top, left, right, bottom. 29 | /// 30 | [Parameter] 31 | public int Spacing { get; set; } = 1; 32 | 33 | /// 34 | /// The small size measured by pixels. 35 | /// 36 | [Parameter] 37 | public int Sm { get; set; } = 600; 38 | 39 | /// 40 | /// The medium size measured by pixels. 41 | /// 42 | [Parameter] 43 | public int Md { get; set; } = 960; 44 | 45 | /// 46 | /// The large size measured by pixels. 47 | /// 48 | [Parameter] 49 | public int Lg { get; set; } = 1280; 50 | 51 | /// 52 | /// The extra large size measured by pixels. 53 | /// 54 | [Parameter] 55 | public int Xl { get; set; } = 1920; 56 | 57 | protected override async Task OnInitializedAsync() 58 | { 59 | await base.OnInitializedAsync(); 60 | BcssService.Attach(this); 61 | } 62 | 63 | bool _firstRendered; 64 | //int _renderCount; 65 | protected override async Task OnAfterRenderAsync(bool firstRender) 66 | { 67 | await base.OnAfterRenderAsync(firstRender); 68 | if (firstRender) 69 | { 70 | _firstRendered = true; 71 | StateHasChanged(); 72 | } 73 | //_renderCount++; 74 | } 75 | 76 | private bool _shouldRender = false; 77 | protected override bool ShouldRender() 78 | { 79 | return _shouldRender; 80 | } 81 | 82 | //string? _isValidResult; 83 | protected internal async Task AddInfo(BcssInfo info) 84 | { 85 | if (string.IsNullOrEmpty(info.Key) || string.IsNullOrEmpty(info.Value)) 86 | { 87 | return; 88 | } 89 | if (_bcssInfos.Any(x => x.Key == info.Key && x.Value == info.Value)) 90 | { 91 | return; 92 | } 93 | 94 | if (PerformanceMode) 95 | { 96 | if (KeepSingleValue) 97 | { 98 | Clear(info.Key); 99 | } 100 | _bcssInfos.Add(info); 101 | Update(); 102 | return; 103 | } 104 | 105 | List splittedValue = info.Value.Split(' ').ToList(); 106 | bool isValid = true; 107 | foreach (var v in splittedValue) 108 | { 109 | string[] definition = BlazorCssConverter.PostProcess(v).Split(':'); 110 | if (definition.Length > 1) 111 | { 112 | isValid = await IsValid(definition[0], definition[1]); 113 | //_isValidResult = "Is Valid" + isValid.ToString(); 114 | } 115 | if (isValid == false) 116 | { 117 | break; 118 | } 119 | } 120 | 121 | if (isValid == true) 122 | { 123 | if (KeepSingleValue) 124 | { 125 | Clear(info.Key); 126 | } 127 | 128 | _bcssInfos.Add(info); 129 | } 130 | Update(); 131 | } 132 | 133 | protected internal async Task IsValid(string propName, string propValue, bool force = false) 134 | { 135 | object[] parameters = new object[] { propName, propValue }; 136 | if (_firstRendered || force == true) 137 | { 138 | bool result = await JSRuntime.InvokeAsync("checkcss", parameters); 139 | return result; 140 | } 141 | return true; 142 | } 143 | 144 | /// 145 | /// Check all BCSS classes if they are valid or not. The method will automatically removes stored and invalid BCSS classes. 146 | /// 147 | /// 148 | public async Task CheckAllValues() 149 | { 150 | List toBeDeletedInfos = new(); 151 | foreach (var item in _bcssInfos) 152 | { 153 | if (await CheckValueIsValid(item, true) == false) 154 | { 155 | toBeDeletedInfos.Add(item); 156 | } 157 | } 158 | _bcssInfos.RemoveAll(x => toBeDeletedInfos.Select(y => y.Key).Contains(x.Key)); 159 | } 160 | 161 | protected async Task CheckValueIsValid(BcssInfo? bcssInfo, bool force = false) 162 | { 163 | if (bcssInfo == null || bcssInfo.Value == null) 164 | { 165 | return false; 166 | } 167 | 168 | string[] definition = BlazorCssConverter.PostProcess(bcssInfo.Value).Split(':'); 169 | if (definition.Length > 1) 170 | { 171 | bool result = await IsValid(definition[0], definition[1], force); 172 | return result; 173 | } 174 | return false; 175 | } 176 | 177 | protected internal BcssInfo? CheckDuplicate(string key) 178 | { 179 | return _bcssInfos.FirstOrDefault(x => x.Key == key); 180 | } 181 | 182 | protected string GetMediaString(string breakpoint) 183 | { 184 | string result = string.Empty; 185 | foreach (var info in _bcssInfos.Where(x => x.Prefixes.Contains(breakpoint))) 186 | { 187 | var listedValue = info.Value?.Split(' ') ?? new string[0]; 188 | List processedValue = new(); 189 | foreach (var s in listedValue) 190 | { 191 | processedValue.Add(GetWebkitString(info.Prefixes) + BlazorCssConverter.PostProcess(s)); 192 | } 193 | result += $".{info.Key}{GetPrefixString(info.Prefixes)} {{ {string.Join("!important;", processedValue) + "!important;"} }}"; 194 | } 195 | return result; 196 | } 197 | 198 | protected string GetPrefixString(List prefixes) 199 | { 200 | var result = string.Empty; 201 | List match = _prefixes.Intersect(prefixes).ToList(); 202 | if (match.Any()) 203 | { 204 | result = $":{match.First()}"; 205 | } 206 | 207 | if (result == ":h") 208 | { 209 | return ":hover"; 210 | } 211 | if (result == ":f") 212 | { 213 | return ":focus"; 214 | } 215 | 216 | return result; 217 | } 218 | 219 | protected string GetWebkitString(List prefixes) 220 | { 221 | var result = string.Empty; 222 | if (prefixes.Contains("w")) 223 | { 224 | return "-webkit-"; 225 | } 226 | if (prefixes.Contains("m")) 227 | { 228 | return "-moz-"; 229 | } 230 | if (prefixes.Contains("o")) 231 | { 232 | return "-o-"; 233 | } 234 | if (prefixes.Contains("ms")) 235 | { 236 | return "-ms-"; 237 | } 238 | 239 | return result; 240 | } 241 | 242 | public void Update() 243 | { 244 | _shouldRender = true; 245 | StateHasChanged(); 246 | _shouldRender = false; 247 | } 248 | 249 | /// 250 | /// Removes all BCSS classes (if key is null or empty) or matched classes (if key specified). If a BCSS class is currently using in the page, it will automatically add again. 251 | /// 252 | /// 253 | public void Clear(string? key = null) 254 | { 255 | if (string.IsNullOrEmpty(key)) 256 | { 257 | _bcssInfos.Clear(); 258 | return; 259 | } 260 | _bcssInfos.RemoveAll(x => x.Key?.Split("-").First() == key.Split('-').First()); 261 | } 262 | 263 | /// 264 | /// Removes last added BcssInfo. 265 | /// 266 | public void ClearLast() 267 | { 268 | _bcssInfos.Remove(_bcssInfos.Last()); 269 | } 270 | 271 | private readonly List _breakpoints = new List() { "xs", "sm", "md", "lg", "xl", "mobile" }; 272 | private readonly List _prefixes = new List() 273 | { 274 | "active", 275 | "checked", 276 | "disabled", 277 | "empty", 278 | "enabled", 279 | "h", 280 | "hover", 281 | "f", 282 | "focus", 283 | "focus-visible", 284 | "focus-within", 285 | "first-child", 286 | "last-child", 287 | "link", 288 | "optional", 289 | "out-of-range", 290 | "read-only", 291 | "read-write", 292 | "required", 293 | "root", 294 | "target", 295 | "valid", 296 | "invalid", 297 | "visited" 298 | }; 299 | 300 | } 301 | } 302 | -------------------------------------------------------------------------------- /BCSS/Extensions/ServiceCollectionExtensions.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.DependencyInjection; 2 | using Microsoft.Extensions.DependencyInjection.Extensions; 3 | 4 | namespace BCSS.Services 5 | { 6 | public static class ServiceCollectionExtensions 7 | { 8 | public static IServiceCollection AddBcss(this IServiceCollection services) 9 | { 10 | services.TryAddScoped(); 11 | return services; 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /BCSS/Models/BcssInfo.cs: -------------------------------------------------------------------------------- 1 | namespace BCSS 2 | { 3 | public class BcssInfo 4 | { 5 | public List Prefixes { get; set; } = new List(); 6 | public string? Key { get; set; } 7 | public string? Value { get; set; } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /BCSS/Services/BcssService.cs: -------------------------------------------------------------------------------- 1 | using BCSS.Services; 2 | 3 | namespace BCSS 4 | { 5 | public class BcssService 6 | { 7 | public BlazorCssProvider? Provider { get; set; } 8 | 9 | public void Attach(BlazorCssProvider provider) 10 | { 11 | Provider = provider; 12 | } 13 | 14 | //This is the method where we need maximum performance. 15 | public string? Add(string value) 16 | { 17 | if (Provider == null) 18 | { 19 | return null; 20 | } 21 | 22 | List decodedValue = new(); 23 | 24 | string[] values = value.Split(' '); 25 | foreach (var val in values) 26 | { 27 | BcssInfo? duplicatedInfo = Provider.CheckDuplicate(val); 28 | if (duplicatedInfo != null) 29 | { 30 | decodedValue.Add(duplicatedInfo.Key ?? string.Empty); 31 | continue; 32 | } 33 | 34 | if (Provider.UnifiedClasses != null) 35 | { 36 | if (Provider.UnifiedClasses.ContainsKey(val)) 37 | { 38 | decodedValue.Add(Provider.UnifiedClasses[val]); 39 | continue; 40 | } 41 | } 42 | 43 | List prefixes = BlazorCssConverter.GetPrefixes(val); 44 | if (prefixes.Contains("c")) 45 | { 46 | decodedValue.Add(val); 47 | continue; 48 | } 49 | 50 | string? result = BlazorCssConverter.Convert(val, Provider); 51 | string key = Decode(val); 52 | BcssInfo info = new(); 53 | info.Prefixes = prefixes; 54 | info.Key = key; 55 | info.Value = result; 56 | _ = Provider.AddInfo(info); 57 | decodedValue.Add(key); 58 | } 59 | 60 | Provider.Update(); 61 | return string.Join(" ", decodedValue); 62 | } 63 | 64 | /// 65 | /// Clears regular BCSS classes. 66 | /// 67 | /// 68 | public void Clear(bool update = true) 69 | { 70 | if (Provider == null) 71 | { 72 | return; 73 | } 74 | Provider.Clear(); 75 | foreach (var item in Provider.UnifiedClasses ?? new Dictionary()) 76 | { 77 | AddUnifiedClass(item.Key, item.Value); 78 | } 79 | if (update == true) 80 | { 81 | Provider.Update(); 82 | } 83 | } 84 | 85 | /// 86 | /// Clears unified classes. 87 | /// 88 | /// 89 | public void ClearUnifiedClasses(bool update = true) 90 | { 91 | if (Provider == null) 92 | { 93 | return; 94 | } 95 | Provider.UnifiedClasses = null; 96 | if (update == true) 97 | { 98 | Provider.Update(); 99 | } 100 | } 101 | 102 | /// 103 | /// Clears both Unified Classes and regular BCSS classes. 104 | /// 105 | public void Reset() 106 | { 107 | if (Provider == null) 108 | { 109 | return; 110 | } 111 | 112 | ClearUnifiedClasses(false); 113 | Clear(false); 114 | Provider.Update(); 115 | } 116 | 117 | /// 118 | /// Adds unified classes with given user-created name and BCSS classes seperated with space. 119 | /// 120 | /// 121 | /// 122 | public void AddUnifiedClass(string unifiedName, string value) 123 | { 124 | if (Provider == null) 125 | { 126 | return; 127 | } 128 | 129 | if (Provider.UnifiedClasses == null) 130 | { 131 | Provider.UnifiedClasses = new(); 132 | } 133 | 134 | Add(value); 135 | Provider.UnifiedClasses.TryAdd(unifiedName, value); 136 | } 137 | 138 | public string? this[string key] 139 | { 140 | get => Add(key); 141 | } 142 | 143 | protected internal string Decode(string value) 144 | { 145 | string result = value.ToLower(); 146 | if (result.StartsWith("c:")) 147 | { 148 | result = result.Substring(2); 149 | } 150 | return result.Replace(':', 'q').Replace('/', 'w').Replace('*', 'e').Replace('#', 'r').Replace(',', 't').Replace('+', 'y').Replace('%', 'a').Replace('.', 's').Replace("[", null).Replace("]", null); 151 | } 152 | 153 | public void SetBreakpoints(int xs = 0, int sm = 600, int md = 960, int lg = 1280, int xl = 1920) 154 | { 155 | if (Provider == null) 156 | { 157 | return; 158 | } 159 | #pragma warning disable BL0005 160 | Provider.Sm = sm; 161 | Provider.Md = md; 162 | Provider.Lg = lg; 163 | Provider.Xl = xl; 164 | #pragma warning restore BL0005 165 | } 166 | 167 | public void SetSpacing(int value) 168 | { 169 | if (Provider == null) 170 | { 171 | return; 172 | } 173 | #pragma warning disable BL0005 174 | Provider.Spacing = value; 175 | #pragma warning restore BL0005 176 | } 177 | 178 | public void SetPerformanceMode(bool value) 179 | { 180 | if (Provider == null) 181 | { 182 | return; 183 | } 184 | #pragma warning disable BL0005 185 | Provider.PerformanceMode = value; 186 | #pragma warning restore BL0005 187 | } 188 | 189 | public async Task RemoveInvalidClasses() 190 | { 191 | if (Provider == null) 192 | { 193 | return; 194 | } 195 | await Provider.CheckAllValues(); 196 | } 197 | 198 | } 199 | } 200 | -------------------------------------------------------------------------------- /BCSS/Services/BlazorCssConverter.cs: -------------------------------------------------------------------------------- 1 | using System.Drawing; 2 | 3 | namespace BCSS.Services 4 | { 5 | public static class BlazorCssConverter 6 | { 7 | public static List GetPrefixes(string className) 8 | { 9 | var prefixes = new List(); 10 | if (string.IsNullOrWhiteSpace(className)) 11 | { 12 | return prefixes; 13 | } 14 | 15 | string key = string.Empty; 16 | if (className.Contains("--")) 17 | { 18 | key = className.Split("--").First(); 19 | } 20 | else 21 | { 22 | key = className.Split('-').First(); 23 | } 24 | 25 | if (key.Contains(':') == false) 26 | { 27 | return prefixes; 28 | } 29 | 30 | string[] partials = key.Replace('/', '-').Split(':'); 31 | for (int i = 0; i < partials.Length - 1; i++) 32 | { 33 | prefixes.Add(partials[i]); 34 | } 35 | return prefixes; 36 | } 37 | 38 | public static string Convert(string className, BlazorCssProvider? provider = null) 39 | { 40 | if (string.IsNullOrWhiteSpace(className)) 41 | { 42 | return string.Empty; 43 | } 44 | 45 | bool _shouldNotLowercase = false; 46 | if (className.Contains('[') && className.Contains('/')) 47 | { 48 | _shouldNotLowercase = true; 49 | } 50 | 51 | if (_shouldNotLowercase == false) 52 | { 53 | className = className.ToLower(); 54 | } 55 | 56 | if (className.Contains('-') == false) 57 | { 58 | return GetOneWordResult(className); 59 | } 60 | 61 | string? key = null; 62 | string? value = null; 63 | string[] splittedString = className.Split("--", 2); 64 | string[] processedString = className.Split('-'); 65 | 66 | if (splittedString.Length == 2 && (className.Contains('[') == false || (className.Contains('[') && className.IndexOf("--") < className.IndexOf("[")))) 67 | { 68 | key = splittedString[0].Split(':').Last(); 69 | value = splittedString[1]; 70 | } 71 | else 72 | { 73 | key = processedString.First().Split(':').Last().Replace('+', '-'); 74 | value = processedString.Length < 2 ? string.Empty : className.Substring(processedString.First().Length + 1); 75 | } 76 | 77 | if (_shouldNotLowercase == true) 78 | { 79 | key = key.ToLower(); 80 | } 81 | 82 | string? fullKey = GetFullKeyName(key.Replace("+", null)); 83 | string? processedValue = value; 84 | 85 | if (string.IsNullOrEmpty(value)) 86 | { 87 | return string.Empty; 88 | } 89 | 90 | string subString = GetCustomValue(value); 91 | processedValue = processedValue.Replace("[" + subString + "]", CustomValueResult(subString)); 92 | 93 | if (string.Equals(fullKey, "animation", StringComparison.InvariantCultureIgnoreCase)) 94 | { 95 | return SpacedResult(value, "animation"); 96 | } 97 | 98 | if (string.Equals(fullKey, "aspect-ratio", StringComparison.InvariantCultureIgnoreCase)) 99 | { 100 | switch (value) 101 | { 102 | case "video": 103 | return "aspect-ratio:16/9"; 104 | case "square": 105 | return "aspect-ratio:1/1"; 106 | default: 107 | return $"aspect-ratio:{processedValue}"; 108 | } 109 | } 110 | 111 | if (string.Equals(fullKey, "background", StringComparison.InvariantCultureIgnoreCase)) 112 | { 113 | switch (value) 114 | { 115 | case "fixed": 116 | return "background-attachment:fixed"; 117 | case "local": 118 | return "background-attachment:local"; 119 | case "scroll": 120 | return "background-attachment:scroll"; 121 | case "clip-box": 122 | return "background-clip:border-box"; 123 | case "clip-padding": 124 | return "background-clip:padding-box"; 125 | case "clip-content": 126 | return "background-clip:content-box"; 127 | case "clip-text": 128 | return "background-clip:text"; 129 | case "origin-border": 130 | return "background-origin:border-box"; 131 | case "origin-padding": 132 | return "background-origin:padding-box"; 133 | case "origin-content": 134 | return "background-origin:content-box"; 135 | case "bottom": 136 | return "background-position:bottom"; 137 | case "center": 138 | return "background-position:center"; 139 | case "top": 140 | return "background-position:top"; 141 | case "left": 142 | return "background-position:left"; 143 | case "right": 144 | return "background-position:right"; 145 | case "left-bottom": 146 | return "background-position:left bottom"; 147 | case "left-top": 148 | return "background-position:left top"; 149 | case "right-bottom": 150 | return "background-position:right bottom"; 151 | case "right-top": 152 | return "background-position:right top"; 153 | case "repeat": 154 | return "background-repeat:repeat"; 155 | case "no-repeat": 156 | return "background-repeat:no-repeat"; 157 | case "repeat-x": 158 | return "background-repeat:repeat-x"; 159 | case "repeat-y": 160 | return "background-repeat:repeat-y"; 161 | case "repeat-round": 162 | return "background-repeat:round"; 163 | case "repeat-space": 164 | return "background-repeat:space"; 165 | case "auto": 166 | return "background-size:auto"; 167 | case "cover": 168 | return "background-size:cover"; 169 | case "contain": 170 | return "background-size:contain"; 171 | case "none": 172 | return "background-image:none"; 173 | } 174 | return $"background:{processedValue}"; 175 | } 176 | 177 | if (string.Equals(fullKey, "backdrop-filter", StringComparison.InvariantCultureIgnoreCase)) 178 | { 179 | string[] splitVal = processedValue.Split('-'); 180 | if (2 <= splitVal.Length) 181 | { 182 | return $"backdrop-filter:{splitVal[0]}({splitVal[1]})"; 183 | } 184 | return $"backdrop-filter:{processedValue})"; 185 | } 186 | 187 | if (string.Equals(fullKey, "border", StringComparison.InvariantCultureIgnoreCase)) 188 | { 189 | switch (value) 190 | { 191 | case "solid": 192 | return "border-style:solid"; 193 | case "dashed": 194 | return "border-style:dashed"; 195 | case "dotted": 196 | return "border-style:dotted"; 197 | case "double": 198 | return "border-style:double"; 199 | case "hidden": 200 | return "border-style:hidden"; 201 | case "none": 202 | return "border-style:none"; 203 | } 204 | return SpacedResult(value, "border"); 205 | } 206 | 207 | if (string.Equals(fullKey, "border-bottom", StringComparison.InvariantCultureIgnoreCase)) 208 | { 209 | return SpacedResult(value, "border-bottom"); 210 | } 211 | 212 | if (string.Equals(fullKey, "border-top", StringComparison.InvariantCultureIgnoreCase)) 213 | { 214 | return SpacedResult(value, "border-top"); 215 | } 216 | 217 | if (string.Equals(fullKey, "border-left", StringComparison.InvariantCultureIgnoreCase)) 218 | { 219 | return SpacedResult(value, "border-left"); 220 | } 221 | 222 | if (string.Equals(fullKey, "border-right", StringComparison.InvariantCultureIgnoreCase)) 223 | { 224 | return SpacedResult(value, "border-right"); 225 | } 226 | 227 | if (string.Equals(fullKey, "bottom", StringComparison.InvariantCultureIgnoreCase)) 228 | { 229 | return DimensionResult(processedValue.Replace('n', '-'), fullKey); 230 | } 231 | 232 | if (string.Equals(fullKey, "box", StringComparison.InvariantCultureIgnoreCase)) 233 | { 234 | switch (value) 235 | { 236 | case "border": 237 | return "box-sizing:border-box"; 238 | case "content": 239 | return "box-sizing:content-box"; 240 | default: 241 | return $"box-sizing:{processedValue}"; 242 | } 243 | } 244 | 245 | if (string.Equals(fullKey, "filter", StringComparison.InvariantCultureIgnoreCase)) 246 | { 247 | string[] splitVal = processedValue.Split('-'); 248 | if (2 <= splitVal.Length) 249 | { 250 | return $"filter:{splitVal[0]}({splitVal[1]})"; 251 | } 252 | return $"filter:{processedValue})"; 253 | } 254 | 255 | if (string.Equals(fullKey, "flex", StringComparison.InvariantCultureIgnoreCase)) 256 | { 257 | switch (processedValue) 258 | { 259 | case "center": 260 | return "place-content:center place-items:center"; 261 | case "start": 262 | return "place-content:start place-items:start"; 263 | case "end": 264 | return "place-content:end place-items:end"; 265 | case "top-left": 266 | return "place-content:start place-items:start"; 267 | case "top-center": 268 | return "place-content:center place-items:start"; 269 | case "top-right": 270 | return "place-content:end place-items:start"; 271 | case "center-left": 272 | return "place-content:start place-items:center"; 273 | case "center-right": 274 | return "place-content:end place-items:center"; 275 | case "bottom-right": 276 | return "place-content:end place-items:end"; 277 | case "bottom-center": 278 | return "place-content:center place-items:end"; 279 | case "bottom-left": 280 | return "place-content:start place-items:end"; 281 | case "col": 282 | return "flex-direction:column"; 283 | case "col-reverse": 284 | return "flex-direction:column-reverse"; 285 | case "row": 286 | return "flex-direction:row"; 287 | case "row-reverse": 288 | return "flex-direction:row-reverse"; 289 | case "wrap": 290 | return "flex-wrap:wrap"; 291 | case "wrap-reverse": 292 | return "flex-wrap:wrap-reverse"; 293 | } 294 | return SpacedResult(processedValue, fullKey); 295 | } 296 | 297 | if (string.Equals(fullKey, "gap", StringComparison.InvariantCultureIgnoreCase)) 298 | { 299 | return DimensionResult(processedValue, fullKey, provider); 300 | } 301 | 302 | if (string.Equals(fullKey, "height", StringComparison.InvariantCultureIgnoreCase)) 303 | { 304 | return GetHeightWidthKeywordResult(processedValue, fullKey); 305 | } 306 | 307 | if (string.Equals(fullKey, "left", StringComparison.InvariantCultureIgnoreCase)) 308 | { 309 | return DimensionResult(processedValue.Replace('n', '-'), fullKey); 310 | } 311 | 312 | if (string.Equals(fullKey, "min-height", StringComparison.InvariantCultureIgnoreCase)) 313 | { 314 | return GetHeightWidthKeywordResult(processedValue, fullKey); 315 | } 316 | 317 | if (string.Equals(fullKey, "max-height", StringComparison.InvariantCultureIgnoreCase)) 318 | { 319 | return GetHeightWidthKeywordResult(processedValue, fullKey); 320 | } 321 | 322 | if (string.Equals(key, "ma", StringComparison.InvariantCultureIgnoreCase)) 323 | { 324 | return DimensionResult(processedValue?.Replace('n', '-'), "margin", provider); 325 | } 326 | 327 | if (string.Equals(key, "mt", StringComparison.InvariantCultureIgnoreCase)) 328 | { 329 | return DimensionResult(processedValue?.Replace('n', '-'), "margin-top", provider); 330 | } 331 | 332 | if (string.Equals(key, "mb", StringComparison.InvariantCultureIgnoreCase)) 333 | { 334 | return DimensionResult(processedValue?.Replace('n', '-'), "margin-bottom", provider); 335 | } 336 | 337 | if (string.Equals(key, "ml", StringComparison.InvariantCultureIgnoreCase)) 338 | { 339 | return DimensionResult(processedValue?.Replace('n', '-'), "margin-left", provider); 340 | } 341 | 342 | if (string.Equals(key, "mr", StringComparison.InvariantCultureIgnoreCase)) 343 | { 344 | return DimensionResult(processedValue?.Replace('n', '-'), "margin-right", provider); 345 | } 346 | 347 | if (string.Equals(key, "mx", StringComparison.InvariantCultureIgnoreCase)) 348 | { 349 | return DimensionResult(processedValue?.Replace('n', '-'), "margin-left", provider) + " " + DimensionResult(processedValue, "margin-right", provider); 350 | } 351 | 352 | if (string.Equals(key, "my", StringComparison.InvariantCultureIgnoreCase)) 353 | { 354 | return DimensionResult(processedValue?.Replace('n', '-'), "margin-top", provider) + " " + DimensionResult(processedValue, "margin-bottom", provider); 355 | } 356 | 357 | if (string.Equals(key, "ms", StringComparison.InvariantCultureIgnoreCase)) 358 | { 359 | return DimensionResult(processedValue?.Replace('n', '-'), "margin-inline-start", provider); 360 | } 361 | 362 | if (string.Equals(key, "me", StringComparison.InvariantCultureIgnoreCase)) 363 | { 364 | return DimensionResult(processedValue?.Replace('n', '-'), "margin-inline-end", provider); 365 | } 366 | 367 | if (string.Equals(key, "object", StringComparison.InvariantCultureIgnoreCase)) 368 | { 369 | switch (processedValue) 370 | { 371 | case "contain": 372 | return "object-fit:contain"; 373 | case "cover": 374 | return "object-fit:cover"; 375 | case "fill": 376 | return "object-fit:fill"; 377 | case "none": 378 | return "object-fit:none"; 379 | case "scale-down": 380 | return "object-fit:scale-down"; 381 | case "bottom": 382 | return "object-position:bottom"; 383 | case "center": 384 | return "object-position:center"; 385 | case "top": 386 | return "object-position:top"; 387 | case "left": 388 | return "object-position:left"; 389 | case "right": 390 | return "object-position:right"; 391 | case "left-bottom": 392 | return "object-position:left bottom"; 393 | case "left-top": 394 | return "object-position:left top"; 395 | case "right-bottom": 396 | return "object-position:right bottom"; 397 | case "right-top": 398 | return "object-position:right top"; 399 | } 400 | } 401 | 402 | if (string.Equals(fullKey, "opacity", StringComparison.InvariantCultureIgnoreCase)) 403 | { 404 | double dividedNum; 405 | if (double.TryParse(processedValue, out dividedNum)) 406 | { 407 | return $"opacity:{(dividedNum / 100d).ToString().Replace(',', '.')}"; 408 | } 409 | return $"opacity:{processedValue}"; 410 | } 411 | 412 | if (string.Equals(fullKey, "origin", StringComparison.InvariantCultureIgnoreCase)) 413 | { 414 | return SpacedResult(value, "transform-origin"); 415 | } 416 | 417 | if (string.Equals(fullKey, "overflow-x", StringComparison.InvariantCultureIgnoreCase)) 418 | { 419 | return $"overflow-x:{processedValue}"; 420 | } 421 | 422 | if (string.Equals(fullKey, "overflow-y", StringComparison.InvariantCultureIgnoreCase)) 423 | { 424 | return $"overflow-y:{processedValue}"; 425 | } 426 | 427 | if (string.Equals(key, "pa", StringComparison.InvariantCultureIgnoreCase)) 428 | { 429 | return DimensionResult(processedValue, "padding", provider); 430 | } 431 | 432 | if (string.Equals(key, "pt", StringComparison.InvariantCultureIgnoreCase)) 433 | { 434 | return DimensionResult(processedValue, "padding-top", provider); 435 | } 436 | 437 | if (string.Equals(key, "pb", StringComparison.InvariantCultureIgnoreCase)) 438 | { 439 | return DimensionResult(processedValue, "padding-bottom", provider); 440 | } 441 | 442 | if (string.Equals(key, "pl", StringComparison.InvariantCultureIgnoreCase)) 443 | { 444 | return DimensionResult(processedValue, "padding-left", provider); 445 | } 446 | 447 | if (string.Equals(key, "pr", StringComparison.InvariantCultureIgnoreCase)) 448 | { 449 | return DimensionResult(processedValue, "padding-right", provider); 450 | } 451 | 452 | if (string.Equals(key, "px", StringComparison.InvariantCultureIgnoreCase)) 453 | { 454 | return DimensionResult(processedValue, "padding-left", provider) + " " + DimensionResult(processedValue, "padding-right", provider); 455 | } 456 | 457 | if (string.Equals(key, "py", StringComparison.InvariantCultureIgnoreCase)) 458 | { 459 | return DimensionResult(processedValue, "padding-top", provider) + " " + DimensionResult(processedValue, "padding-bottom", provider); 460 | } 461 | 462 | if (string.Equals(key, "ps", StringComparison.InvariantCultureIgnoreCase)) 463 | { 464 | return DimensionResult(processedValue, "padding-inline-start", provider); 465 | } 466 | 467 | if (string.Equals(key, "pe", StringComparison.InvariantCultureIgnoreCase)) 468 | { 469 | return DimensionResult(processedValue, "padding-inline-end", provider); 470 | } 471 | 472 | if (string.Equals(key, "r", StringComparison.InvariantCultureIgnoreCase) || string.Equals(key, "rounded", StringComparison.InvariantCultureIgnoreCase)) 473 | { 474 | return DimensionResult(processedValue, "border-radius"); 475 | } 476 | 477 | if (string.Equals(key, "rlt", StringComparison.InvariantCultureIgnoreCase)) 478 | { 479 | return DimensionResult(processedValue, "border-top-left-radius"); 480 | } 481 | 482 | if (string.Equals(key, "rlb", StringComparison.InvariantCultureIgnoreCase)) 483 | { 484 | return DimensionResult(processedValue, "border-bottom-left-radius"); 485 | } 486 | 487 | if (string.Equals(key, "rrt", StringComparison.InvariantCultureIgnoreCase)) 488 | { 489 | return DimensionResult(processedValue, "border-top-right-radius"); 490 | } 491 | 492 | if (string.Equals(key, "rrb", StringComparison.InvariantCultureIgnoreCase)) 493 | { 494 | return DimensionResult(processedValue, "border-bottom-right-radius"); 495 | } 496 | 497 | if (string.Equals(key, "rt", StringComparison.InvariantCultureIgnoreCase)) 498 | { 499 | return DimensionResult(processedValue, "border-top-left-radius") + " " + DimensionResult(processedValue, "border-top-right-radius"); 500 | } 501 | 502 | if (string.Equals(key, "rb", StringComparison.InvariantCultureIgnoreCase)) 503 | { 504 | return DimensionResult(processedValue, "border-bottom-left-radius") + " " + DimensionResult(processedValue, "border-bottom-right-radius"); 505 | } 506 | 507 | if (string.Equals(key, "rl", StringComparison.InvariantCultureIgnoreCase)) 508 | { 509 | return DimensionResult(processedValue, "border-top-left-radius") + " " + DimensionResult(processedValue, "border-bottom-left-radius"); 510 | } 511 | 512 | if (string.Equals(key, "rr", StringComparison.InvariantCultureIgnoreCase)) 513 | { 514 | return DimensionResult(processedValue, "border-top-right-radius") + " " + DimensionResult(processedValue, "border-bottom-right-radius"); 515 | } 516 | 517 | if (string.Equals(key, "rs", StringComparison.InvariantCultureIgnoreCase)) 518 | { 519 | return DimensionResult(processedValue, "border-start-start-radius") + " " + DimensionResult(processedValue, "border-end-start-radius"); 520 | } 521 | 522 | if (string.Equals(key, "re", StringComparison.InvariantCultureIgnoreCase)) 523 | { 524 | return DimensionResult(processedValue, "border-end-end-radius") + " " + DimensionResult(processedValue, "border-start-end-radius"); 525 | } 526 | 527 | if (string.Equals(key, "resize", StringComparison.InvariantCultureIgnoreCase)) 528 | { 529 | switch (processedValue) 530 | { 531 | case "x": 532 | return "resize:horizontal"; 533 | case "y": 534 | return "resize:vertical"; 535 | case "": 536 | case null: 537 | return "resize:both"; 538 | } 539 | return $"resize:{processedValue}"; 540 | } 541 | 542 | if (string.Equals(fullKey, "right", StringComparison.InvariantCultureIgnoreCase)) 543 | { 544 | return DimensionResult(processedValue.Replace('n', '-'), fullKey); 545 | } 546 | 547 | if (string.Equals(fullKey, "rotate", StringComparison.InvariantCultureIgnoreCase)) 548 | { 549 | return $"transform:rotate({processedValue.Replace('n', '-')}deg)"; 550 | } 551 | 552 | if (string.Equals(fullKey, "rotatex", StringComparison.InvariantCultureIgnoreCase)) 553 | { 554 | return $"transform:rotateX({processedValue.Replace('n', '-')}deg)"; 555 | } 556 | 557 | if (string.Equals(fullKey, "rotatey", StringComparison.InvariantCultureIgnoreCase)) 558 | { 559 | return $"transform:rotateY({processedValue.Replace('n', '-')}deg)"; 560 | } 561 | 562 | if (string.Equals(fullKey, "rotatez", StringComparison.InvariantCultureIgnoreCase)) 563 | { 564 | return $"transform:rotateZ({processedValue.Replace('n', '-')}deg)"; 565 | } 566 | 567 | if (string.Equals(fullKey, "scale", StringComparison.InvariantCultureIgnoreCase)) 568 | { 569 | if (double.TryParse(processedValue, out double result)) 570 | { 571 | return $"transform:scale({(result / 100d).ToString().Replace(',', '.')})"; 572 | } 573 | else 574 | { 575 | return $"transform:scale({processedValue})"; 576 | } 577 | } 578 | 579 | if (string.Equals(fullKey, "scalex", StringComparison.InvariantCultureIgnoreCase)) 580 | { 581 | if (double.TryParse(processedValue, out double result)) 582 | { 583 | return $"transform:scaleX({(result / 100d).ToString().Replace(',', '.')})"; 584 | } 585 | else 586 | { 587 | return $"transform:scaleX({processedValue})"; 588 | } 589 | } 590 | 591 | if (string.Equals(fullKey, "scaley", StringComparison.InvariantCultureIgnoreCase)) 592 | { 593 | if (double.TryParse(processedValue, out double result)) 594 | { 595 | return $"transform:scaleY({(result / 100d).ToString().Replace(',', '.')})"; 596 | } 597 | else 598 | { 599 | return $"transform:scaleY({processedValue})"; 600 | } 601 | } 602 | 603 | if (string.Equals(fullKey, "shadow", StringComparison.InvariantCultureIgnoreCase)) 604 | { 605 | if (processedValue.Contains("inset")) 606 | { 607 | string[] splitVal = processedValue.Split("-"); 608 | if (int.TryParse(splitVal.Last(), out int splitResult)) 609 | { 610 | if (splitResult == 0) 611 | { 612 | return "box-shadow:none"; 613 | } 614 | return $"box-shadow:inset*0px*-{1 + (splitResult / 2)}px*{2 + (splitResult / 2) + (splitResult / 10)}px*{splitResult / 3}px*rgba(0,0,0,0.15),inset*0px*{1 + (splitResult / 2)}px*{2 + (splitResult / 2) + (splitResult / 10)}px*{splitResult / 3}px*rgba(0,0,0,0.15)"; 615 | } 616 | } 617 | if (int.TryParse(processedValue, out int result)) 618 | { 619 | if (result == 0) 620 | { 621 | return "box-shadow:none"; 622 | } 623 | return $"box-shadow:0px*{1 + (result / 2)}px*{2 + (result / 2) + (result / 10)}px*{result / 3}px*rgba(0,0,0,0.15)"; 624 | } 625 | else 626 | { 627 | return $"box-shadow:{processedValue}"; 628 | } 629 | 630 | } 631 | 632 | if (string.Equals(fullKey, "shadow-inset", StringComparison.InvariantCultureIgnoreCase)) 633 | { 634 | if (int.TryParse(processedValue, out int result)) 635 | { 636 | if (result == 0) 637 | { 638 | return "box-shadow:none"; 639 | } 640 | return $"box-shadow:inset*0px*-{1 + (result / 2)}px*{2 + (result / 2) + (result / 10)}px*{result / 3}px*rgba(0,0,0,0.15),inset*0px*{1 + (result / 2)}px*{2 + (result / 2) + (result / 10)}px*{result / 3}px*rgba(0,0,0,0.15)"; 641 | } 642 | else 643 | { 644 | return $"box-shadow:{processedValue}"; 645 | } 646 | 647 | } 648 | 649 | if (string.Equals(fullKey, "skew", StringComparison.InvariantCultureIgnoreCase)) 650 | { 651 | return $"transform:skew({processedValue}deg,{processedValue}deg)"; 652 | } 653 | 654 | if (string.Equals(fullKey, "skewx", StringComparison.InvariantCultureIgnoreCase)) 655 | { 656 | return $"transform:skewX({processedValue}deg)"; 657 | } 658 | 659 | if (string.Equals(fullKey, "skewy", StringComparison.InvariantCultureIgnoreCase)) 660 | { 661 | return $"transform:skewY({processedValue}deg)"; 662 | } 663 | 664 | if (string.Equals(fullKey, "top", StringComparison.InvariantCultureIgnoreCase)) 665 | { 666 | return DimensionResult(processedValue.Replace('n', '-'), fullKey); 667 | } 668 | 669 | if (string.Equals(fullKey, "translate", StringComparison.InvariantCultureIgnoreCase)) 670 | { 671 | return $"transform:translate({processedValue}px,{processedValue}px)"; 672 | } 673 | 674 | if (string.Equals(fullKey, "translatex", StringComparison.InvariantCultureIgnoreCase)) 675 | { 676 | return $"transform:translateX({processedValue}px)"; 677 | } 678 | 679 | if (string.Equals(fullKey, "translatey", StringComparison.InvariantCultureIgnoreCase)) 680 | { 681 | return $"transform:translateY({processedValue}px)"; 682 | } 683 | 684 | if (string.Equals(fullKey, "translatez", StringComparison.InvariantCultureIgnoreCase)) 685 | { 686 | return $"transform:translateZ({processedValue}px)"; 687 | } 688 | 689 | if (string.Equals(fullKey, "transition", StringComparison.InvariantCultureIgnoreCase)) 690 | { 691 | return SpacedResult(value, "transition"); 692 | } 693 | 694 | if (string.Equals(fullKey, "width", StringComparison.InvariantCultureIgnoreCase)) 695 | { 696 | return GetHeightWidthKeywordResult(processedValue, fullKey); 697 | } 698 | 699 | if (string.Equals(fullKey, "min-width", StringComparison.InvariantCultureIgnoreCase)) 700 | { 701 | return GetHeightWidthKeywordResult(processedValue, fullKey); 702 | } 703 | 704 | if (string.Equals(fullKey, "max-width", StringComparison.InvariantCultureIgnoreCase)) 705 | { 706 | return GetHeightWidthKeywordResult(processedValue, fullKey); 707 | } 708 | 709 | List filterValues = new() { "blur", "brightness", "contrast", "grayscale", "invert", "saturate", "sepia" }; 710 | if (filterValues.Contains(fullKey)) 711 | { 712 | return $"filter:{fullKey}({DimensionResult(processedValue)})"; 713 | } 714 | if (fullKey.StartsWith("bd") && filterValues.Contains(fullKey.Substring(2))) 715 | { 716 | return $"backdrop-filter:{fullKey.Substring(2)}({DimensionResult(processedValue)})"; 717 | } 718 | 719 | return $"{fullKey}:{processedValue}"; 720 | } 721 | 722 | public static string GetFullKeyName(string name) 723 | { 724 | if (string.IsNullOrEmpty(name)) 725 | { 726 | return string.Empty; 727 | } 728 | string val = name.Replace("-", null); 729 | switch (val) 730 | { 731 | case "ar": 732 | case "aspect": 733 | return "aspect-ratio"; 734 | case "b": 735 | return "border"; 736 | case "bb": 737 | case "borderb": 738 | return "border-bottom"; 739 | case "bt": 740 | case "bordert": 741 | return "border-top"; 742 | case "bl": 743 | case "borderl": 744 | return "border-left"; 745 | case "br": 746 | case "borderr": 747 | return "border-right"; 748 | case "bg": 749 | return "background"; 750 | case "bdfilter": 751 | return "backdrop-filter"; 752 | case "bgc": 753 | case "bgcolor": 754 | return "background-color"; 755 | case "bgi": 756 | case "bgimage": 757 | return "background-image"; 758 | case "box": 759 | case "boxsizing": 760 | return "box-sizing"; 761 | case "c": 762 | return "color"; 763 | case "d": 764 | return "display"; 765 | case "f": 766 | return "font"; 767 | case "h": 768 | return "height"; 769 | case "hmin": 770 | return "min-height"; 771 | case "hmax": 772 | return "max-height"; 773 | case "o": 774 | return "opacity"; 775 | case "of": 776 | case "flow": 777 | return "overflow"; 778 | case "ofx": 779 | case "overflowx": 780 | case "flowx": 781 | return "overflow-x"; 782 | case "ofy": 783 | case "overflowy": 784 | case "flowy": 785 | return "overflow-y"; 786 | case "p": 787 | case "pos": 788 | return "position"; 789 | case "scroll": 790 | return "scroll-behavior"; 791 | case "select": 792 | return "user-select"; 793 | case "touch": 794 | return "touch-action"; 795 | case "v": 796 | case "vis": 797 | return "visibility"; 798 | case "w": 799 | return "width"; 800 | case "wmin": 801 | case "w-min": 802 | return "min-width"; 803 | case "wmax": 804 | case "w-max": 805 | return "max-width"; 806 | case "ws": 807 | return "white-space"; 808 | case "z": 809 | case "zindex": 810 | return "z-index"; 811 | default: 812 | return name; 813 | } 814 | } 815 | 816 | public static string DimensionResult(string? value, string? cssName = null, BlazorCssProvider? provider = null) 817 | { 818 | if (value == null) 819 | { 820 | return string.Empty; 821 | } 822 | bool isNameNull = string.IsNullOrEmpty(cssName); 823 | 824 | if (value?.Contains("rem") == true || value?.Contains('%') == true || value?.Contains("vw") == true || value?.Contains("vh") == true || value?.Contains("em") == true || value?.Contains("deg") == true) 825 | { 826 | return $"{(isNameNull ? null : cssName + ":")}{value}"; 827 | } 828 | if (value?.Contains('.') == true) 829 | { 830 | return $"{(isNameNull ? null : cssName + ":")}{value}0rem"; 831 | } 832 | if (value?.Contains(',') == true) 833 | { 834 | return $"{(isNameNull ? null : cssName + ":")}{value.Replace(',', '.')}0em"; 835 | } 836 | if (provider != null && int.TryParse(value, out int result)) 837 | { 838 | return $"{(isNameNull ? null : cssName + ":")}{result * provider?.Spacing}px"; 839 | } 840 | return $"{(isNameNull ? null : cssName + ":")}{value}px"; 841 | } 842 | 843 | public static string SpacedResult(string? value, string? name = null) 844 | { 845 | if (value == null) 846 | { 847 | return string.Empty; 848 | } 849 | 850 | List partialValues = new(); 851 | 852 | if (value.Contains("ease-in-out")) 853 | { 854 | partialValues.Add("ease+in+out"); 855 | value = value.Replace("ease-in-out", ""); 856 | } 857 | if (value.Contains("ease-in")) 858 | { 859 | partialValues.Add("ease+in"); 860 | value = value.Replace("ease-in", ""); 861 | } 862 | if (value.Contains("ease-out")) 863 | { 864 | partialValues.Add("ease+out"); 865 | value = value.Replace("ease-out", ""); 866 | } 867 | if (value.Contains("background-color")) 868 | { 869 | partialValues.Add("background+color"); 870 | value = value.Replace("background-color", ""); 871 | } 872 | if (value.Contains("border-color")) 873 | { 874 | partialValues.Add("border+color"); 875 | value = value.Replace("border-color", ""); 876 | } 877 | if (value.Contains("box-shadow")) 878 | { 879 | partialValues.Add("box+shadow"); 880 | value = value.Replace("box-shadow", ""); 881 | } 882 | if (value.Contains("backdrop-filter")) 883 | { 884 | partialValues.Add("backdrop+filter"); 885 | value = value.Replace("backdrop-filter", ""); 886 | } 887 | 888 | string[] splittedValue = value.Split('-'); 889 | 890 | 891 | foreach (var val in splittedValue) 892 | { 893 | if (string.IsNullOrEmpty(val)) 894 | { 895 | continue; 896 | } 897 | if (name == null) 898 | { 899 | partialValues.Add(val); 900 | continue; 901 | } 902 | if (name == "transition" || name == "animation") 903 | { 904 | if (double.TryParse(val, out double result)) 905 | { 906 | partialValues.Add(result.ToString().Replace(',', '.') + "s"); 907 | continue; 908 | } 909 | } 910 | 911 | if (name.Contains("border")) 912 | { 913 | if (double.TryParse(val, out double result)) 914 | { 915 | partialValues.Add(result.ToString().Replace(',', '.') + "px"); 916 | continue; 917 | } 918 | } 919 | 920 | partialValues.Add(val); 921 | } 922 | string unifiedValue = string.Join("-", partialValues); 923 | string subString = GetCustomValue(unifiedValue); 924 | return $"{(string.IsNullOrEmpty(name) ? null : name + ":")}{unifiedValue.Replace("["+subString+"]", CustomValueResult(subString)).Replace('-', '*')}"; 925 | } 926 | 927 | public static string CustomValueResult(string? val) 928 | { 929 | if (string.IsNullOrWhiteSpace(val)) 930 | { 931 | return string.Empty; 932 | } 933 | if (val.Contains('#')) 934 | { 935 | Color color = new(); 936 | var ps = val.Split(',').First(); 937 | try 938 | { 939 | color = ColorTranslator.FromHtml(ps); 940 | } 941 | catch (Exception) 942 | { 943 | 944 | } 945 | string result = color.R + "," + color.G + "," + color.B + "," + color.A; 946 | return $"rgba({result})"; 947 | } 948 | if (val.Contains("--")) 949 | { 950 | return $"var({val})"; 951 | } 952 | if (val.Contains(',')) 953 | { 954 | return $"rgba({val})"; 955 | } 956 | if (val.StartsWith('/')) 957 | { 958 | return $"url({val.Substring(1)})"; 959 | } 960 | return val; 961 | } 962 | 963 | public static string GetHeightWidthKeywordResult(string value, string cssProp) 964 | { 965 | switch (value) 966 | { 967 | case "full": 968 | return $"{cssProp}:100%"; 969 | case "screen": 970 | return $"{cssProp}:100{(cssProp.Contains("width") ? "vw" : "vh")}"; 971 | case "min": 972 | return $"{cssProp}:min-content"; 973 | case "max": 974 | return $"{cssProp}:max-content"; 975 | case "fit": 976 | return $"{cssProp}:fit-content"; 977 | } 978 | return DimensionResult(value, cssProp); 979 | } 980 | 981 | public static string GetCustomValue(string? val) 982 | { 983 | if (string.IsNullOrWhiteSpace(val)) 984 | { 985 | return string.Empty; 986 | } 987 | if (val.Contains('[') && val.Contains(']')) 988 | { 989 | int startPos = val.IndexOf('['); 990 | int endPos = val.IndexOf("]"); 991 | string subString = val.Substring(startPos + 1, endPos - startPos - 1); 992 | return subString; 993 | } 994 | return val; 995 | } 996 | 997 | public static string PostProcess(string? val) 998 | { 999 | if (string.IsNullOrWhiteSpace(val)) 1000 | { 1001 | return string.Empty; 1002 | } 1003 | 1004 | return val.Replace('+', '-').Replace('*', ' '); 1005 | } 1006 | 1007 | public static string GetOneWordResult(string? className) 1008 | { 1009 | if (string.IsNullOrEmpty(className)) 1010 | { 1011 | return string.Empty; 1012 | } 1013 | 1014 | if (className.Contains(':')) 1015 | { 1016 | className = className.Split(':').Last(); 1017 | } 1018 | 1019 | switch (className) 1020 | { 1021 | case "absolute": 1022 | return "position:absolute"; 1023 | case "fill": 1024 | return "height:100% width:100%"; 1025 | case "fixed": 1026 | return "position:fixed"; 1027 | case "hidden": 1028 | return "display:none"; 1029 | case "invisible": 1030 | return "visibility:hidden"; 1031 | case "relative": 1032 | return "position:relative"; 1033 | case "static": 1034 | return "position:static"; 1035 | case "sticky": 1036 | return "position:sticky"; 1037 | case "visible": 1038 | return "visibility:visible"; 1039 | } 1040 | 1041 | return className; 1042 | } 1043 | 1044 | } 1045 | } 1046 | -------------------------------------------------------------------------------- /BCSS/_Imports.razor: -------------------------------------------------------------------------------- 1 | @using Microsoft.AspNetCore.Components.Web 2 | -------------------------------------------------------------------------------- /BCSS/bundleconfig.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "outputFileName": "wwwroot/Bcss.min.js", 4 | "inputFiles": [ 5 | "wwwroot/Bcss.js" 6 | ] 7 | } 8 | ] 9 | -------------------------------------------------------------------------------- /BCSS/wwwroot/Bcss.js: -------------------------------------------------------------------------------- 1 | function checkcss(propname, propvalue) { 2 | var result = CSS.supports(propname, propvalue); 3 | return result; 4 | } 5 | -------------------------------------------------------------------------------- /BCSS/wwwroot/Bcss.min.js: -------------------------------------------------------------------------------- 1 | function checkcss(n,t){return CSS.supports(n,t)} -------------------------------------------------------------------------------- /BCSSViewer.Docs/BCSSViewer.Docs.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net8.0;net9.0 5 | enable 6 | enable 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /BCSSViewer.Docs/Components/BcssCard.razor: -------------------------------------------------------------------------------- 1 | @namespace BCSSViewer.Docs 2 | @inject BcssService Bc 3 | 4 | 5 | 6 | 7 | @Header 8 | 9 | 10 | @Description 11 | 12 | 13 | 14 | @code { 15 | [Parameter] 16 | public string? Icon { get; set; } 17 | 18 | [Parameter] 19 | public string? Header { get; set; } 20 | 21 | [Parameter] 22 | public string? Description { get; set; } 23 | } 24 | -------------------------------------------------------------------------------- /BCSSViewer.Docs/Components/CodeBlock.razor: -------------------------------------------------------------------------------- 1 | @namespace BCSSViewer.Docs 2 | @inherits MudComponentBase 3 | @inject BcssService Bc 4 | 5 |
6 | @Title 7 | @Description 8 | @if (string.IsNullOrEmpty(Code) == false) 9 | { 10 |
11 |
@Code
12 |
13 | } 14 |
15 | 16 | @code { 17 | [Parameter] 18 | public string? Title { get; set; } 19 | 20 | [Parameter] 21 | public string? Description { get; set; } 22 | 23 | [Parameter] 24 | public string? Code { get; set; } 25 | } 26 | -------------------------------------------------------------------------------- /BCSSViewer.Docs/Components/PageBottomRouting.razor: -------------------------------------------------------------------------------- 1 | @namespace BCSSViewer.Docs 2 | @inject BcssService Bc 3 | 4 |
5 | Previous: @PreviousText 6 | Next: @NextText 7 |
8 | 9 | @code { 10 | [Parameter] 11 | public string? PreviousText { get; set; } 12 | 13 | [Parameter] 14 | public string? NextText { get; set; } 15 | 16 | [Parameter] 17 | public string? PreviousHref { get; set; } 18 | 19 | [Parameter] 20 | public string? NextHref { get; set; } 21 | } 22 | -------------------------------------------------------------------------------- /BCSSViewer.Docs/Pages/Configuration/BreakpointPage.razor: -------------------------------------------------------------------------------- 1 | @page "/configuration/breakpoints" 2 | @namespace BCSSViewer.Docs.Pages 3 | 4 | 5 | Breakpoints 6 | 7 | 8 | BCSS currently supports 5 breakpoints and 1 definition: xs, sm, md, lg and xl with 'mobile'. 9 | 1920")" /> 10 | ")" /> 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /BCSSViewer.Docs/Pages/Configuration/PerformanceModePage.razor: -------------------------------------------------------------------------------- 1 | @page "/configuration/performancemode" 2 | @namespace BCSSViewer.Docs.Pages 3 | 4 | 5 | Performance Mode 6 | 7 | 8 | BcssService has some validation checks when user adds a BCSS class. If PerformanceMode is true, these checks will disable and users have performance gain. It's especially remarkable on the first initialization and render of BCSS classes. 9 | ")" /> 10 | 11 | PerformanceMode is false by default. You may not need this feature until you have hundreds of components and BCSS classes. 12 | Check the Benchmark Page to see performance values with or without PerformanceMode. 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /BCSSViewer.Docs/Pages/Configuration/SpacingPage.razor: -------------------------------------------------------------------------------- 1 | @page "/configuration/spacing" 2 | @namespace BCSSViewer.Docs.Pages 3 | 4 | 5 | Spacing 6 | 7 | 8 | BlazorCssProvider has Spacing parameter that controls the pixel multiplier. With this way you can control all your application's density with one parameter. Default is 1. 9 | 10 | ")" /> 11 | 12 | Set spacing to 4 has familiar results like MudBlazor, Tailwind etc. Keep spacing 1 for full flexibility. 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /BCSSViewer.Docs/Pages/Content/ContentGeneralPage.razor: -------------------------------------------------------------------------------- 1 | @page "/content" 2 | @namespace BCSSViewer.Docs.Pages 3 | 4 | 5 | Contents 6 | 7 | All CSS property names are directly accepted as Bcss classnames. In this table, only shorthanded values are shown. 8 | 9 | 10 | Content 11 | 12 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | @code { 28 | private List _contents = new(); 29 | private string? _searchString; 30 | 31 | protected override void OnInitialized() 32 | { 33 | base.OnInitialized(); 34 | _contents.Add(new() { ShortName = "absolute", OriginalName = "position:absolute" }); 35 | _contents.Add(new() { ShortName = "ar, aspect", OriginalName = "aspect-ratio"}); 36 | _contents.Add(new() { ShortName = "b", OriginalName = "border" }); 37 | _contents.Add(new() { ShortName = "bb, b-b, borderb, border-b", OriginalName = "border-bottom" }); 38 | _contents.Add(new() { ShortName = "bl, b-l, borderl, border-l", OriginalName = "border-left" }); 39 | _contents.Add(new() { ShortName = "br, b-r, borderr, border-r", OriginalName = "border-right" }); 40 | _contents.Add(new() { ShortName = "bt, b-t, bordert, border-t", OriginalName = "border-top" }); 41 | _contents.Add(new() { ShortName = "bg", OriginalName = "background" }); 42 | _contents.Add(new() { ShortName = "bgc, bgcolor", OriginalName = "background-color" }); 43 | _contents.Add(new() { ShortName = "bgi, bgimage", OriginalName = "background-image" }); 44 | _contents.Add(new() { ShortName = "box, boxsizing", OriginalName = "box-sizing" }); 45 | _contents.Add(new() { ShortName = "c", OriginalName = "color" }); 46 | _contents.Add(new() { ShortName = "d", OriginalName = "display" }); 47 | _contents.Add(new() { ShortName = "f", OriginalName = "font" }); 48 | _contents.Add(new() { ShortName = "fill", OriginalName = "height:100% width:100%" }); 49 | _contents.Add(new() { ShortName = "fixed", OriginalName = "position:fixed" }); 50 | _contents.Add(new() { ShortName = "h", OriginalName = "height" }); 51 | _contents.Add(new() { ShortName = "hmin, h-min", OriginalName = "min-height" }); 52 | _contents.Add(new() { ShortName = "hmax, h-max", OriginalName = "max-height" }); 53 | _contents.Add(new() { ShortName = "hidden", OriginalName = "display:none" }); 54 | _contents.Add(new() { ShortName = "ma", OriginalName = "margin" }); 55 | _contents.Add(new() { ShortName = "mb", OriginalName = "margin-bottom" }); 56 | _contents.Add(new() { ShortName = "ml", OriginalName = "margin-left" }); 57 | _contents.Add(new() { ShortName = "mr", OriginalName = "margin-right" }); 58 | _contents.Add(new() { ShortName = "mt", OriginalName = "margin-top" }); 59 | _contents.Add(new() { ShortName = "ms", OriginalName = "margin-inline-start" }); 60 | _contents.Add(new() { ShortName = "me", OriginalName = "margin-inline-end" }); 61 | _contents.Add(new() { ShortName = "o", OriginalName = "opacity" }); 62 | _contents.Add(new() { ShortName = "of", OriginalName = "overflow" }); 63 | _contents.Add(new() { ShortName = "flow", OriginalName = "overflow" }); 64 | _contents.Add(new() { ShortName = "ofx, of-x, flowx, flow-x", OriginalName = "overflow-x" }); 65 | _contents.Add(new() { ShortName = "ofy, of-y, flowy, flow-y", OriginalName = "overflow-y" }); 66 | _contents.Add(new() { ShortName = "pa", OriginalName = "padding" }); 67 | _contents.Add(new() { ShortName = "pb", OriginalName = "padding-bottom" }); 68 | _contents.Add(new() { ShortName = "pl", OriginalName = "padding-left" }); 69 | _contents.Add(new() { ShortName = "pr", OriginalName = "padding-right" }); 70 | _contents.Add(new() { ShortName = "pt", OriginalName = "padding-top" }); 71 | _contents.Add(new() { ShortName = "ps", OriginalName = "padding-inline-start" }); 72 | _contents.Add(new() { ShortName = "pe", OriginalName = "padding-inline-end" }); 73 | _contents.Add(new() { ShortName = "p, pos", OriginalName = "position" }); 74 | _contents.Add(new() { ShortName = "r, rounded", OriginalName = "border-radius" }); 75 | _contents.Add(new() { ShortName = "relative", OriginalName = "position:relative" }); 76 | _contents.Add(new() { ShortName = "scroll", OriginalName = "scroll-behavior" }); 77 | _contents.Add(new() { ShortName = "select", OriginalName = "user-select" }); 78 | _contents.Add(new() { ShortName = "static", OriginalName = "position:static" }); 79 | _contents.Add(new() { ShortName = "sticky", OriginalName = "position:sticky" }); 80 | _contents.Add(new() { ShortName = "touch", OriginalName = "touch-action" }); 81 | _contents.Add(new() { ShortName = "v, vis", OriginalName = "visibility" }); 82 | _contents.Add(new() { ShortName = "visible", OriginalName = "visibility:visible" }); 83 | _contents.Add(new() { ShortName = "invisible", OriginalName = "visibility:hidden" }); 84 | _contents.Add(new() { ShortName = "w", OriginalName = "width" }); 85 | _contents.Add(new() { ShortName = "wmin, w-min", OriginalName = "min-width" }); 86 | _contents.Add(new() { ShortName = "wmax, w-max", OriginalName = "max-width" }); 87 | _contents.Add(new() { ShortName = "ws", OriginalName = "white-space" }); 88 | _contents.Add(new() { ShortName = "z, zindex", OriginalName = "z-index" }); 89 | } 90 | 91 | private Func _quickFilter => x => 92 | { 93 | if (string.IsNullOrWhiteSpace(_searchString)) 94 | return true; 95 | 96 | if (x.OriginalName?.Contains(_searchString, StringComparison.OrdinalIgnoreCase) == true) 97 | return true; 98 | 99 | if (x.ShortName?.Contains(_searchString, StringComparison.OrdinalIgnoreCase) == true) 100 | return true; 101 | 102 | return false; 103 | }; 104 | 105 | private class BcssContent 106 | { 107 | public string? ShortName { get; set; } 108 | public string? OriginalName { get; set; } 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /BCSSViewer.Docs/Pages/DevTools/BenchmarkPage.razor: -------------------------------------------------------------------------------- 1 | @page "/devtools/benchmark" 2 | @namespace BCSSViewer.Docs.Pages 3 | @using System.Diagnostics; 4 | @inject BcssService Bc 5 | 6 | 7 | Benchmark 8 | Create certain amount of items with or without BCSS and see the benchmark. 9 | 10 |
11 | @_buttonString 12 | Return Defaults 13 |
14 | 15 | 16 | @_elapsed points 17 | Creation Time 18 | 19 | 20 |
21 | 22 | 23 |
24 | 25 |
26 | 27 | 28 |
29 | 30 | 31 | 32 |
33 | @if (_render) 34 | { 35 | for (int i = 0; i < _itemCount; i++) 36 | { 37 | int a = i; 38 | if (_bcssRender) 39 | { 40 | @a 41 | } 42 | else 43 | { 44 | @a 45 | } 46 | } 47 | } 48 |
49 |
50 | 51 | @code { 52 | bool _render; 53 | bool _bcssRender; 54 | int _itemCount = 100; 55 | string _cssString = "bg-yellow"; 56 | Stopwatch st = new(); 57 | string _elapsed = ""; 58 | bool _stopped = false; 59 | string _buttonString = "Run Benchmark"; 60 | string _icon = Icons.Material.Filled.PlayArrow; 61 | 62 | private void Create() 63 | { 64 | st.Reset(); 65 | st.Start(); 66 | if (_render == true) 67 | { 68 | _render = false; 69 | _buttonString = "Run Benchmark"; 70 | _icon = Icons.Material.Filled.PlayArrow; 71 | } 72 | else 73 | { 74 | _stopped = false; 75 | _render = true; 76 | _buttonString = "Clear"; 77 | _icon = Icons.Material.Filled.ClearAll; 78 | } 79 | } 80 | 81 | protected override void OnAfterRender(bool firstRender) 82 | { 83 | if (_stopped == false) 84 | { 85 | _stopped = true; 86 | st.Stop(); 87 | _elapsed = st.ElapsedMilliseconds.ToString(); 88 | StateHasChanged(); 89 | } 90 | } 91 | 92 | private void ChangePerformanceMode(bool value) 93 | { 94 | Bc.SetPerformanceMode(value); 95 | } 96 | 97 | private void SetDefault() 98 | { 99 | _buttonString = "Run Benchmark"; 100 | _cssString = ""; 101 | Bc.Clear(); 102 | Bc.Add("hmin-100vh"); 103 | _cssString = "bg-yellow"; 104 | } 105 | } -------------------------------------------------------------------------------- /BCSSViewer.Docs/Pages/DevTools/QuickDebugPage.razor: -------------------------------------------------------------------------------- 1 | @page "/devtools/quickdebug" 2 | @namespace BCSSViewer.Docs.Pages 3 | @using BCSS.Services; 4 | @using Microsoft.JSInterop; 5 | @inject BcssService Bc 6 | @inject IJSRuntime JSRuntime 7 | @inject NavigationManager NavigationManager 8 | 9 | 10 | BCSS QuickDebug 11 | Write the BCSS class and press convert to see results. 12 | 13 | 14 | Convert 15 | 16 | Suffixes: @string.Join(", ", _prefixes) 17 | Value: @_value 18 | IsValid: 19 | 20 | 21 | @code { 22 | string _cssString = ""; 23 | List _prefixes = new(); 24 | string _value = ""; 25 | bool? _isValid = null; 26 | 27 | private async Task Convert() 28 | { 29 | _prefixes = BlazorCssConverter.GetPrefixes(_cssString); 30 | string[] values = _cssString.Split(' '); 31 | _value = string.Empty; 32 | foreach (var val in values) 33 | { 34 | string currentVal = BlazorCssConverter.PostProcess(BlazorCssConverter.Convert(val)); 35 | _value += GetWebkitString(_prefixes) + currentVal + " "; 36 | 37 | string[] definition = currentVal.Split(':'); 38 | if (definition.Length > 1) 39 | { 40 | object[] parameters = new object[] { definition[0], definition[1] }; 41 | _isValid = await JSRuntime.InvokeAsync("checkcss", parameters); 42 | } 43 | } 44 | } 45 | 46 | private string GetWebkitString(List prefixes) 47 | { 48 | var result = string.Empty; 49 | if (prefixes.Contains("w")) 50 | { 51 | return "-webkit-"; 52 | } 53 | if (prefixes.Contains("m")) 54 | { 55 | return "-moz-"; 56 | } 57 | if (prefixes.Contains("o")) 58 | { 59 | return "-o-"; 60 | } 61 | if (prefixes.Contains("ms")) 62 | { 63 | return "-ms-"; 64 | } 65 | 66 | return result; 67 | } 68 | } -------------------------------------------------------------------------------- /BCSSViewer.Docs/Pages/GettingStarted/HowItWorksPage.razor: -------------------------------------------------------------------------------- 1 | @page "/gettingstarted/howitworks" 2 | @namespace BCSSViewer.Docs.Pages 3 | 4 | 5 | How It Works 6 | 7 | 8 | BCSS works through two basic and key parts: BlazorCssProvider and BcssService. 9 | 10 | BlazorCssProvider is a razor component. The component automatically converts the BCSS class names passed to it into css styles. 11 | Works on the principle of set-it-and-forget-it component. 12 | It is placed in App.razor in the root layer of the application and initial values ​​are determined. 13 | Once in place, no referencing or modification required. 14 | 15 | 16 | BcssService is a classic service that can be used with Dependency Injection (DI). 17 | This service communicates with the Blazor CSS Provider component, controls it and performs all optimization operations. 18 | Unlike the BlazorCssProvider component, it can be injected on multiple pages or layouts. 19 | Operations such as cleaning, updating and configuring can be called manually by this service. 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /BCSSViewer.Docs/Pages/GettingStarted/InstallationPage.razor: -------------------------------------------------------------------------------- 1 | @page "/gettingstarted/installation" 2 | @namespace BCSSViewer.Docs.Pages 3 | 4 | 5 | Installation 6 | 7 | 8 | 9 | 10 | ")" /> 11 | 12 | ")" /> 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /BCSSViewer.Docs/Pages/GettingStarted/WhatPage.razor: -------------------------------------------------------------------------------- 1 | @page "/gettingstarted/what" 2 | @namespace BCSSViewer.Docs.Pages 3 | @inject BcssService Bc 4 | 5 | 6 | What is BCSS 7 | BCSS is runtime CSS generator for Blazor. 8 | 9 | 10 | 11 | BCSS has it's own user-friendly classnames (Called BCSS classnames like 'hidden', 'w-200', 'bg-yellow'). 12 | In the background these classes successully transformed to valid CSS properties and styled your whole application. 13 | 14 | 15 | Why BCSS 16 | BCSS has several advantages: 17 | 18 | 19 | Dynamic. 20 | All values completely transform on runtime. 21 | It means users can easily change the CSS properties on runtime instantly. 22 | 23 | 24 | 25 | Fast & Optimized. 26 | BCSS has a great balance between performance and features. 27 | Optimizing the code is always a top priority. 28 | There are many performance enhancing features to avoid runtime overhead as much as possible. 29 | 30 | 31 | 32 | Flexible. 33 | There are other libraries that provides user-friendly classnames like tailwind. 34 | BCSS uses the Blazor logic and provides the widest flexible options. 35 | It is possible to write all CSS properties with BCSS syntax. No need to use any inline-styles or pre-defined CSS files. 36 | BCSS also has shorthand classname syntax to maximize 37 | 38 | 39 | 40 | Rapid Development. 41 | BCSS also has shorthand classname syntax to maximize the ease of usage. 42 | A good looking page can be crated in a single file within couple of minutes. 43 | Thousands of CSS code lines can be represent with dozens of BCSS classnames. 44 | 45 | 46 | 47 | Lightweight & No Dependency. 48 | BCSS has no external dependency. The total NuGet package has below of 100kb size. 49 | 50 | 51 | 52 | Fast Learning Progress 53 | There is no steep learning curve. For users are familiar with tailwind etc. libraries, takes less than 1 day to start development. 54 | 55 | 56 | 57 | BCSS instead of JS and CSS. 58 | Users no need to know JS. A basic-level CSS knowledge is sufficient to use BCSS. 59 | For users that don't have any experience with CSS, BCSS docs clearly describes the usage. 60 | All BCSS statements written in razor files with C# syntax. So even C# variables are valid for store and change CSS properties. 61 | 62 | 63 | 64 | Use C# and razor files. 65 | All CSS statements written in razor files with C# syntax. So even C# variables are valid for store and change CSS properties. 66 | 67 | 68 | 69 | Complete .NET support. 70 | BCSS supports all currently supporting .NET frameworks: .NET 6, .NET 7 and .NET 8. 71 | As a customized library of Blazor, can easily download with NuGet. 72 | 73 | 74 | 75 | OpenSource. 76 | BCSS will free forever and continued to implement better BCSS classname syntax and performance improvements. 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | -------------------------------------------------------------------------------- /BCSSViewer.Docs/Pages/Index.razor: -------------------------------------------------------------------------------- 1 | @page "/" 2 | @using Microsoft.JSInterop; 3 | @inject BcssService Bc 4 | @inject NavigationManager NavigationManager 5 | @inject IJSRuntime JSRuntime 6 | 7 | 8 |
9 | Blazor- 10 | CSS 11 |
12 | 13 | Revolutionary Runtime 15 | CSS Generator 16 | 17 | by CodeBeam 18 | 19 | GET STARTED 20 |
21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 |
51 | 52 | 53 |
54 | Perfect Balance Between Performance and Development Speed 55 | Easy to learn, implement and refactor the code. Less files and size, more capability. Have a complete control on your styles without JS. 56 |
57 | 58 | 59 | 60 | PlayGround 61 | Try the BCSS abilities and re-style the box. Don't be shy to write or click! 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | @_playgroundText 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | Showcase 84 | Let's make a more real world thing with a little bit more BCSS. 85 | 86 | 87 | 88 | 89 | @if (_boring) 90 | { 91 | Click To Style The Boring Card 92 | } 93 | else 94 | { 95 | 96 | 97 | 98 | } 99 | 100 | 101 | 102 |
103 | MCK 104 | Mehmet Can Karagöz 105 | Creator of BCSS 106 | 107 | Achievements 108 |
109 | 110 | 111 | 112 |
113 |
114 |
115 |
116 |
117 |
118 | 119 | 120 | Like It? 121 | Learn the Fundamentals 122 |
123 | Syntax 124 | Content 125 |
126 |
127 | 128 | @code { 129 | 130 | bool _boring = true; 131 | 132 | string _cssString = ""; 133 | string[] _possibleWidth = new string[] { "w-100", "w-125", "w-150", "w-175", "w-200", "w-225", "w-250", "w-275", "w-300" }; 134 | string[] _possibleHeight = new string[] { "h-100", "h-125", "h-150", "h-175", "h-200", "h-225", "h-250", "h-275", "h-300" }; 135 | string[] _possibleColors = new string[] { "bg-purple", "bg-midnightblue", "bg-blue", "bg-crimson", "bg-steelblue", "bg-purple", "bg-pink", "bg-teal", "bg-orange", "bg-[#123456]", "bg-[#efefef]", "bg-lightsalmon" }; 136 | string[] _possibleRounded = new string[] { "r-0", "r-20", "r-50", "r-50%", "r-100%" }; 137 | string[] _possibleBorders = new string[] { "", "b--8px-solid-yellow", "b--8px-dotted-yellow", "b--4px-dashed-yellow", "b--8px-solid-snow", "b--8px-dotted-snow", "b--4px-solid-snow" }; 138 | string[] _possibleCursor = new string[] { "cursor-default", "cursor-pointer", "cursor-progress", "cursor--not-allowed", "cursor-move", "cursor-help" }; 139 | string[] _possibleShadow = new string[] { "", "box-shadow--5px*5px*5px*black", "box-shadow--5px*-5px*10px*black", "box-shadow---5px*5px*20px*black" }; 140 | string _playgroundText = "Click On Me!"; 141 | 142 | private void Generate() 143 | { 144 | Random rnd = new(); 145 | int val = rnd.Next(0, 9); 146 | _cssString = _possibleWidth[val]; 147 | val = rnd.Next(0, 9); 148 | _cssString += $" {_possibleHeight[val]}"; 149 | val = rnd.Next(0, 12); 150 | _cssString += $" {_possibleColors[val]}"; 151 | if (10 <= val) 152 | { 153 | _cssString += " color-black"; 154 | } 155 | else 156 | { 157 | _cssString += " color-white"; 158 | } 159 | val = rnd.Next(0, 5); 160 | _cssString += $" {_possibleRounded[val]}"; 161 | val = rnd.Next(0, 7); 162 | _cssString += $" {_possibleBorders[val]}"; 163 | val = rnd.Next(0, 6); 164 | _cssString += $" {_possibleCursor[val]}"; 165 | val = rnd.Next(0, 4); 166 | _cssString += $" {_possibleShadow[val]}"; 167 | _playgroundText = "One More Lucky Click!"; 168 | } 169 | 170 | string[] _possibleSpacing = new string[] { "", "gap-2", "gap-4", "gap-6", "gap-8", "gap-10" }; 171 | string[] _possibleInsideBorders = new string[] { "", "b--2px-solid-yellow", "b--2px-dotted-yellow", "b--2px-dashed-yellow", "b--2px-solid-snow", "b--2px-dotted-snow", "b--2px-dashed-snow" }; 172 | string[] _possibleDimensions = new string[] { "w-100 h-100", "w-120 h-120", "w-140 h-140", "w-160 h-160" }; 173 | string[] _possibleFonts = new string[] { "font-family--Roboto", "font-family--Fuggles", "font-family--Pixelify*Sans", "font-family--Young*Serif" }; 174 | string[] _possibleHover = new string[] { "", "h:scale-150", "h:rotate-45", "h:rotate-90", "h:rotate-360", "h:rotate:720" }; 175 | 176 | string _showcaseString = ""; 177 | string _iconClass = ""; 178 | string _spacingClass = ""; 179 | string _colorClass = ""; 180 | string _dimensionClass = ""; 181 | string _fontClass = ""; 182 | string _hoverClass = ""; 183 | 184 | private void GenerateShowcase() 185 | { 186 | _boring = false; 187 | _showcaseString = ""; 188 | Random rnd = new(); 189 | int val = rnd.Next(0, 6); 190 | _spacingClass = _possibleSpacing[val]; 191 | val = rnd.Next(0, 4); 192 | _dimensionClass = _possibleDimensions[val]; 193 | val = rnd.Next(0, 6); 194 | _hoverClass = _possibleHover[val]; 195 | val = rnd.Next(0, 12); 196 | _showcaseString += $" {_possibleColors[val]}"; 197 | _colorClass = $" {_possibleColors[val]}"; 198 | if (10 <= val) 199 | { 200 | _showcaseString += " color-black"; 201 | _colorClass += " color-black"; 202 | } 203 | else 204 | { 205 | _showcaseString += " color-white"; 206 | _colorClass += " color-white"; 207 | } 208 | val = rnd.Next(0, 5); 209 | _showcaseString += $" {_possibleRounded[val]}"; 210 | val = rnd.Next(0, 7); 211 | _showcaseString += $" {_possibleBorders[val]}"; 212 | _iconClass = $" {_possibleInsideBorders[val]}"; 213 | val = rnd.Next(0, 4); 214 | _showcaseString += $" {_possibleShadow[val]}"; 215 | val = rnd.Next(0, 4); 216 | _fontClass = $" {_possibleFonts[val]}"; 217 | } 218 | 219 | protected override async Task OnAfterRenderAsync(bool firstRender) 220 | { 221 | if (firstRender) 222 | { 223 | await ScrollToFragment(); 224 | } 225 | } 226 | 227 | private async Task ScrollToFragment() 228 | { 229 | var uri = new Uri(NavigationManager.Uri, UriKind.Absolute); 230 | var fragment = uri.Fragment; 231 | if (fragment.StartsWith('#')) 232 | { 233 | // Handle text fragment (https://example.org/#test:~:text=foo) 234 | // https://github.com/WICG/scroll-to-text-fragment/ 235 | var elementId = fragment.Substring(1); 236 | var index = elementId.IndexOf(":~:", StringComparison.Ordinal); 237 | if (index > 0) 238 | { 239 | elementId = elementId.Substring(0, index); 240 | } 241 | 242 | if (!string.IsNullOrEmpty(elementId)) 243 | { 244 | await JSRuntime.InvokeVoidAsync("BlazorScrollToId", elementId); 245 | } 246 | } 247 | } 248 | } 249 | -------------------------------------------------------------------------------- /BCSSViewer.Docs/Pages/SpecialContent/FilterPage.razor: -------------------------------------------------------------------------------- 1 | @page "/contentspecial/filter" 2 | @namespace BCSSViewer.Docs.Pages 3 | 4 | 5 | Filter & BackdropFilter 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /BCSSViewer.Docs/Pages/SpecialContent/FlexboxPage.razor: -------------------------------------------------------------------------------- 1 | @page "/contentspecial/flexbox" 2 | @namespace BCSSViewer.Docs.Pages 3 | 4 | 5 | Flexbox 6 | 7 | 8 | If you're new to CSS, check out these two great resources on flexbox for better understand this page: (1)W3 Schools (2)CSS Tricks 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /BCSSViewer.Docs/Pages/SpecialContent/ShadowPage.razor: -------------------------------------------------------------------------------- 1 | @page "/contentspecial/shadow" 2 | @namespace BCSSViewer.Docs.Pages 3 | 4 | 5 | Shadow 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /BCSSViewer.Docs/Pages/SpecialContent/TransformPage.razor: -------------------------------------------------------------------------------- 1 | @page "/contentspecial/transform" 2 | @namespace BCSSViewer.Docs.Pages 3 | 4 | 5 | Transforms 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /BCSSViewer.Docs/Pages/SpecialContent/TransitionPage.razor: -------------------------------------------------------------------------------- 1 | @page "/contentspecial/transition" 2 | @namespace BCSSViewer.Docs.Pages 3 | 4 | 5 | Transitions 6 | 7 | 8 | 9 | Transition values have no order. However, the first number value represents delay, and other one represents duration. 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /BCSSViewer.Docs/Pages/Syntax/AdvancedSyntaxPage.razor: -------------------------------------------------------------------------------- 1 | @page "/syntax/advancedsyntax" 2 | @namespace BCSSViewer.Docs.Pages 3 | 4 | 5 | Advanced Syntax (Manual Typing) 6 | Normally BCSS classes can be created with dash (-) character. But in advanced scenarios '*' and '+' character are also allowed. 7 | 8 | 9 | 10 | With advanced syntax, all CSS statements can be transform into BCSS. If your basic syntax doesn't work, try with advanced syntax. 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /BCSSViewer.Docs/Pages/Syntax/BasicSyntaxPage.razor: -------------------------------------------------------------------------------- 1 | @page "/syntax/basics" 2 | @namespace BCSSViewer.Docs.Pages 3 | 4 | 5 | Basic Syntax 6 | 7 | 8 | 9 | 10 | All full names of CSS properties are allowed for left side of the dash. However there are lots of abbreviated BCSS names for easier usage. For all BCSS definitions, please look at Content section. 11 | ")" /> 12 | \n//Adds width: 200px; height: 120px; border-radius: 20px;")" /> 13 | If you add a BCSS class once, it also works in simple class. However this kind of usage is not recommended and not a best practice. 14 | //works, standard BCSS usage\n
//works because w-200 already defined in first div\n
//doesn't work because h-200 never defined in a BCSS class")" /> 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /BCSSViewer.Docs/Pages/Syntax/CaseInsensitivePage.razor: -------------------------------------------------------------------------------- 1 | @page "/syntax/casesensitivity" 2 | @namespace BCSSViewer.Docs.Pages 3 | 4 | 5 | Case Sensitivity 6 | 7 | 8 | 9 | 10 | BCSS also supports dotted i (i, İ, ı, I) case insensitive. (Known in Turkic languages like Turkish.) 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /BCSSViewer.Docs/Pages/Syntax/CustomClassesPage.razor: -------------------------------------------------------------------------------- 1 | @page "/syntax/customclasses" 2 | @namespace BCSSViewer.Docs.Pages 3 | 4 | 5 | Custom Classes 6 | 7 | 8 | \n\t.user-custom-class {\n\t\tbackground: yellow;\n\t}\n")" /> 9 | ")" /> 10 | ")" /> 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /BCSSViewer.Docs/Pages/Syntax/CustomValuesPage.razor: -------------------------------------------------------------------------------- 1 | @page "/syntax/customvalues" 2 | @namespace BCSSViewer.Docs.Pages 3 | 4 | 5 | Custom Values 6 | 7 | In BCSS, custom values should place in square brackets. BCSS automatically converts them if syntax is proper. 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /BCSSViewer.Docs/Pages/Syntax/DoubleDashPage.razor: -------------------------------------------------------------------------------- 1 | @page "/syntax/doubledash" 2 | @namespace BCSSViewer.Docs.Pages 3 | 4 | 5 | Dash and Double Dash Technique 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /BCSSViewer.Docs/Pages/Syntax/PrefixesPage.razor: -------------------------------------------------------------------------------- 1 | @page "/syntax/prefixes" 2 | @namespace BCSSViewer.Docs.Pages 3 | 4 | 5 | Prefixes 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /BCSSViewer.Docs/Pages/Syntax/UnifiedClassPage.razor: -------------------------------------------------------------------------------- 1 | @page "/syntax/unifiedclass" 2 | @namespace BCSSViewer.Docs.Pages 3 | 4 | 5 | Unified Class (Reusing Classes) 6 | 7 | 8 | Element 1
\n
Element 2
\n
Element 3
")" /> 9 | Element 1
")" /> 10 | Element 1")" /> 11 | AddUnifiedClass method can't use in OnInitialized and OnParametersSet methods. 12 | A UnifiedClass should not be same one of the regular BCSS class (like hidden). 13 |
14 | 15 | 16 |
17 | -------------------------------------------------------------------------------- /BCSSViewer.Docs/Pages/Syntax/UnitMeasurementPage.razor: -------------------------------------------------------------------------------- 1 | @page "/syntax/unitmeasurement" 2 | @namespace BCSSViewer.Docs.Pages 3 | 4 | 5 | Unit Measurement 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /BCSSViewer.Docs/Pages/Syntax/VendorPrefixesPage.razor: -------------------------------------------------------------------------------- 1 | @page "/syntax/vendorprefixes" 2 | @namespace BCSSViewer.Docs.Pages 3 | 4 | 5 | Vendor Prefixes 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /BCSSViewer.Docs/Shared/MainLayout.razor: -------------------------------------------------------------------------------- 1 | @using Microsoft.AspNetCore.Components.Routing; 2 | @inherits LayoutComponentBase 3 | @inject BcssService Bc 4 | @inject NavigationManager NavigationManager 5 | 6 | 7 | 8 | 9 | 10 | 11 | BCSS 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | What is & Why BCSS 21 | How It Works 22 | Installation 23 | 24 | 25 | Breakpoints 26 | Spacing 27 | Performance Mode 28 | 29 | 30 | Basics and Usage 31 | Dash and Double Dash 32 | Advanced Syntax 33 | Unit Measurement (Px, Rem) 34 | Prefixes (Breakpoints, Hover, Focus etc.) 35 | Vendor Prefixes (webkit, moz, ms, o) 36 | Custom Classes 37 | Custom Values & Colors 38 | Case Sensitivity 39 | Unified Class (Reusing Classes) 40 | 41 | 42 | General 43 | Borders 44 | Dimensions 45 | Position 46 | Text 47 | 48 | 49 | Filter & Backdrop Filter 50 | Flexbox 51 | Shadow 52 | Transforms 53 | Transitions 54 | 55 | 56 | QuickDebug 57 | Benchmark 58 | 59 | 60 | 61 | 62 | 63 | @Body 64 | 65 | CodeBeam OpenSource @DateTime.Now.Year. 66 | 67 | 68 | 69 | Donate 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | @code { 81 | MudTheme _bcssTheme = new MudTheme() 82 | { 83 | PaletteLight = new PaletteLight() 84 | { 85 | Primary = "#313B72", 86 | Secondary = "#F45B69", 87 | Tertiary = "#EEF4D4", 88 | TertiaryContrastText = "#000000", 89 | }, 90 | 91 | PaletteDark = new PaletteDark() 92 | { 93 | Secondary = "#F45B69", 94 | Tertiary = "#EEF4D4", 95 | TertiaryContrastText = "#000000", 96 | }, 97 | }; 98 | 99 | MudThemeProvider? _mudThemeProvider; 100 | private bool _open; 101 | private bool _darkMode = false; 102 | 103 | protected override async Task OnAfterRenderAsync(bool firstRender) 104 | { 105 | if (firstRender) 106 | { 107 | if (_mudThemeProvider != null) 108 | { 109 | _darkMode = await _mudThemeProvider.GetSystemPreference(); 110 | } 111 | Bc.AddUnifiedClass("classOfBcss", "bg-yellow color-blue"); 112 | StateHasChanged(); 113 | } 114 | } 115 | 116 | private bool GetExpandedStatus(string routeString) 117 | { 118 | if (NavigationManager.Uri.Contains(routeString)) 119 | { 120 | if (routeString == "content" && NavigationManager.Uri.Contains("contentspecial")) 121 | { 122 | return false; 123 | } 124 | return true; 125 | } 126 | return false; 127 | } 128 | 129 | private string Version 130 | { 131 | get 132 | { 133 | Version v = typeof(BlazorCssProvider).Assembly.GetName().Version ?? new(); 134 | return $"v {v.Major}.{v.Minor}.{v.Build}"; 135 | } 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /BCSSViewer.Docs/_Imports.razor: -------------------------------------------------------------------------------- 1 | @using Microsoft.AspNetCore.Components.Web 2 | 3 | @using BCSS 4 | @using MudBlazor 5 | @using MudExtensions 6 | -------------------------------------------------------------------------------- /BCSSViewer.Docs/wwwroot/background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeBeamOrg/BCSS/dd1657245b2114b7baa15054ac630ec51e6fa0b0/BCSSViewer.Docs/wwwroot/background.png -------------------------------------------------------------------------------- /BCSSViewer.Wasm/App.razor: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | Not found 8 | 9 |

Sorry, there's nothing at this address.

10 |
11 |
12 |
13 | -------------------------------------------------------------------------------- /BCSSViewer.Wasm/BCSSViewer.Wasm.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net9.0 5 | enable 6 | enable 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /BCSSViewer.Wasm/Program.cs: -------------------------------------------------------------------------------- 1 | using BCSS.Services; 2 | using BCSSViewer.Wasm; 3 | using Microsoft.AspNetCore.Components.Web; 4 | using Microsoft.AspNetCore.Components.WebAssembly.Hosting; 5 | using MudBlazor.Services; 6 | using MudExtensions.Services; 7 | 8 | var builder = WebAssemblyHostBuilder.CreateDefault(args); 9 | builder.RootComponents.Add("#app"); 10 | builder.RootComponents.Add("head::after"); 11 | 12 | builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) }); 13 | builder.Services.AddMudServices(); 14 | builder.Services.AddMudExtensions(); 15 | builder.Services.AddBcss(); 16 | 17 | await builder.Build().RunAsync(); 18 | -------------------------------------------------------------------------------- /BCSSViewer.Wasm/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "iisSettings": { 3 | "windowsAuthentication": false, 4 | "anonymousAuthentication": true, 5 | "iisExpress": { 6 | "applicationUrl": "http://localhost:20438", 7 | "sslPort": 44393 8 | } 9 | }, 10 | "profiles": { 11 | "http": { 12 | "commandName": "Project", 13 | "dotnetRunMessages": true, 14 | "launchBrowser": true, 15 | "inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}", 16 | "applicationUrl": "http://localhost:5113", 17 | "environmentVariables": { 18 | "ASPNETCORE_ENVIRONMENT": "Development" 19 | } 20 | }, 21 | "https": { 22 | "commandName": "Project", 23 | "dotnetRunMessages": true, 24 | "launchBrowser": true, 25 | "inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}", 26 | "applicationUrl": "https://localhost:7177;http://localhost:5113", 27 | "environmentVariables": { 28 | "ASPNETCORE_ENVIRONMENT": "Development" 29 | } 30 | }, 31 | "IIS Express": { 32 | "commandName": "IISExpress", 33 | "launchBrowser": true, 34 | "inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}", 35 | "environmentVariables": { 36 | "ASPNETCORE_ENVIRONMENT": "Development" 37 | } 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /BCSSViewer.Wasm/_Imports.razor: -------------------------------------------------------------------------------- 1 | @using System.Net.Http 2 | @using System.Net.Http.Json 3 | @using Microsoft.AspNetCore.Components.Forms 4 | @using Microsoft.AspNetCore.Components.Routing 5 | @using Microsoft.AspNetCore.Components.Web 6 | @using Microsoft.AspNetCore.Components.Web.Virtualization 7 | @using Microsoft.AspNetCore.Components.WebAssembly.Http 8 | @using Microsoft.JSInterop 9 | @using BCSSViewer.Wasm 10 | 11 | @using BCSS 12 | @using MudBlazor 13 | @using MudExtensions 14 | -------------------------------------------------------------------------------- /BCSSViewer.Wasm/wwwroot/cbsmall.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeBeamOrg/BCSS/dd1657245b2114b7baa15054ac630ec51e6fa0b0/BCSSViewer.Wasm/wwwroot/cbsmall.png -------------------------------------------------------------------------------- /BCSSViewer.Wasm/wwwroot/css/app.css: -------------------------------------------------------------------------------- 1 | @import url('open-iconic/font/css/open-iconic-bootstrap.min.css'); 2 | 3 | html, body { 4 | font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; 5 | } 6 | 7 | h1:focus { 8 | outline: none; 9 | } 10 | 11 | a, .btn-link { 12 | color: #0071c1; 13 | } 14 | 15 | .btn-primary { 16 | color: #fff; 17 | background-color: #1b6ec2; 18 | border-color: #1861ac; 19 | } 20 | 21 | .btn:focus, .btn:active:focus, .btn-link.nav-link:focus, .form-control:focus, .form-check-input:focus { 22 | box-shadow: 0 0 0 0.1rem white, 0 0 0 0.25rem #258cfb; 23 | } 24 | 25 | .content { 26 | padding-top: 1.1rem; 27 | } 28 | 29 | .valid.modified:not([type=checkbox]) { 30 | outline: 1px solid #26b050; 31 | } 32 | 33 | .invalid { 34 | outline: 1px solid red; 35 | } 36 | 37 | .validation-message { 38 | color: red; 39 | } 40 | 41 | #blazor-error-ui { 42 | background: lightyellow; 43 | bottom: 0; 44 | box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.2); 45 | display: none; 46 | left: 0; 47 | padding: 0.6rem 1.25rem 0.7rem 1.25rem; 48 | position: fixed; 49 | width: 100%; 50 | z-index: 1000; 51 | } 52 | 53 | #blazor-error-ui .dismiss { 54 | cursor: pointer; 55 | position: absolute; 56 | right: 0.75rem; 57 | top: 0.5rem; 58 | } 59 | 60 | .blazor-error-boundary { 61 | background: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTYiIGhlaWdodD0iNDkiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIG92ZXJmbG93PSJoaWRkZW4iPjxkZWZzPjxjbGlwUGF0aCBpZD0iY2xpcDAiPjxyZWN0IHg9IjIzNSIgeT0iNTEiIHdpZHRoPSI1NiIgaGVpZ2h0PSI0OSIvPjwvY2xpcFBhdGg+PC9kZWZzPjxnIGNsaXAtcGF0aD0idXJsKCNjbGlwMCkiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0yMzUgLTUxKSI+PHBhdGggZD0iTTI2My41MDYgNTFDMjY0LjcxNyA1MSAyNjUuODEzIDUxLjQ4MzcgMjY2LjYwNiA1Mi4yNjU4TDI2Ny4wNTIgNTIuNzk4NyAyNjcuNTM5IDUzLjYyODMgMjkwLjE4NSA5Mi4xODMxIDI5MC41NDUgOTIuNzk1IDI5MC42NTYgOTIuOTk2QzI5MC44NzcgOTMuNTEzIDI5MSA5NC4wODE1IDI5MSA5NC42NzgyIDI5MSA5Ny4wNjUxIDI4OS4wMzggOTkgMjg2LjYxNyA5OUwyNDAuMzgzIDk5QzIzNy45NjMgOTkgMjM2IDk3LjA2NTEgMjM2IDk0LjY3ODIgMjM2IDk0LjM3OTkgMjM2LjAzMSA5NC4wODg2IDIzNi4wODkgOTMuODA3MkwyMzYuMzM4IDkzLjAxNjIgMjM2Ljg1OCA5Mi4xMzE0IDI1OS40NzMgNTMuNjI5NCAyNTkuOTYxIDUyLjc5ODUgMjYwLjQwNyA1Mi4yNjU4QzI2MS4yIDUxLjQ4MzcgMjYyLjI5NiA1MSAyNjMuNTA2IDUxWk0yNjMuNTg2IDY2LjAxODNDMjYwLjczNyA2Ni4wMTgzIDI1OS4zMTMgNjcuMTI0NSAyNTkuMzEzIDY5LjMzNyAyNTkuMzEzIDY5LjYxMDIgMjU5LjMzMiA2OS44NjA4IDI1OS4zNzEgNzAuMDg4N0wyNjEuNzk1IDg0LjAxNjEgMjY1LjM4IDg0LjAxNjEgMjY3LjgyMSA2OS43NDc1QzI2Ny44NiA2OS43MzA5IDI2Ny44NzkgNjkuNTg3NyAyNjcuODc5IDY5LjMxNzkgMjY3Ljg3OSA2Ny4xMTgyIDI2Ni40NDggNjYuMDE4MyAyNjMuNTg2IDY2LjAxODNaTTI2My41NzYgODYuMDU0N0MyNjEuMDQ5IDg2LjA1NDcgMjU5Ljc4NiA4Ny4zMDA1IDI1OS43ODYgODkuNzkyMSAyNTkuNzg2IDkyLjI4MzcgMjYxLjA0OSA5My41Mjk1IDI2My41NzYgOTMuNTI5NSAyNjYuMTE2IDkzLjUyOTUgMjY3LjM4NyA5Mi4yODM3IDI2Ny4zODcgODkuNzkyMSAyNjcuMzg3IDg3LjMwMDUgMjY2LjExNiA4Ni4wNTQ3IDI2My41NzYgODYuMDU0N1oiIGZpbGw9IiNGRkU1MDAiIGZpbGwtcnVsZT0iZXZlbm9kZCIvPjwvZz48L3N2Zz4=) no-repeat 1rem/1.8rem, #b32121; 62 | padding: 1rem 1rem 1rem 3.7rem; 63 | color: white; 64 | } 65 | 66 | .blazor-error-boundary::after { 67 | content: "An error has occurred." 68 | } 69 | 70 | .loading-progress { 71 | position: relative; 72 | display: block; 73 | width: 8rem; 74 | height: 8rem; 75 | margin: 20vh auto 1rem auto; 76 | } 77 | 78 | .loading-progress circle { 79 | fill: none; 80 | stroke: #e0e0e0; 81 | stroke-width: 0.6rem; 82 | transform-origin: 50% 50%; 83 | transform: rotate(-90deg); 84 | } 85 | 86 | .loading-progress circle:last-child { 87 | stroke: #1b6ec2; 88 | stroke-dasharray: calc(3.141 * var(--blazor-load-percentage, 0%) * 0.8), 500%; 89 | transition: stroke-dasharray 0.05s ease-in-out; 90 | } 91 | 92 | .loading-progress-text { 93 | position: absolute; 94 | text-align: center; 95 | font-weight: bold; 96 | inset: calc(20vh + 3.25rem) 0 auto 0.2rem; 97 | } 98 | 99 | .loading-progress-text:after { 100 | content: var(--blazor-load-percentage-text, "Loading"); 101 | } 102 | 103 | .text-move { 104 | overflow: hidden; 105 | white-space: nowrap; 106 | animation: TextWidth 8s ease-in-out infinite; 107 | } 108 | 109 | .text-wrap { 110 | animation: TextWrap 8s linear infinite; 111 | } 112 | 113 | @keyframes TextWidth { 114 | 0% { 115 | width: 30px; 116 | color: var(--mud-palette-primary); 117 | } 118 | 119 | 15% { 120 | width: 30px; 121 | color: var(--mud-palette-primary); 122 | } 123 | 124 | 45% { 125 | width: 156px; 126 | color: var(--mud-palette-text-primary); 127 | } 128 | 129 | 55% { 130 | width: 156px; 131 | color: var(--mud-palette-text-primary); 132 | } 133 | 134 | 75% { 135 | width: 30px; 136 | color: var(--mud-palette-primary); 137 | } 138 | 139 | 100% { 140 | width: 30px; 141 | color: var(--mud-palette-primary); 142 | } 143 | } 144 | 145 | @keyframes TextWrap { 146 | 0% { 147 | letter-spacing: -4px; 148 | color: var(--mud-palette-secondary); 149 | } 150 | 151 | 15% { 152 | letter-spacing: -4px; 153 | color: var(--mud-palette-secondary); 154 | } 155 | 156 | 45% { 157 | letter-spacing: 2px; 158 | color: var(--mud-palette-text-primary); 159 | } 160 | 161 | 55% { 162 | letter-spacing: 2px; 163 | color: var(--mud-palette-text-primary); 164 | } 165 | 166 | 75% { 167 | letter-spacing: -4px; 168 | color: var(--mud-palette-secondary); 169 | } 170 | 171 | 100% { 172 | letter-spacing: -4px; 173 | color: var(--mud-palette-secondary); 174 | } 175 | } 176 | 177 | .rotate-infinite { 178 | animation: rotatefull 1s ease-in-out infinite; 179 | height: 80px !important; 180 | width: 80px !important; 181 | } 182 | 183 | @keyframes rotatefull { 184 | 0% { 185 | transform: rotate(0deg); 186 | } 187 | 188 | 100% { 189 | transform: rotate(360deg); 190 | } 191 | } 192 | 193 | .vibrate-infinite { 194 | animation: vibrate 2s ease-in-out infinite; 195 | color: gold; 196 | height: 60px !important; 197 | width: 60px !important; 198 | } 199 | 200 | @keyframes vibrate { 201 | 0% { 202 | transform: translate(0); 203 | } 204 | 205 | 20% { 206 | transform: translate(-2px, 4px); 207 | } 208 | 209 | 40% { 210 | transform: translate(2px, -4px); 211 | } 212 | 213 | 60% { 214 | transform: translate(-2px, 4px); 215 | } 216 | 217 | 80% { 218 | transform: translate(2px, -4px); 219 | } 220 | 221 | 100% { 222 | transform: translate(0); 223 | } 224 | } 225 | -------------------------------------------------------------------------------- /BCSSViewer.Wasm/wwwroot/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | CodeBeam BCSS 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 |
21 | 22 | 23 | 24 | 25 |
26 |
27 | BCSS 28 |
29 |
30 | 31 | 32 |
33 | An unhandled error has occurred. 34 | Reload 35 | 🗙 36 |
37 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /BCSSViewer/App.razor: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | Not found 8 | 9 |

Sorry, there's nothing at this address.

10 |
11 |
12 |
13 | 14 | 15 | -------------------------------------------------------------------------------- /BCSSViewer/BCSSViewer.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net9.0 5 | enable 6 | enable 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /BCSSViewer/Pages/_Host.cshtml: -------------------------------------------------------------------------------- 1 | @page "/" 2 | @using Microsoft.AspNetCore.Components.Web 3 | @namespace BCSSViewer.Pages 4 | @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers 5 | 6 | 7 | 8 | 9 | CodeBeam BCSS 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | An error has occurred. This application may no longer respond until reloaded. 29 | 30 | 31 | An unhandled exception has occurred. See browser dev tools for details. 32 | 33 | Reload 34 | 🗙 35 |
36 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /BCSSViewer/Program.cs: -------------------------------------------------------------------------------- 1 | using BCSS.Services; 2 | using MudBlazor.Services; 3 | 4 | var builder = WebApplication.CreateBuilder(args); 5 | 6 | // Add services to the container. 7 | builder.Services.AddRazorPages(); 8 | builder.Services.AddServerSideBlazor(); 9 | 10 | builder.Services.AddMudServices(); 11 | builder.Services.AddBcss(); 12 | 13 | var app = builder.Build(); 14 | 15 | // Configure the HTTP request pipeline. 16 | if (!app.Environment.IsDevelopment()) 17 | { 18 | app.UseExceptionHandler("/Error"); 19 | // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. 20 | app.UseHsts(); 21 | } 22 | 23 | app.UseHttpsRedirection(); 24 | 25 | app.UseStaticFiles(); 26 | 27 | app.UseRouting(); 28 | 29 | app.MapBlazorHub(); 30 | app.MapFallbackToPage("/_Host"); 31 | 32 | app.Run(); 33 | -------------------------------------------------------------------------------- /BCSSViewer/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "iisSettings": { 3 | "windowsAuthentication": false, 4 | "anonymousAuthentication": true, 5 | "iisExpress": { 6 | "applicationUrl": "http://localhost:17451", 7 | "sslPort": 44353 8 | } 9 | }, 10 | "profiles": { 11 | "http": { 12 | "commandName": "Project", 13 | "dotnetRunMessages": true, 14 | "launchBrowser": true, 15 | "applicationUrl": "http://localhost:5050", 16 | "environmentVariables": { 17 | "ASPNETCORE_ENVIRONMENT": "Development" 18 | } 19 | }, 20 | "https": { 21 | "commandName": "Project", 22 | "dotnetRunMessages": true, 23 | "launchBrowser": true, 24 | "applicationUrl": "https://localhost:7065;http://localhost:5050", 25 | "environmentVariables": { 26 | "ASPNETCORE_ENVIRONMENT": "Development" 27 | } 28 | }, 29 | "IIS Express": { 30 | "commandName": "IISExpress", 31 | "launchBrowser": true, 32 | "environmentVariables": { 33 | "ASPNETCORE_ENVIRONMENT": "Development" 34 | } 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /BCSSViewer/_Imports.razor: -------------------------------------------------------------------------------- 1 | @using System.Net.Http 2 | @using Microsoft.AspNetCore.Authorization 3 | @using Microsoft.AspNetCore.Components.Authorization 4 | @using Microsoft.AspNetCore.Components.Forms 5 | @using Microsoft.AspNetCore.Components.Routing 6 | @using Microsoft.AspNetCore.Components.Web 7 | @using Microsoft.AspNetCore.Components.Web.Virtualization 8 | @using Microsoft.JSInterop 9 | @using BCSSViewer 10 | 11 | @using MudBlazor 12 | @using BCSS 13 | -------------------------------------------------------------------------------- /BCSSViewer/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "DetailedErrors": true, 3 | "Logging": { 4 | "LogLevel": { 5 | "Default": "Information", 6 | "Microsoft.AspNetCore": "Warning" 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /BCSSViewer/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft.AspNetCore": "Warning" 6 | } 7 | }, 8 | "AllowedHosts": "*" 9 | } 10 | -------------------------------------------------------------------------------- /BCSSViewer/wwwroot/cbsmall.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeBeamOrg/BCSS/dd1657245b2114b7baa15054ac630ec51e6fa0b0/BCSSViewer/wwwroot/cbsmall.png -------------------------------------------------------------------------------- /BCSSViewer/wwwroot/css/site.css: -------------------------------------------------------------------------------- 1 | @import url('open-iconic/font/css/open-iconic-bootstrap.min.css'); 2 | 3 | html, body { 4 | font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; 5 | } 6 | 7 | h1:focus { 8 | outline: none; 9 | } 10 | 11 | a, .btn-link { 12 | color: #0071c1; 13 | } 14 | 15 | .btn-primary { 16 | color: #fff; 17 | background-color: #1b6ec2; 18 | border-color: #1861ac; 19 | } 20 | 21 | .btn:focus, .btn:active:focus, .btn-link.nav-link:focus, .form-control:focus, .form-check-input:focus { 22 | box-shadow: 0 0 0 0.1rem white, 0 0 0 0.25rem #258cfb; 23 | } 24 | 25 | .content { 26 | padding-top: 1.1rem; 27 | } 28 | 29 | .valid.modified:not([type=checkbox]) { 30 | outline: 1px solid #26b050; 31 | } 32 | 33 | .invalid { 34 | outline: 1px solid red; 35 | } 36 | 37 | .validation-message { 38 | color: red; 39 | } 40 | 41 | #blazor-error-ui { 42 | background: lightyellow; 43 | bottom: 0; 44 | box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.2); 45 | display: none; 46 | left: 0; 47 | padding: 0.6rem 1.25rem 0.7rem 1.25rem; 48 | position: fixed; 49 | width: 100%; 50 | z-index: 1000; 51 | } 52 | 53 | #blazor-error-ui .dismiss { 54 | cursor: pointer; 55 | position: absolute; 56 | right: 0.75rem; 57 | top: 0.5rem; 58 | } 59 | 60 | .blazor-error-boundary { 61 | background: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTYiIGhlaWdodD0iNDkiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIG92ZXJmbG93PSJoaWRkZW4iPjxkZWZzPjxjbGlwUGF0aCBpZD0iY2xpcDAiPjxyZWN0IHg9IjIzNSIgeT0iNTEiIHdpZHRoPSI1NiIgaGVpZ2h0PSI0OSIvPjwvY2xpcFBhdGg+PC9kZWZzPjxnIGNsaXAtcGF0aD0idXJsKCNjbGlwMCkiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0yMzUgLTUxKSI+PHBhdGggZD0iTTI2My41MDYgNTFDMjY0LjcxNyA1MSAyNjUuODEzIDUxLjQ4MzcgMjY2LjYwNiA1Mi4yNjU4TDI2Ny4wNTIgNTIuNzk4NyAyNjcuNTM5IDUzLjYyODMgMjkwLjE4NSA5Mi4xODMxIDI5MC41NDUgOTIuNzk1IDI5MC42NTYgOTIuOTk2QzI5MC44NzcgOTMuNTEzIDI5MSA5NC4wODE1IDI5MSA5NC42NzgyIDI5MSA5Ny4wNjUxIDI4OS4wMzggOTkgMjg2LjYxNyA5OUwyNDAuMzgzIDk5QzIzNy45NjMgOTkgMjM2IDk3LjA2NTEgMjM2IDk0LjY3ODIgMjM2IDk0LjM3OTkgMjM2LjAzMSA5NC4wODg2IDIzNi4wODkgOTMuODA3MkwyMzYuMzM4IDkzLjAxNjIgMjM2Ljg1OCA5Mi4xMzE0IDI1OS40NzMgNTMuNjI5NCAyNTkuOTYxIDUyLjc5ODUgMjYwLjQwNyA1Mi4yNjU4QzI2MS4yIDUxLjQ4MzcgMjYyLjI5NiA1MSAyNjMuNTA2IDUxWk0yNjMuNTg2IDY2LjAxODNDMjYwLjczNyA2Ni4wMTgzIDI1OS4zMTMgNjcuMTI0NSAyNTkuMzEzIDY5LjMzNyAyNTkuMzEzIDY5LjYxMDIgMjU5LjMzMiA2OS44NjA4IDI1OS4zNzEgNzAuMDg4N0wyNjEuNzk1IDg0LjAxNjEgMjY1LjM4IDg0LjAxNjEgMjY3LjgyMSA2OS43NDc1QzI2Ny44NiA2OS43MzA5IDI2Ny44NzkgNjkuNTg3NyAyNjcuODc5IDY5LjMxNzkgMjY3Ljg3OSA2Ny4xMTgyIDI2Ni40NDggNjYuMDE4MyAyNjMuNTg2IDY2LjAxODNaTTI2My41NzYgODYuMDU0N0MyNjEuMDQ5IDg2LjA1NDcgMjU5Ljc4NiA4Ny4zMDA1IDI1OS43ODYgODkuNzkyMSAyNTkuNzg2IDkyLjI4MzcgMjYxLjA0OSA5My41Mjk1IDI2My41NzYgOTMuNTI5NSAyNjYuMTE2IDkzLjUyOTUgMjY3LjM4NyA5Mi4yODM3IDI2Ny4zODcgODkuNzkyMSAyNjcuMzg3IDg3LjMwMDUgMjY2LjExNiA4Ni4wNTQ3IDI2My41NzYgODYuMDU0N1oiIGZpbGw9IiNGRkU1MDAiIGZpbGwtcnVsZT0iZXZlbm9kZCIvPjwvZz48L3N2Zz4=) no-repeat 1rem/1.8rem, #b32121; 62 | padding: 1rem 1rem 1rem 3.7rem; 63 | color: white; 64 | } 65 | 66 | .blazor-error-boundary::after { 67 | content: "An error has occurred." 68 | 69 | } 70 | 71 | .tracking-in-expand { 72 | animation: tracking-in-expand 8s cubic-bezier(0.215, 0.610, 0.355, 1.000); 73 | } 74 | 75 | @keyframes tracking-in-expand { 76 | 0% { 77 | letter-spacing: -0.5em; 78 | opacity: 1; 79 | } 80 | 81 | 100% { 82 | letter-spacing: 0; 83 | opacity: 1; 84 | } 85 | } 86 | 87 | .animate-character { 88 | text-transform: uppercase; 89 | background-image: linear-gradient( -225deg, #231557 0%, #44107a 19%, #ff1361 67%, #fff800 100% ); 90 | background-clip: border-box; 91 | background-size: 200% auto; 92 | color: #fff; 93 | background-clip: text; 94 | text-fill-color: transparent; 95 | -webkit-background-clip: text; 96 | -webkit-text-fill-color: transparent; 97 | animation: textclip 8s ease infinite; 98 | } 99 | 100 | @keyframes textclip { 101 | to { 102 | background-position: 200% center; 103 | } 104 | } 105 | 106 | .css-selector { 107 | background-image: linear-gradient(143deg, #313b72, #f45b69, #eef4d4); 108 | background-clip: border-box; 109 | -webkit-background-clip: text; 110 | background-size: 600% 600%; 111 | } 112 | 113 | .text-move { 114 | overflow: hidden; 115 | white-space: nowrap; 116 | animation: TextWidth 8s ease-in-out infinite; 117 | } 118 | 119 | .text-wrap { 120 | animation: TextWrap 8s linear infinite; 121 | } 122 | 123 | @keyframes TextWidth { 124 | 0% { 125 | width: 30px; 126 | color: var(--mud-palette-primary); 127 | } 128 | 129 | 15% { 130 | width: 30px; 131 | color: var(--mud-palette-primary); 132 | } 133 | 134 | 45% { 135 | width: 156px; 136 | color: var(--mud-palette-text-primary); 137 | } 138 | 139 | 55% { 140 | width: 156px; 141 | color: var(--mud-palette-text-primary); 142 | } 143 | 144 | 80% { 145 | width: 30px; 146 | color: var(--mud-palette-primary); 147 | } 148 | 149 | 100% { 150 | width: 30px; 151 | color: var(--mud-palette-primary); 152 | } 153 | } 154 | 155 | @keyframes TextWrap { 156 | 0% { 157 | letter-spacing: -4px; 158 | color: var(--mud-palette-secondary); 159 | } 160 | 161 | 15% { 162 | letter-spacing: -4px; 163 | color: var(--mud-palette-secondary); 164 | } 165 | 166 | 45% { 167 | letter-spacing: 2px; 168 | color: var(--mud-palette-text-primary); 169 | } 170 | 171 | 55% { 172 | letter-spacing: 2px; 173 | color: var(--mud-palette-text-primary); 174 | } 175 | 176 | 80% { 177 | letter-spacing: -4px; 178 | color: var(--mud-palette-secondary); 179 | } 180 | 181 | 100% { 182 | letter-spacing: -4px; 183 | color: var(--mud-palette-secondary); 184 | } 185 | } 186 | 187 | .rotate-infinite { 188 | animation: rotatefull 1s ease-in-out infinite; 189 | height: 80px !important; 190 | width: 80px !important; 191 | } 192 | 193 | @keyframes rotatefull { 194 | 0% { 195 | transform: rotate(0deg); 196 | } 197 | 198 | 100% { 199 | transform: rotate(360deg); 200 | } 201 | } 202 | 203 | .vibrate-infinite { 204 | animation: vibrate 2s ease-in-out infinite; 205 | color: gold; 206 | height: 60px !important; 207 | width: 60px !important; 208 | } 209 | 210 | @keyframes vibrate { 211 | 0% { 212 | transform: translate(0); 213 | } 214 | 215 | 20% { 216 | transform: translate(-2px, 4px); 217 | } 218 | 219 | 40% { 220 | transform: translate(2px, -4px); 221 | } 222 | 223 | 60% { 224 | transform: translate(-2px, 4px); 225 | } 226 | 227 | 80% { 228 | transform: translate(2px, -4px); 229 | } 230 | 231 | 100% { 232 | transform: translate(0); 233 | } 234 | } 235 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) [year] [fullname] 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # BCSS 2 | ### Revolutionary Runtime CSS Generator for Blazor 3 | 4 | [![GitHub Repo stars](https://img.shields.io/github/stars/codebeamorg/bcss?color=594ae2&style=flat-square&logo=github)](https://github.com/codebeamorg/bcss/stargazers) 5 | [![GitHub last commit](https://img.shields.io/github/last-commit/codebeamorg/bcss?color=594ae2&style=flat-square&logo=github)](https://github.com/codebeamorg/bcss) 6 | [![Contributors](https://img.shields.io/github/contributors/codebeamorg/bcss?color=594ae2&style=flat-square&logo=github)](https://github.com/codebeamorg/bcss/graphs/contributors) 7 | [![NuGet version](https://img.shields.io/nuget/v/CodeBeam.bcss?color=ff4081&label=nuget%20version&logo=nuget&style=flat-square)](https://www.nuget.org/packages/CodeBeam.bcss) 8 | [![NuGet downloads](https://img.shields.io/nuget/dt/CodeBeam.bcss?color=ff4081&label=nuget%20downloads&logo=nuget&style=flat-square)](https://www.nuget.org/packages/CodeBeam.bcss) 9 | 10 | | BCSS | .NET | 11 | | :------------- | :-------------: | 12 | | 1.0.0 | .NET 6 - .NET 7 - .NET 8 | 13 | | 1.0.1 | .NET 8 - .NET 9 | 14 | 15 | ## Installation 16 | 1. Install CodeBeam.BCSS Nuget package 17 | ```razor 18 | dotnet add package CodeBeam.BCSS 19 | ``` 20 | 2. Add the following to `_Imports.razor` 21 | ```razor 22 | @using BCSS 23 | ``` 24 | 3. Add the following to your HTML **body** section, it's either `index.html` or `_Layout.cshtml`/`_Host.cshtml` depending on whether you're running Server-Side or WASM. 25 | ```html 26 | 27 | ``` 28 | 4. Add the following to the relevant sections of `Program.cs` 29 | ```c# 30 | using Bcss.Services; 31 | builder.Services.AddBcss(); 32 | ``` 33 | 5. Add the following to`App.razor` 34 | ```razor 35 | 36 | ``` 37 | 6. Inject the service and place the component in the page that you want to use BCSS 38 | ```razor 39 | @inject BcssService Bc 40 | ``` 41 | 42 | ## Usage 43 | Add the BCSS class into a class 44 | ```razor 45 |
46 | //This line adds width: 200px height: 100px and border-radius: 20 47 | ``` 48 | ## Related Links 49 | - [Docs - bcss.codebeam.org](https://bcss.codebeam.org) 50 | - [Playground](https://bcss.codebeam.org#playground) 51 | - [Showcase](https://bcss.codebeam.org#showcase) 52 | - [QuickDebug](https://bcss.codebeam.org/devtools/quickdebug) 53 | - [Benchmark](https://bcss.codebeam.org/devtools/benchmark) 54 | --------------------------------------------------------------------------------