diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 28fef84ce..7a8029e06 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -25,7 +25,7 @@ A clear and concise description of what you expected to happen. If applicable, add screenshots to help explain your problem. **Versions (please complete the following information):** - - .NET Version: [e.g. .NET 6, .NET 7, .NET 8, .NET 9] + - .NET Version: [e.g. .NET 8, .NET 9, .NET 10] - BlazorBootstrap: [e.g. 2.0.0, 2.1.0, 2.2.0] - Blazor WebAssembly / Server: [e.g. WebAssembly, Server] - Blazor Interactive Render Mode: [e.g. Auto, Server, WebAssembly, None] diff --git a/.github/workflows/publish-docs.yml b/.github/workflows/publish-docs.yml index e97220144..3c2792e1e 100644 --- a/.github/workflows/publish-docs.yml +++ b/.github/workflows/publish-docs.yml @@ -1,4 +1,6 @@ name: Publish Documentation +permissions: + contents: write on: # Trigger the workflow on push, # but only for the main branch @@ -36,12 +38,12 @@ jobs: - name: Publish Content if: ${{ inputs.prod_release }} env: - GIT_USER: ${{ secrets.GIT_USER }} - GIT_PASS: ${{ secrets.GIT_USER_TOKEN }} + GIT_USER: x-access-token + GIT_PASS: ${{ secrets.GITHUB_TOKEN }} run: | cd docs - git config --global user.name "${{ secrets.GIT_USER }}" - git config --global user.email "${{ secrets.GIT_USER_EMAIL }}" + git config --global user.name "github-actions[bot]" + git config --global user.email "41898282+github-actions[bot]@users.noreply.github.com" if [ -e package-lock.json ]; then npm ci else diff --git a/.github/workflows/static-web-app.yml b/.github/workflows/static-web-app.yml index e46c71b42..1b176d6f7 100644 --- a/.github/workflows/static-web-app.yml +++ b/.github/workflows/static-web-app.yml @@ -1,4 +1,4 @@ -name: Static WebApp (Blazor WebAssembly) +name: StaticWebApp (Blazor WebAssembly) on: push: @@ -18,36 +18,52 @@ on: jobs: build_and_deploy_job: - if: ${{ inputs.prod_release }} || (github.event_name == 'pull_request' && github.event.action != 'closed') + if: ${{ inputs.prod_release }} || (github.event_name == 'pull_request' && github.event.action != 'closed') runs-on: ubuntu-latest + env: + DOTNET_VERSION: "net10.0" + DOTNET_CLI_TELEMETRY_OPTOUT: 1 + PROJECT: "BlazorBootstrap.Demo.WebAssembly/BlazorBootstrap.Demo.WebAssembly.csproj" + BUILD_CONFIG: "Release" + name: Build and Deploy Job steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 with: submodules: true + lfs: false - - name: Setup .NET Core SDK - uses: actions/setup-dotnet@v1 + # Setup .NET 10.0 + - name: Setup .NET 10.0 + uses: actions/setup-dotnet@v4 with: - dotnet-version: '9.0.x' - - - name: Build And Deploy - id: builddeploy - uses: Azure/static-web-apps-deploy@v1 + dotnet-version: '10.0.x' + + # .NET Restore + - name: .NET Restore + run: dotnet restore ${{ env.PROJECT }} + + # .NET Build + - name: .NET Build + run: dotnet build ${{ env.PROJECT }} -c ${{ env.BUILD_CONFIG }} -f ${{ env.DOTNET_VERSION }} --no-restore + + # .NET Publish + - name: .NET Publish + run: dotnet publish ${{ env.PROJECT }} -c ${{ env.BUILD_CONFIG }} -o output -f ${{ env.DOTNET_VERSION }} --no-build + + # Azure Static Web App Deployment Action + - name: Build And Deploy Blazor WASM App + id: swa + uses: azure/static-web-apps-deploy@v1 with: - dotnet-version: '9.0.x' - azure_static_web_apps_api_token: ${{ secrets.AZURE_STATIC_WEB_APPS_API_TOKEN_GRAY_WAVE_0E4848710 }} - skip_deploy_on_missing_secrets: true - repo_token: ${{ secrets.GITHUB_TOKEN }} # Used for Github integrations (i.e. PR comments) + azure_static_web_apps_api_token: ${{ secrets.AZURE_STATIC_WEB_APPS_API_TOKEN_CALM_PLANT_04DA70210 }} + repo_token: ${{ secrets.GITHUB_TOKEN }} action: "upload" - ###### Repository/Build Configurations - These values can be configured to match your app requirements. ###### - # For more information regarding Static Web App workflow configurations, please visit: https://aka.ms/swaworkflowconfig - app_location: "BlazorBootstrap.Demo.WebAssembly" # App source code path - #api_location: "Api" # Api source code path - optional - #output_location: "build/wwwroot" # Built app content directory - optional - output_location: "wwwroot" # Built app content directory - optional - app_build_command: 'dotnet publish --configuration Release --output build' - ###### End of Repository/Build Configurations ###### + app_location: "output/wwwroot" + api_location: "" + output_location: "output/wwwroot" + skip_api_build: true + skip_app_build: true close_pull_request_job: if: github.event_name == 'pull_request' && github.event.action == 'closed' @@ -56,8 +72,7 @@ jobs: steps: - name: Close Pull Request id: closepullrequest - uses: Azure/static-web-apps-deploy@v1 + uses: azure/static-web-apps-deploy@v1 with: - azure_static_web_apps_api_token: ${{ secrets.AZURE_STATIC_WEB_APPS_API_TOKEN_GRAY_WAVE_0E4848710 }} - skip_deploy_on_missing_secrets: true + azure_static_web_apps_api_token: ${{ secrets.AZURE_STATIC_WEB_APPS_API_TOKEN_CALM_PLANT_04DA70210 }} action: "close" diff --git a/.github/workflows/web-app.yml b/.github/workflows/web-app.yml index e2f0fa20f..56f86be6b 100644 --- a/.github/workflows/web-app.yml +++ b/.github/workflows/web-app.yml @@ -17,22 +17,21 @@ jobs: runs-on: windows-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - - name: Set up .NET 9.0.x - uses: actions/setup-dotnet@v1 + - name: Set up .NET 10.0.x + uses: actions/setup-dotnet@v3 with: - dotnet-version: '9.0.x' - include-prerelease: false + dotnet-version: '10.0.x' - name: Build run: dotnet build ./BlazorBootstrap.Demo.Server/BlazorBootstrap.Demo.Server.csproj --configuration Release - name: Publish - run: dotnet publish ./BlazorBootstrap.Demo.Server/BlazorBootstrap.Demo.Server.csproj -c Release -o ${{env.DOTNET_ROOT}}/myapp + run: dotnet publish ./BlazorBootstrap.Demo.Server/BlazorBootstrap.Demo.Server.csproj -c Release -o "${{env.DOTNET_ROOT}}/myapp" - name: Upload artifact for deployment job - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: .net-app path: ${{env.DOTNET_ROOT}}/myapp @@ -47,7 +46,7 @@ jobs: steps: - name: Download artifact from build job - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: .net-app diff --git a/BlazorBootstrap.Demo.Hosted/Client/App.razor b/BlazorBootstrap.Demo.Hosted/Client/App.razor deleted file mode 100644 index 94953bc3e..000000000 --- a/BlazorBootstrap.Demo.Hosted/Client/App.razor +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - Not found - -

Sorry, there's nothing at this address.

-
-
-
diff --git a/BlazorBootstrap.Demo.Hosted/Client/BlazorBootstrap.Demo.Hosted.Client.csproj b/BlazorBootstrap.Demo.Hosted/Client/BlazorBootstrap.Demo.Hosted.Client.csproj deleted file mode 100644 index 80e41a737..000000000 --- a/BlazorBootstrap.Demo.Hosted/Client/BlazorBootstrap.Demo.Hosted.Client.csproj +++ /dev/null @@ -1,19 +0,0 @@ - - - - net9.0 - enable - enable - - - - - - - - - - - - - diff --git a/BlazorBootstrap.Demo.Hosted/Client/Program.cs b/BlazorBootstrap.Demo.Hosted/Client/Program.cs deleted file mode 100644 index ff2e8ae02..000000000 --- a/BlazorBootstrap.Demo.Hosted/Client/Program.cs +++ /dev/null @@ -1,8 +0,0 @@ -var builder = WebAssemblyHostBuilder.CreateDefault(args); - -builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) }); - -builder.Services.AddBlazorBootstrap(); -builder.Services.AddDemoServices(); - -await builder.Build().RunAsync(); diff --git a/BlazorBootstrap.Demo.Hosted/Client/Properties/launchSettings.json b/BlazorBootstrap.Demo.Hosted/Client/Properties/launchSettings.json deleted file mode 100644 index a11e419ed..000000000 --- a/BlazorBootstrap.Demo.Hosted/Client/Properties/launchSettings.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "iisSettings": { - "windowsAuthentication": false, - "anonymousAuthentication": true, - "iisExpress": { - "applicationUrl": "http://localhost:7232", - "sslPort": 44372 - } - }, - "profiles": { - "BlazorBootstrap.Demos": { - "commandName": "Project", - "dotnetRunMessages": true, - "launchBrowser": true, - "inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}", - "applicationUrl": "https://localhost:7020;http://localhost:5127", - "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development" - } - }, - "IIS Express": { - "commandName": "IISExpress", - "launchBrowser": true, - "inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}", - "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development" - } - } - } -} diff --git a/BlazorBootstrap.Demo.Hosted/Client/Usings.cs b/BlazorBootstrap.Demo.Hosted/Client/Usings.cs deleted file mode 100644 index eeb3a44bd..000000000 --- a/BlazorBootstrap.Demo.Hosted/Client/Usings.cs +++ /dev/null @@ -1,2 +0,0 @@ -global using BlazorBootstrap.Demo.RCL; -global using Microsoft.AspNetCore.Components.WebAssembly.Hosting; diff --git a/BlazorBootstrap.Demo.Hosted/Client/_Imports.razor b/BlazorBootstrap.Demo.Hosted/Client/_Imports.razor deleted file mode 100644 index 2dbf7e3e1..000000000 --- a/BlazorBootstrap.Demo.Hosted/Client/_Imports.razor +++ /dev/null @@ -1,10 +0,0 @@ -@using System.Net.Http -@using System.Net.Http.Json -@using Microsoft.AspNetCore.Components.Forms -@using Microsoft.AspNetCore.Components.Routing -@using Microsoft.AspNetCore.Components.Web -@using Microsoft.AspNetCore.Components.Web.Virtualization -@using Microsoft.AspNetCore.Components.WebAssembly.Http -@using Microsoft.JSInterop -@using BlazorBootstrap; -@using BlazorBootstrap.Demo.Hosted.Client diff --git a/BlazorBootstrap.Demo.Hosted/Client/wwwroot/appsettings.json b/BlazorBootstrap.Demo.Hosted/Client/wwwroot/appsettings.json deleted file mode 100644 index 06039eb6d..000000000 --- a/BlazorBootstrap.Demo.Hosted/Client/wwwroot/appsettings.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "version": "3.2.0", - "release": { - "short_description": "New MainLayout and Theme Switcher components, along with other enhancements!!!" - }, - "urls": { - "docs": "//docs.blazorbootstrap.com/docs/getting-started/blazor-webassembly", - "blog": "//docs.blazorbootstrap.com/blog", - "github": "//github.com/vikramlearning/blazorbootstrap", - "twitter": "//twitter.com/blazorbootstrap", - "linkedin": "//www.linkedin.com/groups/14161025", - "opencollective": "//opencollective.com/blazorbootstrap", - "github_issues": "//github.com/vikramlearning/blazorbootstrap/issues", - "github_discussions": "//github.com/vikramlearning/blazorbootstrap/discussions", - "stackoverflow": "//stackoverflow.com/questions/tagged/blazor-bootstrap" - }, - "dotNetVersion": "9.0.0" -} \ No newline at end of file diff --git a/BlazorBootstrap.Demo.Hosted/Client/wwwroot/images/logo/128X128.png b/BlazorBootstrap.Demo.Hosted/Client/wwwroot/images/logo/128X128.png deleted file mode 100644 index 4cc404fcb..000000000 Binary files a/BlazorBootstrap.Demo.Hosted/Client/wwwroot/images/logo/128X128.png and /dev/null differ diff --git a/BlazorBootstrap.Demo.Hosted/Client/wwwroot/images/logo/150X150.png b/BlazorBootstrap.Demo.Hosted/Client/wwwroot/images/logo/150X150.png deleted file mode 100644 index 007f6e095..000000000 Binary files a/BlazorBootstrap.Demo.Hosted/Client/wwwroot/images/logo/150X150.png and /dev/null differ diff --git a/BlazorBootstrap.Demo.Hosted/Client/wwwroot/images/logo/16X16.png b/BlazorBootstrap.Demo.Hosted/Client/wwwroot/images/logo/16X16.png deleted file mode 100644 index 975865786..000000000 Binary files a/BlazorBootstrap.Demo.Hosted/Client/wwwroot/images/logo/16X16.png and /dev/null differ diff --git a/BlazorBootstrap.Demo.Hosted/Client/wwwroot/images/logo/180X180.png b/BlazorBootstrap.Demo.Hosted/Client/wwwroot/images/logo/180X180.png deleted file mode 100644 index 7a54949c7..000000000 Binary files a/BlazorBootstrap.Demo.Hosted/Client/wwwroot/images/logo/180X180.png and /dev/null differ diff --git a/BlazorBootstrap.Demo.Hosted/Client/wwwroot/images/logo/192X192.png b/BlazorBootstrap.Demo.Hosted/Client/wwwroot/images/logo/192X192.png deleted file mode 100644 index c8c2b2f99..000000000 Binary files a/BlazorBootstrap.Demo.Hosted/Client/wwwroot/images/logo/192X192.png and /dev/null differ diff --git a/BlazorBootstrap.Demo.Hosted/Client/wwwroot/images/logo/24X24.png b/BlazorBootstrap.Demo.Hosted/Client/wwwroot/images/logo/24X24.png deleted file mode 100644 index 05271c5b8..000000000 Binary files a/BlazorBootstrap.Demo.Hosted/Client/wwwroot/images/logo/24X24.png and /dev/null differ diff --git a/BlazorBootstrap.Demo.Hosted/Client/wwwroot/images/logo/256X256.png b/BlazorBootstrap.Demo.Hosted/Client/wwwroot/images/logo/256X256.png deleted file mode 100644 index 53810fd26..000000000 Binary files a/BlazorBootstrap.Demo.Hosted/Client/wwwroot/images/logo/256X256.png and /dev/null differ diff --git a/BlazorBootstrap.Demo.Hosted/Client/wwwroot/images/logo/310X310.png b/BlazorBootstrap.Demo.Hosted/Client/wwwroot/images/logo/310X310.png deleted file mode 100644 index af0f803c1..000000000 Binary files a/BlazorBootstrap.Demo.Hosted/Client/wwwroot/images/logo/310X310.png and /dev/null differ diff --git a/BlazorBootstrap.Demo.Hosted/Client/wwwroot/images/logo/32X32.png b/BlazorBootstrap.Demo.Hosted/Client/wwwroot/images/logo/32X32.png deleted file mode 100644 index 86ecffdc8..000000000 Binary files a/BlazorBootstrap.Demo.Hosted/Client/wwwroot/images/logo/32X32.png and /dev/null differ diff --git a/BlazorBootstrap.Demo.Hosted/Client/wwwroot/images/logo/48X48.png b/BlazorBootstrap.Demo.Hosted/Client/wwwroot/images/logo/48X48.png deleted file mode 100644 index 6b72cc6a6..000000000 Binary files a/BlazorBootstrap.Demo.Hosted/Client/wwwroot/images/logo/48X48.png and /dev/null differ diff --git a/BlazorBootstrap.Demo.Hosted/Client/wwwroot/images/logo/64X64.png b/BlazorBootstrap.Demo.Hosted/Client/wwwroot/images/logo/64X64.png deleted file mode 100644 index 098a0fcb1..000000000 Binary files a/BlazorBootstrap.Demo.Hosted/Client/wwwroot/images/logo/64X64.png and /dev/null differ diff --git a/BlazorBootstrap.Demo.Hosted/Client/wwwroot/images/logo/96X96.png b/BlazorBootstrap.Demo.Hosted/Client/wwwroot/images/logo/96X96.png deleted file mode 100644 index d78b76e8e..000000000 Binary files a/BlazorBootstrap.Demo.Hosted/Client/wwwroot/images/logo/96X96.png and /dev/null differ diff --git a/BlazorBootstrap.Demo.Hosted/Client/wwwroot/images/logo/logo-color.svg b/BlazorBootstrap.Demo.Hosted/Client/wwwroot/images/logo/logo-color.svg deleted file mode 100644 index a229764f3..000000000 --- a/BlazorBootstrap.Demo.Hosted/Client/wwwroot/images/logo/logo-color.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/BlazorBootstrap.Demo.Hosted/Client/wwwroot/images/logo/logo-white.svg b/BlazorBootstrap.Demo.Hosted/Client/wwwroot/images/logo/logo-white.svg deleted file mode 100644 index 629cd3367..000000000 --- a/BlazorBootstrap.Demo.Hosted/Client/wwwroot/images/logo/logo-white.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/BlazorBootstrap.Demo.Hosted/Client/wwwroot/images/logo/logo.svg b/BlazorBootstrap.Demo.Hosted/Client/wwwroot/images/logo/logo.svg deleted file mode 100644 index 86d94bf13..000000000 --- a/BlazorBootstrap.Demo.Hosted/Client/wwwroot/images/logo/logo.svg +++ /dev/null @@ -1,17632 +0,0 @@ - - - - - - - - - - - - - - - - - - B - - diff --git a/BlazorBootstrap.Demo.Hosted/Client/wwwroot/images/placeholder.png b/BlazorBootstrap.Demo.Hosted/Client/wwwroot/images/placeholder.png deleted file mode 100644 index 6928765e1..000000000 Binary files a/BlazorBootstrap.Demo.Hosted/Client/wwwroot/images/placeholder.png and /dev/null differ diff --git a/BlazorBootstrap.Demo.Hosted/Client/wwwroot/sample-data/customer/customer.json b/BlazorBootstrap.Demo.Hosted/Client/wwwroot/sample-data/customer/customer.json deleted file mode 100644 index c7b07bbf2..000000000 --- a/BlazorBootstrap.Demo.Hosted/Client/wwwroot/sample-data/customer/customer.json +++ /dev/null @@ -1 +0,0 @@ -[{"customerId":1,"customerName":"Laith Berger","phone":"(379) 882-1444","email":"auctor.velit@protonmail.com","address":"278-7577 Inceptos Ave","postalZip":"5481","country":"Norway"},{"customerId":2,"customerName":"Ivor Burnett","phone":"(551) 710-5413","email":"donec.non@outlook.com","address":"Ap #206-2313 A, Ave","postalZip":"KF91 6RO","country":"Australia"},{"customerId":3,"customerName":"Yasir Hobbs","phone":"(538) 773-6771","email":"et@outlook.com","address":"P.O. Box 209, 6872 Mollis. Av.","postalZip":"56137","country":"Singapore"},{"customerId":4,"customerName":"Rinah Bowman","phone":"(834) 224-3856","email":"elit@protonmail.ca","address":"Ap #657-4008 Nulla Rd.","postalZip":"99566","country":"Philippines"},{"customerId":5,"customerName":"Montana Avery","phone":"(514) 546-4034","email":"tristique.senectus@hotmail.couk","address":"Ap #915-2989 Venenatis Ave","postalZip":"25425-84215","country":"South Africa"},{"customerId":6,"customerName":"Kevyn Smith","phone":"1-152-749-6373","email":"neque@protonmail.ca","address":"431-4752 Neque St.","postalZip":"3697","country":"India"},{"customerId":7,"customerName":"Maite Faulkner","phone":"(466) 210-3875","email":"malesuada@outlook.couk","address":"P.O. Box 254, 3766 Quisque Street","postalZip":"55263","country":"New Zealand"},{"customerId":8,"customerName":"Anne Meadows","phone":"(527) 848-2270","email":"donec.tempus@icloud.ca","address":"Ap #378-2309 Ornare. Av.","postalZip":"19845","country":"Germany"},{"customerId":9,"customerName":"Kamal Bush","phone":"(937) 745-2871","email":"nec.luctus@protonmail.org","address":"7491 Egestas. Rd.","postalZip":"13-185","country":"Chile"},{"customerId":10,"customerName":"Tasha Gill","phone":"(755) 756-9385","email":"justo.faucibus@hotmail.couk","address":"487-2374 Sed Street","postalZip":"800173","country":"Mexico"},{"customerId":11,"customerName":"Vernon Clark","phone":"(630) 344-8774","email":"velit.cras@protonmail.net","address":"1885 Proin Road","postalZip":"414742","country":"Colombia"},{"customerId":12,"customerName":"Kibo Shelton","phone":"(278) 258-8502","email":"ante.maecenas@yahoo.com","address":"P.O. Box 336, 5076 Fringilla St.","postalZip":"87-381","country":"Turkey"},{"customerId":13,"customerName":"Shelly Vazquez","phone":"(643) 452-4588","email":"lacus.nulla@outlook.ca","address":"602-8739 Mauris St.","postalZip":"56-22","country":"France"},{"customerId":14,"customerName":"Hilary Poole","phone":"(937) 972-7551","email":"suspendisse.sagittis@hotmail.ca","address":"875-9021 Sed Av.","postalZip":"66320","country":"United States"},{"customerId":15,"customerName":"Tarik England","phone":"(554) 498-3672","email":"nec.metus.facilisis@hotmail.com","address":"P.O. Box 316, 3800 Pellentesque Rd.","postalZip":"75-22","country":"Italy"},{"customerId":16,"customerName":"Hamilton Hayden","phone":"1-882-568-0494","email":"class.aptent.taciti@protonmail.couk","address":"567-8292 Sed Road","postalZip":"52861","country":"Poland"},{"customerId":17,"customerName":"Uriel Barton","phone":"(176) 435-5738","email":"dolor.sit.amet@protonmail.net","address":"882-7144 Arcu. Street","postalZip":"5663-2444","country":"Germany"},{"customerId":18,"customerName":"Craig Richmond","phone":"(927) 236-8054","email":"ut.odio@outlook.com","address":"Ap #571-6322 Tortor Ave","postalZip":"39143","country":"Philippines"},{"customerId":19,"customerName":"Brent Robbins","phone":"(492) 936-5527","email":"interdum@aol.ca","address":"Ap #494-482 Egestas St.","postalZip":"36751","country":"Costa Rica"},{"customerId":20,"customerName":"Chaney Short","phone":"1-733-537-5892","email":"sed@outlook.edu","address":"P.O. Box 567, 8641 Fermentum Avenue","postalZip":"243631","country":"Pakistan"},{"customerId":21,"customerName":"Orlando Chapman","phone":"1-798-564-3871","email":"mauris@hotmail.edu","address":"9021 Sem Av.","postalZip":"8706","country":"Vietnam"},{"customerId":22,"customerName":"Holly Long","phone":"(613) 844-0530","email":"non.nisi@icloud.org","address":"411-5020 At St.","postalZip":"3183-2246","country":"Netherlands"},{"customerId":23,"customerName":"Jane Salas","phone":"1-746-223-2024","email":"odio@google.ca","address":"Ap #842-2591 Consectetuer Avenue","postalZip":"73-48","country":"China"},{"customerId":24,"customerName":"Deirdre Simmons","phone":"1-925-245-4398","email":"sed.turpis.nec@protonmail.ca","address":"Ap #214-2638 Mauris, Avenue","postalZip":"377358","country":"Peru"},{"customerId":25,"customerName":"Sigourney Melendez","phone":"1-147-785-7367","email":"odio.nam@icloud.ca","address":"876-3056 Non, St.","postalZip":"9543-3653","country":"Chile"},{"customerId":26,"customerName":"Zachary Merritt","phone":"1-636-602-5539","email":"semper.et@aol.edu","address":"806 Posuere Street","postalZip":"12467","country":"Norway"},{"customerId":27,"customerName":"Derek Glover","phone":"(150) 931-4838","email":"donec.fringilla@google.couk","address":"Ap #365-6386 Neque Avenue","postalZip":"454395","country":"Canada"},{"customerId":28,"customerName":"Alfonso Rasmussen","phone":"(927) 264-8247","email":"lorem.fringilla@aol.net","address":"Ap #229-4362 Eros St.","postalZip":"3171","country":"Netherlands"},{"customerId":29,"customerName":"Nadine Oneal","phone":"(188) 746-1660","email":"a.odio@google.edu","address":"746-5975 Eu, Avenue","postalZip":"1865","country":"Belgium"},{"customerId":30,"customerName":"Naomi Dejesus","phone":"1-265-639-0296","email":"fames@aol.couk","address":"P.O. Box 290, 9020 Pellentesque St.","postalZip":"897421","country":"Canada"},{"customerId":31,"customerName":"Winter Weber","phone":"(538) 648-2568","email":"faucibus.leo.in@protonmail.org","address":"Ap #725-3539 Dolor Street","postalZip":"40507","country":"Ireland"},{"customerId":32,"customerName":"Jennifer Hurst","phone":"(531) 733-3049","email":"urna.nunc@outlook.couk","address":"P.O. Box 174, 9406 Ante St.","postalZip":"14153","country":"Nigeria"},{"customerId":33,"customerName":"Kevin Guy","phone":"(283) 229-1753","email":"mauris@yahoo.ca","address":"P.O. Box 436, 3613 Ligula. Rd.","postalZip":"523981","country":"Norway"},{"customerId":34,"customerName":"Hakeem Henson","phone":"1-264-857-8861","email":"mus@outlook.com","address":"907-8892 Montes, Rd.","postalZip":"46-846","country":"United Kingdom"},{"customerId":35,"customerName":"Avram Hardin","phone":"1-764-303-7127","email":"vel.pede.blandit@protonmail.org","address":"Ap #328-2448 Velit. Rd.","postalZip":"728900","country":"Germany"},{"customerId":36,"customerName":"Kiayada Bray","phone":"(935) 824-3485","email":"lectus.rutrum@hotmail.edu","address":"580-9599 Mattis St.","postalZip":"4055","country":"Philippines"},{"customerId":37,"customerName":"Elizabeth Cardenas","phone":"1-633-852-7760","email":"hendrerit.id.ante@hotmail.org","address":"Ap #628-1875 Egestas. Rd.","postalZip":"18990","country":"Pakistan"},{"customerId":38,"customerName":"Kimberley Durham","phone":"(746) 731-5318","email":"et@hotmail.org","address":"P.O. Box 469, 7337 Neque Street","postalZip":"4187","country":"Brazil"},{"customerId":39,"customerName":"Arthur Clarke","phone":"(287) 129-2460","email":"egestas@google.org","address":"8458 Vivamus Rd.","postalZip":"1827 JX","country":"Russian Federation"},{"customerId":40,"customerName":"Giacomo Newton","phone":"1-182-675-4805","email":"non.enim.commodo@google.com","address":"Ap #341-8380 Ut Rd.","postalZip":"41715","country":"Vietnam"},{"customerId":41,"customerName":"Amelia Alexander","phone":"1-718-582-4253","email":"non.vestibulum.nec@outlook.ca","address":"413-9679 Cum Avenue","postalZip":"26744","country":"Spain"},{"customerId":42,"customerName":"Stacy Davenport","phone":"1-819-211-8276","email":"risus.donec.egestas@yahoo.org","address":"P.O. Box 415, 2772 Vitae, St.","postalZip":"597735","country":"Germany"},{"customerId":43,"customerName":"Rosalyn Patrick","phone":"1-995-906-7898","email":"vitae@google.com","address":"P.O. Box 693, 5762 Porttitor Rd.","postalZip":"9759 WE","country":"Ukraine"},{"customerId":44,"customerName":"Logan Buckner","phone":"(516) 386-2835","email":"donec.nibh@google.com","address":"Ap #275-1807 Dictum Ave","postalZip":"40233","country":"Canada"},{"customerId":45,"customerName":"Stewart Johnston","phone":"1-967-407-4365","email":"pharetra.felis.eget@hotmail.org","address":"Ap #710-3875 Lectus, St.","postalZip":"55065","country":"Nigeria"},{"customerId":46,"customerName":"Colton Myers","phone":"1-100-736-7463","email":"nam.ligula@aol.com","address":"443-1273 Natoque Rd.","postalZip":"14672","country":"Peru"},{"customerId":47,"customerName":"Sylvester Phillips","phone":"(297) 713-3040","email":"lorem.vehicula@hotmail.org","address":"P.O. Box 642, 9852 Nulla. St.","postalZip":"7660","country":"Nigeria"},{"customerId":48,"customerName":"Deacon Barnes","phone":"(571) 242-4528","email":"gravida.mauris@yahoo.org","address":"334-9465 Amet, Av.","postalZip":"382115","country":"Pakistan"},{"customerId":49,"customerName":"Drew Terrell","phone":"1-715-909-4824","email":"et@icloud.com","address":"Ap #616-7205 Turpis St.","postalZip":"10087","country":"Norway"},{"customerId":50,"customerName":"Britanni Bennett","phone":"1-220-669-3332","email":"turpis@icloud.org","address":"4222 Lobortis Street","postalZip":"6523","country":"Singapore"},{"customerId":51,"customerName":"Desirae Houston","phone":"(726) 847-0251","email":"iaculis@outlook.couk","address":"P.O. Box 950, 421 Ipsum Road","postalZip":"654802","country":"Canada"},{"customerId":52,"customerName":"Jordan Knight","phone":"1-674-723-2927","email":"dolor.elit@protonmail.edu","address":"P.O. Box 604, 3917 Commodo Rd.","postalZip":"33-746","country":"Sweden"},{"customerId":53,"customerName":"Lucy Newman","phone":"1-795-382-9988","email":"mollis.lectus.pede@protonmail.edu","address":"Ap #457-3018 Non Road","postalZip":"151381","country":"China"},{"customerId":54,"customerName":"Kylan Church","phone":"1-593-716-9158","email":"dictum.eu@protonmail.net","address":"Ap #519-178 Ut Street","postalZip":"83-26","country":"Nigeria"},{"customerId":55,"customerName":"Nevada Howard","phone":"(324) 886-7525","email":"litora@icloud.ca","address":"P.O. Box 215, 2750 Pellentesque St.","postalZip":"12444","country":"Colombia"},{"customerId":56,"customerName":"Kirby Wilder","phone":"1-552-868-5375","email":"ullamcorper.nisl@icloud.org","address":"3404 Iaculis Road","postalZip":"695822","country":"Brazil"},{"customerId":57,"customerName":"Risa Hendrix","phone":"(877) 579-6357","email":"faucibus.lectus@hotmail.org","address":"330-3283 Magnis Rd.","postalZip":"7527 JE","country":"Vietnam"},{"customerId":58,"customerName":"Hu Wong","phone":"1-461-816-4756","email":"per@icloud.org","address":"681-2058 Feugiat. Rd.","postalZip":"51362","country":"Netherlands"},{"customerId":59,"customerName":"Sonya Hughes","phone":"(858) 658-3635","email":"faucibus.lectus.a@hotmail.net","address":"P.O. Box 553, 3124 Aliquam St.","postalZip":"27829","country":"Vietnam"},{"customerId":60,"customerName":"Craig Logan","phone":"(906) 473-4868","email":"tristique@google.ca","address":"P.O. Box 942, 610 Est, Av.","postalZip":"3547","country":"Netherlands"},{"customerId":61,"customerName":"Raja Dorsey","phone":"1-829-181-5111","email":"varius.orci.in@google.org","address":"P.O. Box 566, 8429 Enim. Rd.","postalZip":"4450 HZ","country":"Ireland"},{"customerId":62,"customerName":"Asher Morin","phone":"(221) 262-6862","email":"mauris@google.org","address":"P.O. Box 671, 2035 Vulputate, Rd.","postalZip":"8552","country":"Mexico"},{"customerId":63,"customerName":"Bruce Ferrell","phone":"(820) 342-4472","email":"eu.euismod.ac@protonmail.edu","address":"Ap #767-7889 Sed Av.","postalZip":"11532","country":"Chile"},{"customerId":64,"customerName":"Erasmus Adkins","phone":"(928) 341-5433","email":"enim.nisl@outlook.edu","address":"P.O. Box 951, 5448 Pharetra Avenue","postalZip":"173364","country":"South Africa"},{"customerId":65,"customerName":"TaShya Huber","phone":"(997) 425-5262","email":"erat.vitae@icloud.com","address":"517 Non St.","postalZip":"38416-44863","country":"Indonesia"},{"customerId":66,"customerName":"Tate Blackburn","phone":"1-524-604-6431","email":"dui.suspendisse.ac@protonmail.edu","address":"Ap #570-9373 Sed Street","postalZip":"3377","country":"China"},{"customerId":67,"customerName":"Neve Stewart","phone":"(886) 554-7149","email":"non@yahoo.couk","address":"887 Nullam Road","postalZip":"16823","country":"Sweden"},{"customerId":68,"customerName":"Emerald Workman","phone":"1-358-673-5524","email":"mauris.erat.eget@protonmail.ca","address":"691-5554 Odio Road","postalZip":"47582","country":"Nigeria"},{"customerId":69,"customerName":"Lisandra Roman","phone":"(726) 475-0331","email":"proin@aol.edu","address":"Ap #505-3613 Mauris Rd.","postalZip":"35506","country":"Australia"},{"customerId":70,"customerName":"Dalton Duran","phone":"(478) 837-6585","email":"aenean.euismod@yahoo.edu","address":"4588 Molestie Ave","postalZip":"1653","country":"Vietnam"},{"customerId":71,"customerName":"Victor Mckee","phone":"1-660-287-2856","email":"nam.ligula.elit@protonmail.edu","address":"Ap #536-3369 Non Rd.","postalZip":"62360","country":"Canada"},{"customerId":72,"customerName":"Salvador Robles","phone":"1-935-528-6827","email":"nulla.interdum.curabitur@aol.com","address":"672-4225 Malesuada St.","postalZip":"21618","country":"France"},{"customerId":73,"customerName":"Jerry Gallegos","phone":"(418) 584-9666","email":"et@protonmail.edu","address":"583-642 Lobortis Av.","postalZip":"261152","country":"Brazil"},{"customerId":74,"customerName":"Holmes Elliott","phone":"(829) 533-8718","email":"tellus.suspendisse@outlook.com","address":"P.O. Box 625, 133 Sed Ave","postalZip":"56286","country":"Singapore"},{"customerId":75,"customerName":"Summer O'donnell","phone":"1-775-462-1128","email":"orci@yahoo.ca","address":"P.O. Box 292, 723 Fringilla Avenue","postalZip":"383881","country":"Brazil"},{"customerId":76,"customerName":"Whoopi Ashley","phone":"(444) 234-8486","email":"placerat@yahoo.com","address":"370-7703 Nullam Rd.","postalZip":"7255","country":"South Korea"},{"customerId":77,"customerName":"Brenden Rojas","phone":"(551) 747-6714","email":"euismod.urna@outlook.couk","address":"725-3109 Vel, Av.","postalZip":"33768","country":"Sweden"},{"customerId":78,"customerName":"Cody Valencia","phone":"1-765-411-6783","email":"donec.est@yahoo.net","address":"482-2216 Nunc Rd.","postalZip":"5767","country":"Brazil"},{"customerId":79,"customerName":"Evelyn Young","phone":"(261) 753-5708","email":"non@protonmail.org","address":"108-7247 Non, Av.","postalZip":"2241","country":"Peru"},{"customerId":80,"customerName":"Madeline Gay","phone":"1-777-735-1512","email":"sit.amet@google.com","address":"250-9455 Et Av.","postalZip":"26-969","country":"Sweden"},{"customerId":81,"customerName":"Chloe Buchanan","phone":"1-741-492-5197","email":"lorem@icloud.com","address":"560-7818 Phasellus Street","postalZip":"348619","country":"Brazil"},{"customerId":82,"customerName":"Deirdre Sanchez","phone":"(255) 431-3593","email":"lectus@outlook.ca","address":"167-7082 Pharetra Rd.","postalZip":"84825","country":"France"},{"customerId":83,"customerName":"Patience Ayala","phone":"1-175-835-6043","email":"eu@hotmail.edu","address":"Ap #939-8609 Ullamcorper, Avenue","postalZip":"424592","country":"Netherlands"},{"customerId":84,"customerName":"Raphael Meyers","phone":"1-618-652-5132","email":"diam.luctus@hotmail.edu","address":"897-234 Integer Road","postalZip":"323418","country":"Philippines"},{"customerId":85,"customerName":"Grady Mcconnell","phone":"(415) 838-4695","email":"elementum.at@hotmail.ca","address":"Ap #573-1091 Lobortis Road","postalZip":"9136-2302","country":"India"},{"customerId":86,"customerName":"Forrest Gallagher","phone":"(889) 734-2185","email":"aliquam.adipiscing@hotmail.ca","address":"699-4186 Sed Avenue","postalZip":"2529","country":"Turkey"},{"customerId":87,"customerName":"Vincent Christensen","phone":"(657) 527-7613","email":"sed@protonmail.net","address":"6745 Cursus Avenue","postalZip":"28371","country":"New Zealand"},{"customerId":88,"customerName":"Knox Christensen","phone":"1-644-505-3615","email":"parturient.montes@google.edu","address":"Ap #137-6596 Magna Avenue","postalZip":"30746","country":"Philippines"},{"customerId":89,"customerName":"Bruno Rose","phone":"1-386-544-9221","email":"diam.luctus.lobortis@icloud.ca","address":"Ap #834-6610 Nullam St.","postalZip":"88306-862","country":"Mexico"},{"customerId":90,"customerName":"Ainsley Cardenas","phone":"1-403-423-2787","email":"fringilla.est@outlook.com","address":"Ap #881-2935 Ac Street","postalZip":"66813","country":"Austria"},{"customerId":91,"customerName":"Eve Haley","phone":"(598) 779-1786","email":"etiam.bibendum@google.ca","address":"272-4961 Accumsan Rd.","postalZip":"26918","country":"Norway"},{"customerId":92,"customerName":"Holly Suarez","phone":"1-134-603-2874","email":"curabitur.sed@protonmail.ca","address":"4423 Magnis Street","postalZip":"977634","country":"United States"},{"customerId":93,"customerName":"Kylynn Sanchez","phone":"1-408-582-5546","email":"tincidunt@yahoo.ca","address":"6963 Vel Ave","postalZip":"3581","country":"Netherlands"},{"customerId":94,"customerName":"Unity Joyner","phone":"1-272-884-1422","email":"rhoncus.proin@protonmail.edu","address":"Ap #124-5421 Rhoncus Rd.","postalZip":"23-55","country":"South Africa"},{"customerId":95,"customerName":"Uma Bates","phone":"1-483-533-3821","email":"lorem.ipsum@outlook.ca","address":"Ap #442-8734 Nam St.","postalZip":"1175","country":"Austria"},{"customerId":96,"customerName":"Laura Barrera","phone":"(471) 953-1134","email":"vehicula.aliquet@protonmail.edu","address":"103-2810 Quis, Rd.","postalZip":"611481","country":"Colombia"},{"customerId":97,"customerName":"Maya Floyd","phone":"1-225-552-3173","email":"enim.commodo@outlook.com","address":"P.O. Box 323, 419 Sodales Avenue","postalZip":"78575","country":"Mexico"},{"customerId":98,"customerName":"Keane Bates","phone":"1-763-432-1755","email":"dolor@icloud.org","address":"7976 Lobortis St.","postalZip":"415765","country":"Pakistan"},{"customerId":99,"customerName":"Daniel Oneil","phone":"1-898-887-1438","email":"rutrum@google.org","address":"4147 Blandit. St.","postalZip":"862013","country":"Ireland"},{"customerId":100,"customerName":"Whoopi Kirby","phone":"1-227-963-8934","email":"non.sapien@protonmail.couk","address":"Ap #616-9146 Vitae Street","postalZip":"S2N 3G4","country":"Philippines"},{"customerId":101,"customerName":"Chancellor Schmidt","phone":"1-257-278-1512","email":"elementum.dui@google.ca","address":"709-4368 Eget Avenue","postalZip":"84192","country":"Singapore"},{"customerId":102,"customerName":"Jeanette Mcclain","phone":"(594) 232-4539","email":"interdum.curabitur.dictum@protonmail.couk","address":"1491 Suscipit Rd.","postalZip":"98169","country":"China"},{"customerId":103,"customerName":"Cassady House","phone":"(587) 515-2289","email":"mauris.molestie@protonmail.org","address":"379-2361 Orci. Rd.","postalZip":"58451-626","country":"Germany"},{"customerId":104,"customerName":"Paloma Marks","phone":"1-845-404-6778","email":"donec.non@google.com","address":"3701 Tincidunt, Av.","postalZip":"27812-705","country":"Austria"},{"customerId":105,"customerName":"Mona Ramos","phone":"(626) 558-5848","email":"facilisis.non@hotmail.edu","address":"4240 Et, Avenue","postalZip":"4208","country":"Italy"},{"customerId":106,"customerName":"Charissa Mccray","phone":"(304) 568-2336","email":"in.lobortis.tellus@icloud.couk","address":"Ap #857-2334 Consequat Ave","postalZip":"6545","country":"Colombia"},{"customerId":107,"customerName":"Xander Manning","phone":"1-366-929-4289","email":"libero.mauris@yahoo.net","address":"Ap #856-8433 Sed St.","postalZip":"0843","country":"Vietnam"},{"customerId":108,"customerName":"Alisa Hensley","phone":"(887) 788-9532","email":"cum.sociis@google.net","address":"Ap #214-2529 Tellus Street","postalZip":"71577","country":"United Kingdom"},{"customerId":109,"customerName":"Sean Cantu","phone":"1-341-487-4494","email":"pellentesque@aol.couk","address":"4230 Ipsum Av.","postalZip":"243618","country":"Ireland"},{"customerId":110,"customerName":"Anastasia Park","phone":"1-330-813-7504","email":"hendrerit.consectetuer@outlook.couk","address":"966-6254 At Rd.","postalZip":"31141","country":"Brazil"},{"customerId":111,"customerName":"Penelope Chan","phone":"(298) 403-8351","email":"mauris@hotmail.couk","address":"644-6055 Cubilia Ave","postalZip":"36-698","country":"Sweden"},{"customerId":112,"customerName":"Dane Gould","phone":"(763) 516-0833","email":"a@aol.net","address":"9900 Vitae St.","postalZip":"5074","country":"Chile"},{"customerId":113,"customerName":"Rigel Morrow","phone":"1-486-135-8227","email":"phasellus.elit@outlook.couk","address":"Ap #513-1698 Nam Road","postalZip":"9888 CG","country":"Germany"},{"customerId":114,"customerName":"Rachel Walter","phone":"(168) 802-6672","email":"eleifend.vitae@protonmail.couk","address":"P.O. Box 252, 5440 Dictum Av.","postalZip":"475378","country":"Vietnam"},{"customerId":115,"customerName":"Dieter Bryant","phone":"1-600-315-4688","email":"donec.at@hotmail.edu","address":"P.O. Box 235, 6138 Augue Avenue","postalZip":"10799","country":"Ukraine"},{"customerId":116,"customerName":"Trevor Cook","phone":"(934) 210-2974","email":"nullam.feugiat.placerat@yahoo.net","address":"346-1650 Est Ave","postalZip":"8721 FE","country":"Italy"},{"customerId":117,"customerName":"Amanda Richards","phone":"(649) 729-2153","email":"nec.tellus.nunc@google.com","address":"493 Elit Rd.","postalZip":"14169","country":"China"},{"customerId":118,"customerName":"Francis Hunt","phone":"(828) 818-6888","email":"non.sollicitudin.a@aol.org","address":"7808 Ut St.","postalZip":"38-27","country":"New Zealand"},{"customerId":119,"customerName":"Catherine Hahn","phone":"(295) 899-8645","email":"hendrerit.consectetuer@hotmail.edu","address":"601-7752 Maecenas Street","postalZip":"23649","country":"Canada"},{"customerId":120,"customerName":"Victoria O'brien","phone":"1-137-599-3115","email":"enim.mi@google.couk","address":"P.O. Box 853, 3183 Nulla. Av.","postalZip":"20262","country":"Germany"},{"customerId":121,"customerName":"Dale Mcgowan","phone":"(725) 237-5823","email":"interdum.curabitur.dictum@google.com","address":"547-7664 Orci. Rd.","postalZip":"8109","country":"Costa Rica"},{"customerId":122,"customerName":"Quail Bolton","phone":"(832) 674-8829","email":"tristique@outlook.net","address":"Ap #924-9195 Scelerisque Rd.","postalZip":"161618","country":"South Korea"},{"customerId":123,"customerName":"Colleen Buchanan","phone":"(489) 652-9221","email":"gravida.non.sollicitudin@outlook.com","address":"Ap #585-4765 Curabitur Rd.","postalZip":"9155","country":"New Zealand"},{"customerId":124,"customerName":"Jordan Hull","phone":"1-486-233-4722","email":"velit@yahoo.org","address":"3842 Ut St.","postalZip":"17373","country":"India"},{"customerId":125,"customerName":"Quintessa Sampson","phone":"(847) 389-1866","email":"risus.duis.a@google.com","address":"334-4544 Et Rd.","postalZip":"33-62","country":"Norway"},{"customerId":126,"customerName":"Karly Craft","phone":"1-524-364-4215","email":"tellus.justo@hotmail.org","address":"354-9670 Urna Street","postalZip":"787883","country":"New Zealand"},{"customerId":127,"customerName":"Barrett Dean","phone":"1-380-362-3015","email":"semper.rutrum@google.com","address":"842-4346 Quis Avenue","postalZip":"2289","country":"South Korea"},{"customerId":128,"customerName":"India Whitaker","phone":"(522) 788-6541","email":"sed@yahoo.com","address":"P.O. Box 108, 3306 Non Rd.","postalZip":"02488","country":"Netherlands"},{"customerId":129,"customerName":"Thomas Richard","phone":"1-824-641-6273","email":"neque@outlook.ca","address":"316-1643 Nulla Avenue","postalZip":"61874-416","country":"Indonesia"},{"customerId":130,"customerName":"Jasmine Crane","phone":"1-891-646-0226","email":"diam.proin@protonmail.net","address":"Ap #377-2730 Arcu. St.","postalZip":"39781-73286","country":"Norway"},{"customerId":131,"customerName":"Wallace Doyle","phone":"(254) 654-2761","email":"ultrices@aol.edu","address":"Ap #457-8572 Integer Road","postalZip":"7765-3087","country":"Ireland"},{"customerId":132,"customerName":"Alec Pierce","phone":"(197) 667-1536","email":"pede.praesent@protonmail.com","address":"Ap #727-3783 Donec St.","postalZip":"16697","country":"Norway"},{"customerId":133,"customerName":"Colleen Mercado","phone":"1-794-170-8235","email":"sed.orci@google.ca","address":"Ap #551-4511 Ut, St.","postalZip":"5506","country":"India"},{"customerId":134,"customerName":"Idola Dotson","phone":"(312) 785-6651","email":"arcu@aol.couk","address":"Ap #228-5653 Purus. Avenue","postalZip":"8901 HD","country":"South Africa"},{"customerId":135,"customerName":"Leah Wilkinson","phone":"1-339-577-0861","email":"diam.dictum@yahoo.com","address":"5480 Risus. Street","postalZip":"14901","country":"Norway"},{"customerId":136,"customerName":"Amal Evans","phone":"1-167-757-4737","email":"amet.orci@google.edu","address":"Ap #544-6344 Metus. Road","postalZip":"9286","country":"Poland"},{"customerId":137,"customerName":"Hollee Strickland","phone":"(279) 204-7726","email":"odio@aol.ca","address":"3157 Varius Street","postalZip":"85572-75813","country":"Australia"},{"customerId":138,"customerName":"Adrian Walter","phone":"1-663-544-8567","email":"nec.mollis@outlook.couk","address":"7658 Est Rd.","postalZip":"489734","country":"Belgium"},{"customerId":139,"customerName":"Alisa Ayala","phone":"(370) 634-7253","email":"semper.tellus@yahoo.ca","address":"6653 Dictum Ave","postalZip":"6156","country":"Nigeria"},{"customerId":140,"customerName":"Petra Orr","phone":"1-118-977-8874","email":"et.rutrum@google.com","address":"198-117 Interdum. Av.","postalZip":"75848","country":"Singapore"},{"customerId":141,"customerName":"Remedios Wade","phone":"1-453-153-7725","email":"velit.eget.laoreet@hotmail.edu","address":"398-2243 Risus. Street","postalZip":"3145","country":"Philippines"},{"customerId":142,"customerName":"Daria Fisher","phone":"1-922-693-0450","email":"mauris.ipsum.porta@outlook.net","address":"P.O. Box 517, 9472 Id Street","postalZip":"5760-3343","country":"Poland"},{"customerId":143,"customerName":"Wang Shaffer","phone":"(488) 297-7564","email":"nibh.sit@icloud.edu","address":"248-3849 Nulla Rd.","postalZip":"45566","country":"India"},{"customerId":144,"customerName":"Nichole William","phone":"(341) 312-6916","email":"erat.sed@protonmail.com","address":"1929 Est Avenue","postalZip":"63715","country":"France"},{"customerId":145,"customerName":"Lee Patterson","phone":"1-874-858-8879","email":"nulla.integer@icloud.com","address":"Ap #890-550 Ad St.","postalZip":"4895","country":"China"},{"customerId":146,"customerName":"Phelan Peterson","phone":"(670) 464-0740","email":"vivamus.euismod@icloud.edu","address":"8281 Ac Ave","postalZip":"166723","country":"Indonesia"},{"customerId":147,"customerName":"Willa Bradshaw","phone":"(867) 712-4721","email":"cursus@yahoo.com","address":"Ap #582-6883 Mauris Street","postalZip":"671047","country":"South Korea"},{"customerId":148,"customerName":"Mohammad Spencer","phone":"(288) 753-0218","email":"amet.consectetuer.adipiscing@google.edu","address":"Ap #677-7632 Ac Av.","postalZip":"94-68","country":"South Africa"},{"customerId":149,"customerName":"Jemima Ramsey","phone":"(661) 120-0528","email":"mi.tempor@outlook.com","address":"7627 Risus. Rd.","postalZip":"573033","country":"Peru"},{"customerId":150,"customerName":"Branden Flynn","phone":"1-280-949-5552","email":"ornare.lectus.ante@icloud.net","address":"P.O. Box 546, 6023 Hendrerit Avenue","postalZip":"461852","country":"Netherlands"},{"customerId":151,"customerName":"Hamish Horton","phone":"1-120-249-8810","email":"nullam@protonmail.com","address":"Ap #703-3807 Cras Rd.","postalZip":"3109 QK","country":"Vietnam"},{"customerId":152,"customerName":"Nissim Bolton","phone":"(317) 269-3680","email":"iaculis.enim.sit@icloud.net","address":"677-2899 Semper Rd.","postalZip":"968232","country":"Turkey"},{"customerId":153,"customerName":"Graiden Moon","phone":"(709) 852-2733","email":"erat.vitae@outlook.com","address":"890-441 Ultrices. Street","postalZip":"51808","country":"Poland"},{"customerId":154,"customerName":"Ferris Lancaster","phone":"(996) 822-7520","email":"lacinia.sed.congue@protonmail.edu","address":"Ap #688-7311 Sem Av.","postalZip":"0238","country":"Ireland"},{"customerId":155,"customerName":"Clio Mccarthy","phone":"(164) 332-8316","email":"dictum@google.net","address":"948-6813 Arcu. St.","postalZip":"6864","country":"United States"},{"customerId":156,"customerName":"Kaseem Greene","phone":"(935) 829-2472","email":"magna.a@google.edu","address":"Ap #799-4143 Id Rd.","postalZip":"5655","country":"Costa Rica"},{"customerId":157,"customerName":"Sybill Pitts","phone":"1-947-253-5977","email":"molestie.dapibus@protonmail.ca","address":"568-480 Nibh St.","postalZip":"31145","country":"Sweden"},{"customerId":158,"customerName":"Conan Meyer","phone":"1-493-424-1552","email":"arcu.vestibulum@outlook.edu","address":"Ap #442-2569 Tincidunt Rd.","postalZip":"A9S 7B4","country":"Costa Rica"},{"customerId":159,"customerName":"Lev Small","phone":"(450) 596-7551","email":"sem.magna@yahoo.org","address":"P.O. Box 388, 2942 Elit, Rd.","postalZip":"214938","country":"Poland"},{"customerId":160,"customerName":"Nayda Rowe","phone":"(656) 765-3487","email":"vulputate.posuere@protonmail.org","address":"Ap #299-7971 Maecenas Street","postalZip":"433098","country":"Vietnam"},{"customerId":161,"customerName":"Brenden Taylor","phone":"1-681-577-3266","email":"phasellus.dolor.elit@protonmail.net","address":"P.O. Box 370, 9840 Ante. Ave","postalZip":"64289-11548","country":"Austria"},{"customerId":162,"customerName":"Timothy Sutton","phone":"(444) 218-4545","email":"nulla.at@aol.net","address":"485-1176 Eget Avenue","postalZip":"10709","country":"Germany"},{"customerId":163,"customerName":"Zephania Banks","phone":"1-544-569-2574","email":"magnis@outlook.org","address":"7028 Risus. Avenue","postalZip":"21-851","country":"Nigeria"},{"customerId":164,"customerName":"Reagan O'brien","phone":"(231) 373-3319","email":"phasellus.dapibus@hotmail.net","address":"Ap #169-271 Facilisis St.","postalZip":"8753-2182","country":"Belgium"},{"customerId":165,"customerName":"Bradley Bartlett","phone":"1-388-513-4174","email":"erat.semper@yahoo.edu","address":"Ap #918-9331 Ultrices. Av.","postalZip":"85220","country":"Norway"},{"customerId":166,"customerName":"Lani Jackson","phone":"(877) 547-9285","email":"malesuada.fringilla@yahoo.org","address":"6411 Mus. Av.","postalZip":"3467-3394","country":"Turkey"},{"customerId":167,"customerName":"Igor Gay","phone":"1-314-412-6528","email":"enim.commodo.hendrerit@protonmail.com","address":"Ap #708-7859 Donec Road","postalZip":"65384","country":"Norway"},{"customerId":168,"customerName":"Gay Howell","phone":"(545) 978-4368","email":"et.magnis@yahoo.net","address":"Ap #120-418 Nunc, St.","postalZip":"3234","country":"Indonesia"},{"customerId":169,"customerName":"Maisie Mcclain","phone":"(457) 122-1351","email":"libero.mauris@protonmail.net","address":"Ap #415-705 Non, Rd.","postalZip":"11303","country":"Russian Federation"},{"customerId":170,"customerName":"Sylvia Hayes","phone":"1-200-348-8041","email":"pellentesque.habitant@icloud.edu","address":"Ap #553-9909 Aptent Road","postalZip":"813866","country":"Colombia"},{"customerId":171,"customerName":"Constance Hernandez","phone":"1-214-776-7702","email":"pede.ac@icloud.org","address":"Ap #847-9411 Eget Street","postalZip":"81376-48226","country":"Brazil"},{"customerId":172,"customerName":"Xenos Acosta","phone":"(245) 831-2348","email":"nec.euismod.in@yahoo.net","address":"637-7178 Vitae Ave","postalZip":"170998","country":"Netherlands"},{"customerId":173,"customerName":"Leandra Navarro","phone":"1-417-731-8039","email":"praesent@protonmail.couk","address":"7250 Dictum St.","postalZip":"14152","country":"United States"},{"customerId":174,"customerName":"Yolanda Frye","phone":"1-747-856-8765","email":"aenean@icloud.net","address":"773-9543 Ac St.","postalZip":"3762","country":"Netherlands"},{"customerId":175,"customerName":"Melyssa Moran","phone":"(851) 742-5120","email":"eget.ipsum@aol.org","address":"P.O. Box 141, 8487 Iaculis Street","postalZip":"21135-58571","country":"Vietnam"},{"customerId":176,"customerName":"Jermaine Whitley","phone":"1-713-959-8547","email":"eleifend.vitae@outlook.com","address":"204-8232 Nec, Rd.","postalZip":"411316","country":"Norway"},{"customerId":177,"customerName":"Ramona Cunningham","phone":"1-739-817-2821","email":"eu.enim.etiam@aol.couk","address":"4073 Gravida. Rd.","postalZip":"41213","country":"Austria"},{"customerId":178,"customerName":"Kirk Holcomb","phone":"1-238-478-4240","email":"integer.mollis.integer@icloud.com","address":"P.O. Box 570, 7087 Euismod Av.","postalZip":"484232","country":"Indonesia"},{"customerId":179,"customerName":"Erin Moses","phone":"1-737-387-2710","email":"nec.luctus.felis@aol.ca","address":"Ap #582-3463 A Rd.","postalZip":"1638","country":"Germany"},{"customerId":180,"customerName":"Joelle Casey","phone":"1-235-245-1813","email":"et.risus@icloud.couk","address":"P.O. Box 757, 7096 Tellus Av.","postalZip":"51106","country":"Belgium"},{"customerId":181,"customerName":"Hamilton Serrano","phone":"1-237-330-2730","email":"suspendisse.sed@outlook.org","address":"223 Justo Av.","postalZip":"484955","country":"India"},{"customerId":182,"customerName":"Sierra Bridges","phone":"1-214-790-6763","email":"vitae.nibh.donec@aol.couk","address":"1165 Elit Street","postalZip":"4136","country":"Chile"},{"customerId":183,"customerName":"Jamalia Slater","phone":"1-967-277-3814","email":"nam.ac@hotmail.couk","address":"685-1393 Vulputate, Street","postalZip":"3664","country":"Singapore"},{"customerId":184,"customerName":"Cleo O'brien","phone":"1-336-515-1247","email":"ipsum.phasellus.vitae@yahoo.net","address":"9200 Nam Road","postalZip":"9183-7785","country":"China"},{"customerId":185,"customerName":"Yardley Weeks","phone":"(771) 775-6528","email":"donec.felis@google.com","address":"Ap #821-6615 Porttitor St.","postalZip":"9522","country":"Chile"},{"customerId":186,"customerName":"Gabriel Mullins","phone":"1-653-117-9264","email":"eros.turpis@outlook.net","address":"Ap #974-645 Vel Rd.","postalZip":"32943","country":"Italy"},{"customerId":187,"customerName":"Kirestin Kent","phone":"1-555-824-7829","email":"dignissim.lacus@hotmail.net","address":"560-439 Morbi Ave","postalZip":"71913","country":"Italy"},{"customerId":188,"customerName":"Guinevere Foreman","phone":"(763) 953-1852","email":"ultrices.sit@google.edu","address":"Ap #625-949 Ut, St.","postalZip":"1616","country":"Netherlands"},{"customerId":189,"customerName":"Dean Gordon","phone":"1-191-202-1640","email":"bibendum.fermentum.metus@hotmail.com","address":"303-7358 At, Road","postalZip":"49913","country":"Turkey"},{"customerId":190,"customerName":"Quemby Ayala","phone":"1-211-475-1683","email":"aliquam.ornare.libero@icloud.org","address":"Ap #491-2446 Sed Ave","postalZip":"1682","country":"Spain"},{"customerId":191,"customerName":"Lynn Crosby","phone":"(913) 614-2347","email":"suspendisse.eleifend@outlook.edu","address":"810-1069 A, Avenue","postalZip":"16-36","country":"Ireland"},{"customerId":192,"customerName":"Shelly Raymond","phone":"1-361-965-5339","email":"duis@icloud.net","address":"Ap #819-9220 Laoreet Rd.","postalZip":"Y7L 6W3","country":"Austria"},{"customerId":193,"customerName":"Baxter Valenzuela","phone":"(193) 276-6247","email":"mi.lacinia@yahoo.ca","address":"192-1805 Ac Street","postalZip":"415859","country":"Germany"},{"customerId":194,"customerName":"Caleb Montgomery","phone":"(817) 602-7763","email":"fusce.aliquet@aol.com","address":"6251 Dui. St.","postalZip":"65473","country":"Canada"},{"customerId":195,"customerName":"Isabella Trujillo","phone":"(788) 924-6787","email":"neque.non@hotmail.edu","address":"4601 Donec Ave","postalZip":"123342","country":"Chile"},{"customerId":196,"customerName":"Fitzgerald Buckley","phone":"(151) 130-3142","email":"non.dapibus.rutrum@outlook.ca","address":"680-2290 Dis St.","postalZip":"896833","country":"Austria"},{"customerId":197,"customerName":"Paul Frank","phone":"1-954-730-1417","email":"sed@hotmail.net","address":"3205 Varius Avenue","postalZip":"6311","country":"Austria"},{"customerId":198,"customerName":"Alexa Holland","phone":"(451) 214-3886","email":"augue.sed@icloud.com","address":"Ap #634-8004 Odio. Rd.","postalZip":"66-138","country":"Austria"},{"customerId":199,"customerName":"Holly Hutchinson","phone":"(759) 626-2541","email":"est.mollis@hotmail.com","address":"441-2070 Tristique Avenue","postalZip":"8852 CD","country":"France"},{"customerId":200,"customerName":"Colette Vega","phone":"1-809-541-0225","email":"nam.ac@google.edu","address":"949-8812 Quam Avenue","postalZip":"95240","country":"France"},{"customerId":201,"customerName":"Aurelia Mccullough","phone":"(529) 578-8112","email":"amet.diam@protonmail.net","address":"812-920 Ligula Rd.","postalZip":"51017","country":"Brazil"},{"customerId":202,"customerName":"Nicholas King","phone":"1-335-959-0268","email":"eget.ipsum@icloud.com","address":"P.O. Box 770, 237 Volutpat Av.","postalZip":"3715","country":"Nigeria"},{"customerId":203,"customerName":"Palmer Wheeler","phone":"(277) 292-2618","email":"non.dapibus@google.net","address":"372-8673 Odio. Street","postalZip":"385823","country":"Canada"},{"customerId":204,"customerName":"Samuel Berry","phone":"(475) 337-4578","email":"id.libero.donec@hotmail.net","address":"894-3616 Nonummy Road","postalZip":"66977","country":"Ukraine"},{"customerId":205,"customerName":"Yasir Montoya","phone":"(137) 236-3582","email":"a.felis@yahoo.couk","address":"P.O. Box 930, 4496 Integer Rd.","postalZip":"6634-7162","country":"Ireland"},{"customerId":206,"customerName":"Evan Harper","phone":"1-887-985-5954","email":"ut@aol.couk","address":"Ap #839-4041 Metus Av.","postalZip":"74-66","country":"Australia"},{"customerId":207,"customerName":"Gregory Leach","phone":"(817) 526-9671","email":"fusce.fermentum@outlook.net","address":"9527 Ultrices. Ave","postalZip":"6625","country":"Pakistan"},{"customerId":208,"customerName":"Josephine Burris","phone":"1-280-667-8722","email":"mus.proin@hotmail.ca","address":"911-6465 Condimentum Rd.","postalZip":"52514","country":"Nigeria"},{"customerId":209,"customerName":"Otto Mercer","phone":"1-437-258-2150","email":"inceptos.hymenaeos.mauris@icloud.net","address":"8671 Scelerisque Rd.","postalZip":"32147","country":"Belgium"},{"customerId":210,"customerName":"Illana Kennedy","phone":"(921) 287-4668","email":"tristique@protonmail.ca","address":"P.O. Box 427, 7016 Nibh St.","postalZip":"6991","country":"Nigeria"},{"customerId":211,"customerName":"Cally Kaufman","phone":"1-721-125-2623","email":"ut.mi.duis@outlook.com","address":"Ap #829-867 Eget Ave","postalZip":"70-258","country":"Norway"},{"customerId":212,"customerName":"Jameson Mosley","phone":"1-727-864-9532","email":"aliquam.nec@icloud.edu","address":"Ap #315-119 Phasellus St.","postalZip":"635531","country":"New Zealand"},{"customerId":213,"customerName":"Henry Humphrey","phone":"(166) 817-2735","email":"turpis.aliquam@aol.edu","address":"713-1242 Id, Ave","postalZip":"27672","country":"Poland"},{"customerId":214,"customerName":"Gloria England","phone":"1-386-252-4973","email":"eu.enim@hotmail.org","address":"Ap #736-8873 Dui Avenue","postalZip":"414340","country":"Australia"},{"customerId":215,"customerName":"Helen Wilkinson","phone":"1-677-472-2742","email":"non@yahoo.edu","address":"741-6586 Molestie St.","postalZip":"5051","country":"United Kingdom"},{"customerId":216,"customerName":"Talon Pitts","phone":"(666) 839-7372","email":"sem.consequat@protonmail.edu","address":"5571 Mi. St.","postalZip":"66-68","country":"Russian Federation"},{"customerId":217,"customerName":"Ursula Newman","phone":"1-657-729-5559","email":"arcu.nunc.mauris@icloud.couk","address":"Ap #631-751 Fames Road","postalZip":"889247","country":"Belgium"},{"customerId":218,"customerName":"Fatima Boyd","phone":"1-663-334-7121","email":"lorem.luctus@yahoo.ca","address":"701-8986 A Av.","postalZip":"8463-2931","country":"Netherlands"},{"customerId":219,"customerName":"Aline Battle","phone":"(251) 310-2663","email":"vivamus.nisi@yahoo.ca","address":"P.O. Box 581, 6213 Duis Av.","postalZip":"22332","country":"Mexico"},{"customerId":220,"customerName":"Brent Allen","phone":"(875) 515-3322","email":"non.feugiat@protonmail.com","address":"724-9470 Elementum Ave","postalZip":"757793","country":"New Zealand"},{"customerId":221,"customerName":"Yetta Powell","phone":"(329) 142-3882","email":"justo.faucibus@icloud.org","address":"Ap #901-6412 Nam Rd.","postalZip":"48676","country":"Russian Federation"},{"customerId":222,"customerName":"Zeus Lynch","phone":"1-515-704-3286","email":"ut.cursus.luctus@yahoo.com","address":"P.O. Box 391, 9445 Rutrum St.","postalZip":"37598-75017","country":"South Korea"},{"customerId":223,"customerName":"Matthew Bryan","phone":"(927) 453-7193","email":"porttitor.scelerisque@outlook.net","address":"Ap #709-3616 Praesent Ave","postalZip":"58027","country":"Austria"},{"customerId":224,"customerName":"Aidan Emerson","phone":"(672) 720-9542","email":"nulla@hotmail.org","address":"2395 Purus St.","postalZip":"72813","country":"New Zealand"},{"customerId":225,"customerName":"Whilemina Fitzgerald","phone":"(267) 247-9036","email":"eu.neque.pellentesque@google.edu","address":"P.O. Box 265, 1761 Nisi Rd.","postalZip":"35530","country":"China"},{"customerId":226,"customerName":"Talon Little","phone":"1-896-644-3685","email":"mauris.sapien@hotmail.couk","address":"Ap #600-3214 Natoque St.","postalZip":"009406","country":"Netherlands"},{"customerId":227,"customerName":"Deborah Davenport","phone":"1-488-593-0067","email":"adipiscing.non.luctus@hotmail.net","address":"500-8011 Eget, Av.","postalZip":"287534","country":"United States"},{"customerId":228,"customerName":"MacKensie Fernandez","phone":"1-316-265-6465","email":"urna@yahoo.couk","address":"746-7829 In St.","postalZip":"38827","country":"Mexico"},{"customerId":229,"customerName":"Marcia Snider","phone":"(259) 882-5376","email":"integer@hotmail.net","address":"P.O. Box 651, 9732 Porttitor St.","postalZip":"01674","country":"Italy"},{"customerId":230,"customerName":"Selma Gray","phone":"(825) 777-6846","email":"commodo.ipsum@yahoo.ca","address":"9975 Quam Rd.","postalZip":"303114","country":"United States"},{"customerId":231,"customerName":"Igor Brady","phone":"1-224-170-7577","email":"quis.urna.nunc@google.edu","address":"P.O. Box 843, 3207 Eros Avenue","postalZip":"120342","country":"South Korea"},{"customerId":232,"customerName":"Marsden Scott","phone":"(312) 469-4156","email":"semper@yahoo.edu","address":"9821 Magna. St.","postalZip":"5755 IZ","country":"Sweden"},{"customerId":233,"customerName":"Caleb Beasley","phone":"1-761-565-3058","email":"gravida.nunc.sed@yahoo.edu","address":"Ap #678-9550 Quisque Avenue","postalZip":"3878","country":"Russian Federation"},{"customerId":234,"customerName":"Allen Soto","phone":"(486) 921-8537","email":"non@icloud.net","address":"Ap #552-1964 Semper Street","postalZip":"735428","country":"Norway"},{"customerId":235,"customerName":"Belle Kramer","phone":"1-963-314-4195","email":"nec.diam.duis@protonmail.ca","address":"Ap #533-5143 Odio, Ave","postalZip":"621357","country":"France"},{"customerId":236,"customerName":"Savannah Martin","phone":"1-604-634-2426","email":"suspendisse@protonmail.couk","address":"950-171 Ultricies Avenue","postalZip":"22253","country":"Ukraine"},{"customerId":237,"customerName":"Jasmine Stokes","phone":"(826) 644-4729","email":"aliquam@protonmail.org","address":"6372 Nunc St.","postalZip":"513382","country":"Netherlands"},{"customerId":238,"customerName":"Alexander Doyle","phone":"1-488-354-9546","email":"ipsum@yahoo.edu","address":"6847 Ipsum Av.","postalZip":"7886","country":"South Africa"},{"customerId":239,"customerName":"Lamar Bush","phone":"1-756-173-6359","email":"ipsum@hotmail.ca","address":"985 Donec Rd.","postalZip":"45-86","country":"India"},{"customerId":240,"customerName":"Isadora Fuller","phone":"1-484-722-9103","email":"sed.dictum.proin@yahoo.net","address":"838-5569 Nunc St.","postalZip":"73-13","country":"Philippines"},{"customerId":241,"customerName":"Mallory Goodwin","phone":"(831) 123-7927","email":"dapibus@outlook.com","address":"5849 Lacus. Road","postalZip":"3756","country":"Netherlands"},{"customerId":242,"customerName":"Carol Clay","phone":"1-513-371-2533","email":"ornare.placerat@protonmail.couk","address":"Ap #629-2448 Tortor Avenue","postalZip":"3567 TX","country":"France"},{"customerId":243,"customerName":"Emerald Valenzuela","phone":"1-311-823-3821","email":"id.ante@yahoo.net","address":"1237 Aliquam Av.","postalZip":"43732","country":"Costa Rica"},{"customerId":244,"customerName":"Lynn Dean","phone":"(853) 220-5171","email":"nulla@outlook.ca","address":"592-4473 Cras Street","postalZip":"136265","country":"Colombia"},{"customerId":245,"customerName":"Deanna Drake","phone":"(907) 704-8403","email":"viverra.maecenas@hotmail.com","address":"Ap #245-5061 Ultricies Av.","postalZip":"53261-077","country":"China"},{"customerId":246,"customerName":"Risa Barnett","phone":"1-484-724-7792","email":"nam.tempor@google.ca","address":"387-3289 Id, Ave","postalZip":"42324","country":"Belgium"},{"customerId":247,"customerName":"Chanda Goff","phone":"1-363-136-6294","email":"auctor.ullamcorper@google.com","address":"P.O. Box 445, 2913 Amet, Road","postalZip":"1586","country":"Colombia"},{"customerId":248,"customerName":"Cecilia Elliott","phone":"(323) 556-6283","email":"consectetuer.adipiscing@protonmail.ca","address":"2794 Mauris Street","postalZip":"854730","country":"Ireland"},{"customerId":249,"customerName":"Deacon Monroe","phone":"(712) 334-2351","email":"risus.donec@hotmail.net","address":"9360 Odio Rd.","postalZip":"14707-637","country":"Spain"},{"customerId":250,"customerName":"Edan Nguyen","phone":"1-433-816-3453","email":"ad.litora@google.ca","address":"566-2831 Nam St.","postalZip":"68-356","country":"Brazil"},{"customerId":251,"customerName":"Wesley Hughes","phone":"(216) 437-1077","email":"tristique.senectus@icloud.couk","address":"359-7242 Mi Rd.","postalZip":"577763","country":"Nigeria"},{"customerId":252,"customerName":"Henry Coffey","phone":"1-604-438-7321","email":"risus.nulla@outlook.couk","address":"9846 Natoque Rd.","postalZip":"6432-1728","country":"Brazil"},{"customerId":253,"customerName":"Nolan Lara","phone":"1-865-914-8666","email":"justo.faucibus@hotmail.couk","address":"Ap #712-8382 Urna, St.","postalZip":"5615","country":"Canada"},{"customerId":254,"customerName":"Justin Willis","phone":"1-412-547-4767","email":"et.magna@icloud.com","address":"498-9593 Nisl St.","postalZip":"665044","country":"United Kingdom"},{"customerId":255,"customerName":"Selma English","phone":"(696) 953-3985","email":"nec.mauris@aol.org","address":"Ap #349-4635 Sapien. St.","postalZip":"18597","country":"Brazil"},{"customerId":256,"customerName":"Donna Todd","phone":"(778) 814-1364","email":"nibh.dolor.nonummy@protonmail.ca","address":"Ap #106-3050 Aliquam Rd.","postalZip":"34752-75482","country":"South Africa"},{"customerId":257,"customerName":"Noah Francis","phone":"1-488-212-7714","email":"molestie@icloud.org","address":"429 Et, Road","postalZip":"3336","country":"Mexico"},{"customerId":258,"customerName":"Dora Head","phone":"(395) 855-5634","email":"donec.tempor@google.couk","address":"Ap #309-2891 Vitae, Rd.","postalZip":"35713","country":"South Korea"},{"customerId":259,"customerName":"Louis Gallegos","phone":"1-530-425-6764","email":"nec.cursus.a@outlook.edu","address":"624-7788 Lacinia. St.","postalZip":"694428","country":"Nigeria"},{"customerId":260,"customerName":"Penelope Hogan","phone":"(255) 416-4132","email":"ornare.libero@icloud.com","address":"P.O. Box 728, 7345 Cras Avenue","postalZip":"8522","country":"South Africa"},{"customerId":261,"customerName":"Cedric Hopkins","phone":"1-582-252-8036","email":"a.aliquet.vel@google.net","address":"341-9236 Porta Street","postalZip":"7332","country":"Australia"},{"customerId":262,"customerName":"Craig Alvarado","phone":"(644) 405-5215","email":"morbi@google.couk","address":"Ap #204-2795 A, Avenue","postalZip":"ET1 7NM","country":"Chile"},{"customerId":263,"customerName":"Callie Conner","phone":"(541) 433-7779","email":"amet.dapibus.id@google.net","address":"Ap #773-8201 A Rd.","postalZip":"10301","country":"Peru"},{"customerId":264,"customerName":"Brenden Bell","phone":"1-816-372-4255","email":"pellentesque.ultricies.dignissim@protonmail.ca","address":"Ap #723-1428 Nec Street","postalZip":"41001","country":"United Kingdom"},{"customerId":265,"customerName":"Adria Booth","phone":"1-818-603-5565","email":"lobortis.mauris@protonmail.edu","address":"273-9905 Sit Rd.","postalZip":"88761","country":"United Kingdom"},{"customerId":266,"customerName":"Chava Fischer","phone":"1-313-245-0765","email":"id.erat@yahoo.ca","address":"Ap #919-1096 Venenatis Rd.","postalZip":"31811","country":"United States"},{"customerId":267,"customerName":"Clayton Hoffman","phone":"(895) 786-3262","email":"adipiscing@google.org","address":"Ap #179-174 Cras Street","postalZip":"7268","country":"Poland"},{"customerId":268,"customerName":"Hayes Ferrell","phone":"1-443-337-3613","email":"vel.sapien.imperdiet@yahoo.org","address":"8251 Eu St.","postalZip":"5178","country":"United States"},{"customerId":269,"customerName":"Emma Newton","phone":"(228) 715-2705","email":"eu@yahoo.com","address":"Ap #581-3655 Ac Av.","postalZip":"1231-1389","country":"Canada"},{"customerId":270,"customerName":"Giacomo Fitzpatrick","phone":"1-627-382-2524","email":"nec.ante@google.ca","address":"9491 Velit Road","postalZip":"380298","country":"Indonesia"},{"customerId":271,"customerName":"Christine Steele","phone":"1-325-646-8233","email":"dignissim@google.couk","address":"780-3131 Augue. Rd.","postalZip":"616127","country":"China"},{"customerId":272,"customerName":"Ray Bush","phone":"(872) 462-4427","email":"sed.id.risus@yahoo.com","address":"362-359 Nullam Rd.","postalZip":"755108","country":"South Africa"},{"customerId":273,"customerName":"Price Cote","phone":"1-388-854-2213","email":"ipsum@protonmail.edu","address":"Ap #927-651 Mauris Rd.","postalZip":"22353","country":"Peru"},{"customerId":274,"customerName":"Silas Maynard","phone":"1-765-832-6975","email":"velit@google.org","address":"6731 Fusce Avenue","postalZip":"22773","country":"Ireland"},{"customerId":275,"customerName":"Zena Brooks","phone":"(288) 273-1375","email":"donec.nibh@aol.org","address":"Ap #156-9306 Lectus Rd.","postalZip":"8268","country":"Singapore"},{"customerId":276,"customerName":"Ferdinand Hampton","phone":"(915) 920-8532","email":"erat.semper.rutrum@yahoo.com","address":"Ap #561-5241 Aliquet Street","postalZip":"14556","country":"Singapore"},{"customerId":277,"customerName":"Keefe Gilliam","phone":"(845) 657-5376","email":"augue@aol.edu","address":"Ap #662-5036 Mauris Rd.","postalZip":"39-666","country":"India"},{"customerId":278,"customerName":"Timon Barr","phone":"1-488-359-0136","email":"accumsan.laoreet.ipsum@icloud.org","address":"626-8640 Nec, St.","postalZip":"07460","country":"South Korea"},{"customerId":279,"customerName":"Harlan Beard","phone":"1-994-671-3557","email":"nam@yahoo.net","address":"Ap #332-1742 Vitae, St.","postalZip":"652675","country":"Colombia"},{"customerId":280,"customerName":"Fletcher Mclean","phone":"(255) 876-5491","email":"in@outlook.com","address":"P.O. Box 898, 9802 Sollicitudin Rd.","postalZip":"46626","country":"United States"},{"customerId":281,"customerName":"Griffin Woods","phone":"(541) 325-1702","email":"nulla.eu@icloud.edu","address":"Ap #404-6111 Per Rd.","postalZip":"772818","country":"New Zealand"},{"customerId":282,"customerName":"Angela Ferguson","phone":"1-430-334-0671","email":"luctus.vulputate@protonmail.org","address":"Ap #541-9833 Aliquet. Ave","postalZip":"46575","country":"Chile"},{"customerId":283,"customerName":"Hashim Lowe","phone":"1-377-593-3919","email":"proin@google.couk","address":"668-8867 Lorem, Rd.","postalZip":"467422","country":"Russian Federation"},{"customerId":284,"customerName":"Wyatt Joyce","phone":"(530) 212-6652","email":"tellus.imperdiet@icloud.org","address":"646-7638 Ut Road","postalZip":"5978-5762","country":"New Zealand"},{"customerId":285,"customerName":"Gregory Bradshaw","phone":"(545) 483-8816","email":"aliquet.sem@outlook.com","address":"P.O. Box 275, 9869 Rhoncus. Road","postalZip":"64-53","country":"Mexico"},{"customerId":286,"customerName":"Pearl Wood","phone":"1-618-481-2183","email":"feugiat@google.couk","address":"Ap #620-3056 Lobortis Avenue","postalZip":"866376","country":"Nigeria"},{"customerId":287,"customerName":"Richard Ortiz","phone":"(469) 876-8463","email":"consequat@protonmail.couk","address":"Ap #637-5686 Elementum, Rd.","postalZip":"85742","country":"Peru"},{"customerId":288,"customerName":"Hakeem Hayden","phone":"(313) 793-7137","email":"quisque.ornare@yahoo.com","address":"428-4459 Turpis Av.","postalZip":"01238","country":"France"},{"customerId":289,"customerName":"Byron Cooper","phone":"(665) 687-0031","email":"amet.ante.vivamus@protonmail.ca","address":"6402 Amet, St.","postalZip":"7349 HW","country":"United States"},{"customerId":290,"customerName":"Ruby Wolfe","phone":"1-547-568-7216","email":"morbi.sit@yahoo.org","address":"7422 Eu Rd.","postalZip":"21129-965","country":"Ukraine"},{"customerId":291,"customerName":"Odysseus Howard","phone":"1-689-722-4560","email":"eros.non@yahoo.couk","address":"Ap #665-4091 Magna Road","postalZip":"584207","country":"Netherlands"},{"customerId":292,"customerName":"Magee Mann","phone":"1-864-488-5741","email":"donec.nibh@hotmail.com","address":"531-6849 Est, Ave","postalZip":"5480","country":"Costa Rica"},{"customerId":293,"customerName":"Inez Sexton","phone":"1-323-835-7826","email":"penatibus.et@protonmail.couk","address":"Ap #518-9623 Posuere Ave","postalZip":"43554","country":"Italy"},{"customerId":294,"customerName":"Charde Rose","phone":"1-994-423-0323","email":"mauris@icloud.ca","address":"819-7349 In St.","postalZip":"77224","country":"Canada"},{"customerId":295,"customerName":"Quinn Burnett","phone":"(327) 234-6675","email":"sit.amet@hotmail.edu","address":"Ap #978-3339 Curabitur Rd.","postalZip":"66725","country":"Pakistan"},{"customerId":296,"customerName":"Hollee Fletcher","phone":"(401) 671-5652","email":"vehicula.aliquet.libero@yahoo.ca","address":"2459 Elit, Avenue","postalZip":"6784-1011","country":"Costa Rica"},{"customerId":297,"customerName":"Sybill Hoover","phone":"1-749-153-7298","email":"nec@hotmail.com","address":"183-1871 Ante. Street","postalZip":"389383","country":"Austria"},{"customerId":298,"customerName":"Keefe Blackburn","phone":"1-835-251-3502","email":"tempus@yahoo.net","address":"Ap #110-5064 Duis Street","postalZip":"39211-11883","country":"Singapore"},{"customerId":299,"customerName":"Coby Evans","phone":"(528) 295-9329","email":"metus.sit.amet@outlook.ca","address":"Ap #540-8073 Sem. St.","postalZip":"5351","country":"Ireland"},{"customerId":300,"customerName":"Reese Mccarthy","phone":"(525) 665-1876","email":"vitae.dolor.donec@outlook.edu","address":"P.O. Box 537, 6955 Libero. St.","postalZip":"5857","country":"Spain"},{"customerId":301,"customerName":"Gisela Collins","phone":"1-983-834-2244","email":"donec@aol.org","address":"492-7356 Risus Rd.","postalZip":"Y1G 8N4","country":"Nigeria"},{"customerId":302,"customerName":"Rylee Sears","phone":"(281) 220-3044","email":"semper.erat.in@hotmail.ca","address":"Ap #396-3079 Pellentesque, Ave","postalZip":"I5 8YA","country":"Poland"},{"customerId":303,"customerName":"Jana Parsons","phone":"(469) 784-9162","email":"elementum@protonmail.couk","address":"356-7478 Id St.","postalZip":"30765","country":"Poland"},{"customerId":304,"customerName":"Chiquita Giles","phone":"(690) 282-1110","email":"nec.mauris@icloud.edu","address":"P.O. Box 623, 2780 Massa St.","postalZip":"325151","country":"South Korea"},{"customerId":305,"customerName":"Leah Jefferson","phone":"(534) 837-4432","email":"pede.cum@protonmail.couk","address":"3960 Consectetuer, Ave","postalZip":"803683","country":"Pakistan"},{"customerId":306,"customerName":"Amy Middleton","phone":"1-425-639-1978","email":"quisque@icloud.ca","address":"P.O. Box 271, 3429 Tortor St.","postalZip":"2367","country":"South Africa"},{"customerId":307,"customerName":"Maris Underwood","phone":"(635) 838-8174","email":"elit.curabitur@protonmail.net","address":"972-8674 Non Street","postalZip":"188425","country":"Australia"},{"customerId":308,"customerName":"Hall Mendoza","phone":"1-581-423-4214","email":"sed@aol.couk","address":"594-1417 Libero St.","postalZip":"50109","country":"Ireland"},{"customerId":309,"customerName":"Kibo Curtis","phone":"1-318-489-5448","email":"integer.sem@hotmail.com","address":"P.O. Box 491, 6073 Semper Rd.","postalZip":"79457","country":"Belgium"},{"customerId":310,"customerName":"Ian Hyde","phone":"(503) 424-7209","email":"eget@google.com","address":"Ap #443-3234 Arcu Rd.","postalZip":"81322-448","country":"Chile"},{"customerId":311,"customerName":"Vincent Rivers","phone":"1-415-129-2713","email":"id@yahoo.com","address":"Ap #185-3842 Integer Rd.","postalZip":"571644","country":"Nigeria"},{"customerId":312,"customerName":"Elton Duran","phone":"(824) 759-8438","email":"aenean.eget.magna@yahoo.com","address":"790-3169 Nullam St.","postalZip":"517453","country":"Sweden"},{"customerId":313,"customerName":"Anne Barnes","phone":"1-250-658-2841","email":"ipsum.non@outlook.ca","address":"Ap #137-9867 Sapien Av.","postalZip":"40300","country":"Ukraine"},{"customerId":314,"customerName":"Althea Holland","phone":"(938) 787-6943","email":"a@yahoo.org","address":"783-1382 Cursus Rd.","postalZip":"4773","country":"India"},{"customerId":315,"customerName":"Sade Brooks","phone":"1-641-623-2307","email":"cras.dictum@icloud.edu","address":"9034 Sit Rd.","postalZip":"3443","country":"Philippines"},{"customerId":316,"customerName":"Elvis Mann","phone":"1-384-864-5311","email":"facilisis.lorem@icloud.edu","address":"Ap #500-9323 Vehicula. St.","postalZip":"23541","country":"New Zealand"},{"customerId":317,"customerName":"Jason Ewing","phone":"(764) 231-5857","email":"magna.a@protonmail.edu","address":"441-5511 Gravida Road","postalZip":"637943","country":"South Africa"},{"customerId":318,"customerName":"Brennan Dunn","phone":"(285) 940-6155","email":"ultricies@outlook.org","address":"5191 Quam Street","postalZip":"952885","country":"Canada"},{"customerId":319,"customerName":"Griffith Gonzales","phone":"1-146-961-5197","email":"egestas.aliquam@icloud.net","address":"518-4398 In, Rd.","postalZip":"862432","country":"Nigeria"},{"customerId":320,"customerName":"Demetrius Spencer","phone":"(620) 245-2604","email":"amet.ultricies@yahoo.ca","address":"Ap #563-4210 Lorem St.","postalZip":"35144","country":"Mexico"},{"customerId":321,"customerName":"Jerry Houston","phone":"1-100-235-6447","email":"ornare@protonmail.com","address":"238-4106 Odio St.","postalZip":"21156","country":"Germany"},{"customerId":322,"customerName":"Madonna May","phone":"1-541-883-2666","email":"nullam.scelerisque@outlook.com","address":"860-2657 Ultrices Avenue","postalZip":"7827 SF","country":"India"},{"customerId":323,"customerName":"Vance Cunningham","phone":"(477) 661-9718","email":"nunc.quisque@icloud.edu","address":"559-7825 Sapien. St.","postalZip":"S4 7MU","country":"Colombia"},{"customerId":324,"customerName":"Timothy Garrison","phone":"1-398-261-7157","email":"imperdiet@aol.net","address":"Ap #928-9398 Vivamus Road","postalZip":"33252","country":"Italy"},{"customerId":325,"customerName":"Berk Carver","phone":"1-128-645-8082","email":"in.scelerisque@google.com","address":"182-8065 Adipiscing Rd.","postalZip":"768627","country":"Norway"},{"customerId":326,"customerName":"Jason Torres","phone":"1-153-624-7418","email":"velit.in@outlook.com","address":"3286 Morbi Ave","postalZip":"67-245","country":"Germany"},{"customerId":327,"customerName":"Lane Mitchell","phone":"(347) 133-6044","email":"ridiculus.mus@yahoo.net","address":"862-8773 Dictum Rd.","postalZip":"08-554","country":"Germany"},{"customerId":328,"customerName":"Amir Albert","phone":"(957) 879-0145","email":"congue.in@aol.org","address":"229-7578 Euismod St.","postalZip":"6584","country":"New Zealand"},{"customerId":329,"customerName":"Magee Guthrie","phone":"(526) 884-0836","email":"dictum.eu@icloud.com","address":"P.O. Box 724, 9254 Neque. St.","postalZip":"4435","country":"Austria"},{"customerId":330,"customerName":"Jerry Rasmussen","phone":"1-458-356-2655","email":"elementum.sem@hotmail.edu","address":"P.O. Box 914, 3761 Risus. Ave","postalZip":"MK4 7RL","country":"Chile"},{"customerId":331,"customerName":"Kaseem Leon","phone":"1-243-864-6476","email":"proin.sed@hotmail.edu","address":"696 Sed Rd.","postalZip":"9125","country":"Mexico"},{"customerId":332,"customerName":"Olympia Noble","phone":"(537) 635-6386","email":"justo.nec@hotmail.com","address":"466-2060 Vitae Road","postalZip":"83128","country":"Brazil"},{"customerId":333,"customerName":"Phillip Cabrera","phone":"1-556-315-7456","email":"ligula.consectetuer.rhoncus@icloud.org","address":"P.O. Box 639, 8994 Egestas. Rd.","postalZip":"703516","country":"France"},{"customerId":334,"customerName":"Diana Chavez","phone":"1-729-354-1853","email":"ullamcorper.duis@google.couk","address":"309-9819 Cras Street","postalZip":"B2N 9J5","country":"Peru"},{"customerId":335,"customerName":"Shay Kline","phone":"(332) 131-7766","email":"porttitor.interdum@outlook.edu","address":"5658 Lacinia Street","postalZip":"5055 HD","country":"Nigeria"},{"customerId":336,"customerName":"Lana Santana","phone":"1-945-466-5287","email":"pretium.et@hotmail.ca","address":"5118 Bibendum Road","postalZip":"318788","country":"United Kingdom"},{"customerId":337,"customerName":"Hammett Raymond","phone":"1-229-452-6520","email":"dictum@hotmail.edu","address":"3144 Egestas. Road","postalZip":"6324","country":"Philippines"},{"customerId":338,"customerName":"Francis Harper","phone":"1-357-421-4528","email":"ultrices.duis.volutpat@aol.ca","address":"P.O. Box 832, 2212 Tellus St.","postalZip":"87-69","country":"Norway"},{"customerId":339,"customerName":"Rylee Hooper","phone":"1-214-823-1015","email":"sodales.mauris.blandit@yahoo.net","address":"7186 Ornare, Street","postalZip":"502473","country":"Australia"},{"customerId":340,"customerName":"Kaye Alvarez","phone":"(855) 158-7702","email":"parturient.montes.nascetur@aol.edu","address":"862-5219 Placerat Rd.","postalZip":"382323","country":"Brazil"},{"customerId":341,"customerName":"Quail Kennedy","phone":"(867) 221-6583","email":"nunc.quis.arcu@aol.org","address":"196-1452 Magna Ave","postalZip":"05255","country":"Costa Rica"},{"customerId":342,"customerName":"Violet Massey","phone":"1-277-634-2381","email":"ante@hotmail.ca","address":"Ap #378-4290 Suspendisse Avenue","postalZip":"43560","country":"Philippines"},{"customerId":343,"customerName":"Thomas Whitaker","phone":"1-767-722-9632","email":"orci.donec@aol.ca","address":"647-1109 Mi Rd.","postalZip":"16775","country":"Pakistan"},{"customerId":344,"customerName":"Orson Kidd","phone":"(671) 558-1733","email":"montes.nascetur@yahoo.couk","address":"Ap #139-5917 Rutrum Avenue","postalZip":"T5X 1EN","country":"Indonesia"},{"customerId":345,"customerName":"Sharon Sanders","phone":"1-709-128-4651","email":"orci.lobortis@icloud.ca","address":"182-6607 Accumsan Av.","postalZip":"54164","country":"Indonesia"},{"customerId":346,"customerName":"Kuame Gilmore","phone":"1-164-623-2250","email":"montes.nascetur@icloud.couk","address":"P.O. Box 611, 8816 Dapibus Ave","postalZip":"5476-8827","country":"South Korea"},{"customerId":347,"customerName":"Yetta Gamble","phone":"(113) 772-2838","email":"nisi.nibh@aol.com","address":"P.O. Box 136, 8433 Mauris, St.","postalZip":"23471","country":"China"},{"customerId":348,"customerName":"Cleo Bruce","phone":"(494) 454-5412","email":"euismod.urna@protonmail.edu","address":"P.O. Box 415, 9066 Neque. St.","postalZip":"49257","country":"Peru"},{"customerId":349,"customerName":"Rigel Miller","phone":"(557) 666-8730","email":"ultrices.duis@google.com","address":"770-4112 Fermentum Av.","postalZip":"2382-7561","country":"Germany"},{"customerId":350,"customerName":"Erica Ratliff","phone":"1-633-695-3559","email":"gravida@aol.ca","address":"Ap #114-9821 Nullam Avenue","postalZip":"47-128","country":"Turkey"},{"customerId":351,"customerName":"Asher Barnes","phone":"1-731-790-1527","email":"volutpat.nulla@hotmail.edu","address":"686-9182 Mattis. Rd.","postalZip":"5607","country":"South Africa"},{"customerId":352,"customerName":"Jane Bond","phone":"1-773-962-6237","email":"sit@hotmail.com","address":"9982 Arcu. Street","postalZip":"241644","country":"Singapore"},{"customerId":353,"customerName":"Veda Gates","phone":"1-525-719-1234","email":"ut.semper.pretium@hotmail.ca","address":"536-950 Mattis. Rd.","postalZip":"18354","country":"Spain"},{"customerId":354,"customerName":"Lisandra Hull","phone":"1-913-744-5839","email":"non.bibendum@outlook.edu","address":"P.O. Box 482, 5103 In Ave","postalZip":"69565","country":"Costa Rica"},{"customerId":355,"customerName":"Echo Diaz","phone":"(445) 405-4587","email":"non.cursus.non@google.edu","address":"Ap #855-3934 Proin Ave","postalZip":"3205","country":"Colombia"},{"customerId":356,"customerName":"Celeste Preston","phone":"1-261-688-8369","email":"ultrices.a.auctor@hotmail.com","address":"Ap #189-425 Metus Ave","postalZip":"413248","country":"China"},{"customerId":357,"customerName":"Keane Cervantes","phone":"1-582-238-7332","email":"urna.nunc@aol.edu","address":"Ap #870-6101 Dignissim Ave","postalZip":"54385","country":"New Zealand"},{"customerId":358,"customerName":"Kieran Lowe","phone":"1-524-443-9131","email":"duis.dignissim@protonmail.ca","address":"882 Etiam St.","postalZip":"J5X 7C4","country":"Singapore"},{"customerId":359,"customerName":"Isaiah Duran","phone":"1-511-634-8106","email":"tincidunt.neque@google.com","address":"P.O. Box 370, 4907 Risus Rd.","postalZip":"4572","country":"Nigeria"},{"customerId":360,"customerName":"Armando Yang","phone":"(718) 531-1069","email":"imperdiet@google.org","address":"571-4395 Montes, Street","postalZip":"774564","country":"Sweden"},{"customerId":361,"customerName":"Aretha Sawyer","phone":"(794) 398-6437","email":"urna@icloud.net","address":"995-4838 Euismod Street","postalZip":"1512","country":"Costa Rica"},{"customerId":362,"customerName":"Rogan Sloan","phone":"(889) 457-2267","email":"risus.a@protonmail.couk","address":"169-3718 Neque Rd.","postalZip":"625058","country":"Poland"},{"customerId":363,"customerName":"Julian Branch","phone":"1-128-430-2363","email":"libero@hotmail.ca","address":"P.O. Box 383, 1112 Neque Rd.","postalZip":"3657","country":"Poland"},{"customerId":364,"customerName":"Aidan Ayers","phone":"1-594-977-5864","email":"ac.risus@icloud.org","address":"P.O. Box 369, 4964 Tellus, Street","postalZip":"621482","country":"South Korea"},{"customerId":365,"customerName":"Kaitlin Peterson","phone":"(483) 656-1820","email":"sit@google.ca","address":"Ap #908-5222 Consectetuer Road","postalZip":"80440-32248","country":"South Korea"},{"customerId":366,"customerName":"Mark Jimenez","phone":"1-834-270-4558","email":"cras.vehicula@yahoo.couk","address":"P.O. Box 323, 4116 Neque Rd.","postalZip":"2825","country":"Germany"},{"customerId":367,"customerName":"Jin Lane","phone":"(284) 561-6240","email":"sem.mollis@outlook.com","address":"P.O. Box 443, 7371 Vitae Rd.","postalZip":"5311","country":"China"},{"customerId":368,"customerName":"Malachi Bender","phone":"(212) 377-1120","email":"at.arcu@yahoo.couk","address":"696-467 Nunc Rd.","postalZip":"21167","country":"Sweden"},{"customerId":369,"customerName":"Kasimir Strickland","phone":"(365) 534-5724","email":"arcu@yahoo.org","address":"Ap #778-5996 Tristique Ave","postalZip":"408322","country":"Austria"},{"customerId":370,"customerName":"Avram Landry","phone":"(725) 567-1191","email":"ante@outlook.edu","address":"Ap #595-7217 Fermentum Av.","postalZip":"95251","country":"Ukraine"},{"customerId":371,"customerName":"Charissa Soto","phone":"1-862-478-0734","email":"scelerisque.scelerisque.dui@icloud.com","address":"Ap #109-9179 Elit. Av.","postalZip":"872388","country":"New Zealand"},{"customerId":372,"customerName":"Josiah Rocha","phone":"(788) 631-9275","email":"eleifend.nec@hotmail.couk","address":"510-3381 Nunc St.","postalZip":"853868","country":"Indonesia"},{"customerId":373,"customerName":"Adara Tillman","phone":"1-878-908-6832","email":"commodo.hendrerit.donec@icloud.org","address":"Ap #639-5997 Nec Rd.","postalZip":"50212","country":"Norway"},{"customerId":374,"customerName":"Louis Skinner","phone":"(367) 631-2734","email":"at@hotmail.edu","address":"Ap #976-3050 Orci Street","postalZip":"PD6R 3PI","country":"United Kingdom"},{"customerId":375,"customerName":"Lacey Weeks","phone":"1-722-936-2754","email":"integer.mollis.integer@icloud.couk","address":"9313 Sem. Avenue","postalZip":"42176","country":"Poland"},{"customerId":376,"customerName":"Yvonne Kim","phone":"1-279-868-1631","email":"semper.pretium.neque@google.net","address":"Ap #656-7665 Est Avenue","postalZip":"13693","country":"South Africa"},{"customerId":377,"customerName":"Damian Jefferson","phone":"(741) 385-7251","email":"massa@yahoo.ca","address":"P.O. Box 511, 5696 Nam Av.","postalZip":"F8H 9Z4","country":"Ireland"},{"customerId":378,"customerName":"Craig Short","phone":"(763) 637-2831","email":"quisque@protonmail.edu","address":"Ap #282-3271 Est Street","postalZip":"4539","country":"South Korea"},{"customerId":379,"customerName":"Rhoda Mcknight","phone":"(741) 458-7914","email":"penatibus.et@icloud.ca","address":"Ap #565-6944 Cras Rd.","postalZip":"31824","country":"New Zealand"},{"customerId":380,"customerName":"Maile Mercer","phone":"1-566-245-7657","email":"luctus.lobortis.class@yahoo.edu","address":"Ap #439-3970 Fringilla Ave","postalZip":"28693","country":"Philippines"},{"customerId":381,"customerName":"Cullen Sellers","phone":"(398) 340-9244","email":"ac.orci@protonmail.net","address":"P.O. Box 460, 3283 Elit, Rd.","postalZip":"570427","country":"Philippines"},{"customerId":382,"customerName":"Kato Olson","phone":"(735) 555-2525","email":"at@google.couk","address":"Ap #391-8711 Ante Street","postalZip":"976564","country":"Italy"},{"customerId":383,"customerName":"Lionel Good","phone":"(474) 544-6638","email":"fermentum@hotmail.org","address":"Ap #863-5541 Vulputate St.","postalZip":"7317","country":"Norway"},{"customerId":384,"customerName":"Owen Mueller","phone":"(486) 407-7500","email":"leo.vivamus@google.net","address":"Ap #119-5560 Enim St.","postalZip":"C7Z 3Y5","country":"South Africa"},{"customerId":385,"customerName":"Kennan Acosta","phone":"1-394-556-5185","email":"magna@google.org","address":"Ap #306-7782 Sollicitudin St.","postalZip":"4693-7121","country":"Brazil"},{"customerId":386,"customerName":"Bruce Buckley","phone":"1-374-282-4315","email":"ac.eleifend@aol.edu","address":"Ap #695-1546 Eget Avenue","postalZip":"8714","country":"Pakistan"},{"customerId":387,"customerName":"Caldwell England","phone":"1-833-581-4760","email":"pharetra.nam.ac@google.couk","address":"Ap #614-3781 Suspendisse Street","postalZip":"439634","country":"Colombia"},{"customerId":388,"customerName":"Moses Gordon","phone":"(566) 867-2182","email":"elit.etiam@google.edu","address":"869-5000 Ac Ave","postalZip":"78-55","country":"Netherlands"},{"customerId":389,"customerName":"Abigail Mcintyre","phone":"1-799-679-0214","email":"ac.arcu@outlook.ca","address":"180-5468 Nec Rd.","postalZip":"308060","country":"Singapore"},{"customerId":390,"customerName":"Virginia Travis","phone":"(456) 164-4253","email":"neque.et@hotmail.org","address":"6945 Tincidunt, Av.","postalZip":"J6P 2G5","country":"Germany"},{"customerId":391,"customerName":"Iris Morse","phone":"1-766-815-6360","email":"dis.parturient.montes@icloud.ca","address":"P.O. Box 663, 9844 Sit Avenue","postalZip":"423762","country":"Canada"},{"customerId":392,"customerName":"Samson Douglas","phone":"(728) 447-8454","email":"aliquam.adipiscing@aol.ca","address":"Ap #573-5089 Orci, Av.","postalZip":"287604","country":"Sweden"},{"customerId":393,"customerName":"Stone Daniel","phone":"1-770-405-4824","email":"tempus@icloud.couk","address":"Ap #954-1907 Et Rd.","postalZip":"72021","country":"China"},{"customerId":394,"customerName":"Jade Vasquez","phone":"1-452-435-1738","email":"nec.quam@google.net","address":"7410 Imperdiet Rd.","postalZip":"82725","country":"Germany"},{"customerId":395,"customerName":"Mia Nguyen","phone":"(925) 746-8536","email":"tempor.est.ac@icloud.edu","address":"Ap #232-4245 At, St.","postalZip":"99515","country":"United Kingdom"},{"customerId":396,"customerName":"Jeremy Holloway","phone":"(379) 222-9206","email":"nec.ligula@icloud.couk","address":"P.O. Box 283, 2641 Consectetuer Rd.","postalZip":"08481","country":"Canada"},{"customerId":397,"customerName":"Dieter Richard","phone":"(338) 298-6841","email":"sit@icloud.net","address":"P.O. Box 852, 629 Laoreet, Rd.","postalZip":"YY6 5JT","country":"Italy"},{"customerId":398,"customerName":"Kylie Ballard","phone":"1-478-336-7431","email":"nec.imperdiet.nec@aol.org","address":"1952 Ipsum Rd.","postalZip":"73168","country":"Australia"},{"customerId":399,"customerName":"Winter Cox","phone":"(516) 421-8332","email":"pede.nonummy@hotmail.couk","address":"620-473 Lectus Rd.","postalZip":"57931","country":"Germany"},{"customerId":400,"customerName":"Maisie Vaughn","phone":"1-825-318-6435","email":"tempor.erat@yahoo.org","address":"453-4253 Tincidunt St.","postalZip":"74-74","country":"Pakistan"},{"customerId":401,"customerName":"Burton Lucas","phone":"(376) 658-4612","email":"libero.integer.in@protonmail.org","address":"Ap #898-8853 Eu Road","postalZip":"386871","country":"Canada"},{"customerId":402,"customerName":"Unity Mullins","phone":"1-837-312-6128","email":"lorem.vehicula@yahoo.ca","address":"386-632 Tellus Road","postalZip":"73338-56432","country":"Nigeria"},{"customerId":403,"customerName":"Basia Parks","phone":"1-440-883-7962","email":"erat.volutpat.nulla@protonmail.com","address":"Ap #599-610 Pharetra Street","postalZip":"68534-211","country":"Russian Federation"},{"customerId":404,"customerName":"Cameran Guy","phone":"1-271-354-1648","email":"bibendum.donec.felis@outlook.edu","address":"933-4282 Amet St.","postalZip":"77771","country":"Indonesia"},{"customerId":405,"customerName":"Wilma Lindsay","phone":"(963) 948-3167","email":"et.netus@aol.org","address":"Ap #935-3952 Mus. Avenue","postalZip":"363977","country":"Germany"},{"customerId":406,"customerName":"Axel Reyes","phone":"1-604-514-3222","email":"vestibulum.ante@icloud.net","address":"897-6751 Vitae Rd.","postalZip":"183503","country":"United States"},{"customerId":407,"customerName":"Sara Tran","phone":"(716) 494-7543","email":"interdum.enim@aol.net","address":"106-4176 Amet Av.","postalZip":"6200","country":"Russian Federation"},{"customerId":408,"customerName":"Zenia Dotson","phone":"1-265-516-3169","email":"pellentesque.ultricies.dignissim@google.ca","address":"Ap #433-2117 Lacus, Avenue","postalZip":"1893 FY","country":"Nigeria"},{"customerId":409,"customerName":"Ignatius Coleman","phone":"1-576-225-2466","email":"diam@yahoo.org","address":"757-8359 Sed Ave","postalZip":"33452","country":"United Kingdom"},{"customerId":410,"customerName":"Xavier Hughes","phone":"(204) 656-2774","email":"enim.nec@google.edu","address":"660-2867 Suspendisse Av.","postalZip":"62S 9R8","country":"Canada"},{"customerId":411,"customerName":"Kirestin Mcmillan","phone":"1-885-268-9515","email":"id.enim@aol.edu","address":"P.O. Box 517, 8457 Pede. Ave","postalZip":"11268","country":"Peru"},{"customerId":412,"customerName":"Herman Whitfield","phone":"(230) 690-5961","email":"gravida.aliquam@aol.edu","address":"344-3824 Morbi Street","postalZip":"9454","country":"New Zealand"},{"customerId":413,"customerName":"Dylan Pickett","phone":"(339) 874-7973","email":"posuere.at.velit@yahoo.net","address":"P.O. Box 362, 1266 Commodo Rd.","postalZip":"87661","country":"Philippines"},{"customerId":414,"customerName":"Gary Espinoza","phone":"(904) 288-9363","email":"vitae.velit.egestas@google.couk","address":"342-9066 Auctor Rd.","postalZip":"ZG2G 3JX","country":"Belgium"},{"customerId":415,"customerName":"Nehru Byrd","phone":"1-891-575-8280","email":"nonummy.fusce@icloud.com","address":"Ap #843-8303 Quis, St.","postalZip":"875063","country":"Ireland"},{"customerId":416,"customerName":"Tyler Riley","phone":"1-181-559-5170","email":"ornare@yahoo.net","address":"4328 Dui. Av.","postalZip":"6472","country":"Russian Federation"},{"customerId":417,"customerName":"Kelsey Faulkner","phone":"(522) 458-3587","email":"faucibus.orci.luctus@outlook.ca","address":"9385 Nibh Road","postalZip":"74703-435","country":"China"},{"customerId":418,"customerName":"Bruno Clark","phone":"(636) 893-0237","email":"phasellus@google.couk","address":"Ap #938-7753 At St.","postalZip":"GT7 9OV","country":"Germany"},{"customerId":419,"customerName":"Damian Burch","phone":"1-576-884-6072","email":"odio.sagittis@aol.com","address":"P.O. Box 391, 5587 Donec Av.","postalZip":"X82 4UF","country":"New Zealand"},{"customerId":420,"customerName":"Carol Ramsey","phone":"1-887-238-9733","email":"augue.ut.lacus@aol.ca","address":"Ap #799-2575 Ante Av.","postalZip":"189592","country":"Philippines"},{"customerId":421,"customerName":"Jena Barr","phone":"1-275-516-7237","email":"in.tempus.eu@protonmail.org","address":"Ap #359-2483 Nec Road","postalZip":"18381","country":"Singapore"},{"customerId":422,"customerName":"Kimberly Mays","phone":"1-251-208-1467","email":"sed.et.libero@outlook.edu","address":"198-9512 Aliquam St.","postalZip":"157671","country":"Poland"},{"customerId":423,"customerName":"Laith Kim","phone":"(478) 948-4743","email":"duis.a.mi@hotmail.net","address":"342-6341 Feugiat. Ave","postalZip":"3637","country":"Pakistan"},{"customerId":424,"customerName":"Orla Oneil","phone":"(388) 849-8159","email":"egestas.urna@aol.org","address":"6735 Nunc. Av.","postalZip":"29696","country":"Germany"},{"customerId":425,"customerName":"Charles Morton","phone":"(767) 519-3695","email":"aliquet.molestie.tellus@google.couk","address":"202-5602 Mi. Ave","postalZip":"12241","country":"Costa Rica"},{"customerId":426,"customerName":"Debra Sosa","phone":"1-201-400-2217","email":"justo.sit@icloud.org","address":"Ap #540-2810 Tincidunt, Av.","postalZip":"65718","country":"Colombia"},{"customerId":427,"customerName":"Hedwig Rosario","phone":"1-256-395-7566","email":"porttitor.scelerisque@protonmail.couk","address":"598-3605 Mi Ave","postalZip":"73746-699","country":"Vietnam"},{"customerId":428,"customerName":"Maxwell Shaffer","phone":"(305) 288-9774","email":"nam.tempor.diam@google.edu","address":"Ap #440-7692 Dictum. Road","postalZip":"27-74","country":"Vietnam"},{"customerId":429,"customerName":"Hamish Foreman","phone":"1-683-565-4311","email":"ac@google.com","address":"2305 Mauris Ave","postalZip":"S5K 6H8","country":"Russian Federation"},{"customerId":430,"customerName":"MacKenzie Cortez","phone":"1-418-976-4523","email":"at.nisi@google.net","address":"387-287 Nam Ave","postalZip":"77969","country":"Spain"},{"customerId":431,"customerName":"Oleg Stephens","phone":"1-436-287-3161","email":"elementum.lorem@icloud.ca","address":"9093 Sed Avenue","postalZip":"26532","country":"South Korea"},{"customerId":432,"customerName":"Joseph Fry","phone":"1-279-190-2967","email":"porttitor.vulputate@google.ca","address":"P.O. Box 593, 4292 Sagittis St.","postalZip":"85-24","country":"Australia"},{"customerId":433,"customerName":"Sybil Bullock","phone":"(878) 282-8810","email":"mi@aol.net","address":"Ap #821-9673 Eget Road","postalZip":"42-72","country":"China"},{"customerId":434,"customerName":"Tucker Stephens","phone":"1-485-422-1135","email":"nulla@icloud.ca","address":"P.O. Box 992, 1019 Amet Av.","postalZip":"2897","country":"Belgium"},{"customerId":435,"customerName":"Barrett Harmon","phone":"1-647-944-8773","email":"at@hotmail.edu","address":"462-1221 Aenean St.","postalZip":"442288","country":"Italy"},{"customerId":436,"customerName":"Kirk Sweeney","phone":"(452) 412-2973","email":"sodales@aol.net","address":"457-5872 Id, Av.","postalZip":"O56 7YS","country":"Chile"},{"customerId":437,"customerName":"Orson Bowers","phone":"1-948-408-6471","email":"facilisis.suspendisse@google.org","address":"995-7530 Nullam Avenue","postalZip":"1117","country":"Ireland"},{"customerId":438,"customerName":"Lila Gomez","phone":"(777) 644-5534","email":"ipsum.cursus.vestibulum@yahoo.edu","address":"734-9379 Suspendisse Rd.","postalZip":"4722","country":"Poland"},{"customerId":439,"customerName":"Jerry Hensley","phone":"1-522-705-8983","email":"orci.in@yahoo.couk","address":"Ap #664-8633 Orci St.","postalZip":"1215-1724","country":"South Africa"},{"customerId":440,"customerName":"Jackson Rodriquez","phone":"(405) 608-1438","email":"nullam.feugiat@hotmail.org","address":"P.O. Box 472, 8587 Ante Rd.","postalZip":"6883","country":"Austria"},{"customerId":441,"customerName":"Emi Tyler","phone":"1-206-862-4695","email":"neque.morbi@outlook.net","address":"407-4268 Penatibus Street","postalZip":"52323","country":"Chile"},{"customerId":442,"customerName":"Brynne Todd","phone":"(893) 834-3819","email":"vulputate.lacus@protonmail.net","address":"Ap #462-5927 Faucibus Av.","postalZip":"5748","country":"Nigeria"},{"customerId":443,"customerName":"Fitzgerald Valencia","phone":"1-447-557-3238","email":"lorem.ipsum@outlook.edu","address":"4238 Aliquam Road","postalZip":"85473","country":"Italy"},{"customerId":444,"customerName":"Martina Henson","phone":"(269) 158-1591","email":"ut@icloud.ca","address":"Ap #724-2429 Vel Street","postalZip":"12353","country":"United States"},{"customerId":445,"customerName":"Hasad Beach","phone":"1-810-426-2541","email":"faucibus@hotmail.com","address":"202-2982 Nec Rd.","postalZip":"9114 ZY","country":"United Kingdom"},{"customerId":446,"customerName":"Aphrodite Schneider","phone":"1-734-453-1155","email":"vitae.sodales.at@icloud.net","address":"3628 Aliquam Rd.","postalZip":"874155","country":"Norway"},{"customerId":447,"customerName":"Farrah Everett","phone":"1-467-236-7028","email":"ligula@hotmail.com","address":"949-7839 Sagittis. Av.","postalZip":"5495","country":"Singapore"},{"customerId":448,"customerName":"Silas Parks","phone":"1-212-565-6775","email":"suspendisse@outlook.net","address":"356-7448 Eu Rd.","postalZip":"54427","country":"Indonesia"},{"customerId":449,"customerName":"Aretha Whitney","phone":"1-133-722-0766","email":"facilisis@protonmail.edu","address":"187-5686 Urna Ave","postalZip":"664376","country":"Canada"},{"customerId":450,"customerName":"Chanda Kidd","phone":"(235) 285-8558","email":"euismod@outlook.edu","address":"P.O. Box 438, 6067 Cras Rd.","postalZip":"54444","country":"Germany"},{"customerId":451,"customerName":"Devin Nicholson","phone":"(537) 841-2636","email":"nunc@google.org","address":"Ap #727-5591 Vitae Avenue","postalZip":"9813","country":"Norway"},{"customerId":452,"customerName":"Mira Conner","phone":"1-731-932-6305","email":"sapien.gravida@outlook.net","address":"712-540 Congue Avenue","postalZip":"215067","country":"Italy"},{"customerId":453,"customerName":"Cameron Avery","phone":"1-711-110-5289","email":"mattis@google.edu","address":"962-2700 Duis Road","postalZip":"3807","country":"China"},{"customerId":454,"customerName":"Tara Mercado","phone":"(476) 424-5325","email":"vivamus@aol.edu","address":"327-4369 Feugiat. Rd.","postalZip":"68-88","country":"France"},{"customerId":455,"customerName":"Abdul Lyons","phone":"(393) 179-5521","email":"nunc.sed@yahoo.edu","address":"P.O. Box 252, 9089 Cursus St.","postalZip":"40616","country":"United Kingdom"},{"customerId":456,"customerName":"Kelsey Woods","phone":"1-598-278-2470","email":"scelerisque.neque.sed@hotmail.couk","address":"2006 Vivamus Avenue","postalZip":"177122","country":"China"},{"customerId":457,"customerName":"Ciara Russell","phone":"1-601-466-4670","email":"magna@icloud.edu","address":"P.O. Box 673, 3257 Sed, Av.","postalZip":"5876","country":"Sweden"},{"customerId":458,"customerName":"Doris Head","phone":"(458) 563-1867","email":"imperdiet.ullamcorper@yahoo.com","address":"Ap #821-2942 Lectus St.","postalZip":"67834-782","country":"Peru"},{"customerId":459,"customerName":"Simone Blackwell","phone":"(812) 501-7644","email":"ac.ipsum@protonmail.edu","address":"Ap #735-3018 Egestas Rd.","postalZip":"05571","country":"Turkey"},{"customerId":460,"customerName":"Laith Carlson","phone":"(825) 855-8848","email":"adipiscing.enim.mi@google.net","address":"8988 Amet, Street","postalZip":"8997 WU","country":"Germany"},{"customerId":461,"customerName":"Lavinia Mccall","phone":"(229) 384-0166","email":"dictum.augue@protonmail.couk","address":"687-598 Nisi. Ave","postalZip":"2805","country":"Pakistan"},{"customerId":462,"customerName":"Cynthia Lindsey","phone":"1-616-547-4933","email":"duis@yahoo.org","address":"Ap #542-1629 Dictum Rd.","postalZip":"681507","country":"Austria"},{"customerId":463,"customerName":"Mason Dennis","phone":"(630) 332-8318","email":"natoque.penatibus@yahoo.ca","address":"Ap #323-3212 Sociis Ave","postalZip":"87-746","country":"United Kingdom"},{"customerId":464,"customerName":"Rajah Osborn","phone":"1-542-883-3541","email":"ac.sem.ut@icloud.ca","address":"Ap #938-3674 Accumsan Av.","postalZip":"35041-33265","country":"Sweden"},{"customerId":465,"customerName":"Sopoline Watts","phone":"(676) 369-1232","email":"sodales@google.couk","address":"9673 Tincidunt, Rd.","postalZip":"316104","country":"Mexico"},{"customerId":466,"customerName":"Ifeoma Anthony","phone":"(616) 102-5432","email":"sapien.molestie@protonmail.ca","address":"586-5080 Eleifend Av.","postalZip":"8606","country":"Mexico"},{"customerId":467,"customerName":"Chandler Hunter","phone":"1-260-566-7096","email":"lorem@yahoo.com","address":"7734 Sed Rd.","postalZip":"3558","country":"Mexico"},{"customerId":468,"customerName":"Jackson Hernandez","phone":"1-467-786-5912","email":"orci.lobortis@outlook.couk","address":"P.O. Box 175, 4872 Eu, Av.","postalZip":"80108","country":"Canada"},{"customerId":469,"customerName":"Mark Roy","phone":"1-682-266-1885","email":"lorem@outlook.org","address":"Ap #636-8909 Velit St.","postalZip":"9763-1377","country":"New Zealand"},{"customerId":470,"customerName":"Amos Burke","phone":"(421) 955-9430","email":"ipsum.ac.mi@hotmail.edu","address":"Ap #183-2811 Nulla Rd.","postalZip":"12779","country":"United States"},{"customerId":471,"customerName":"Amethyst Reed","phone":"(551) 727-1287","email":"mi.duis@google.couk","address":"Ap #146-7303 Eu Avenue","postalZip":"635241","country":"New Zealand"},{"customerId":472,"customerName":"Josephine Skinner","phone":"(975) 427-6472","email":"egestas.hendrerit@outlook.net","address":"Ap #170-7914 Aliquam Avenue","postalZip":"6166 JN","country":"Chile"},{"customerId":473,"customerName":"Alan Sampson","phone":"1-132-527-6711","email":"eleifend.nec.malesuada@hotmail.org","address":"5271 Aptent Av.","postalZip":"4458-0172","country":"Russian Federation"},{"customerId":474,"customerName":"Samantha Rich","phone":"1-273-959-9671","email":"sed.molestie@protonmail.couk","address":"Ap #394-3258 Nascetur St.","postalZip":"5819-6511","country":"Germany"},{"customerId":475,"customerName":"Nicholas Robinson","phone":"1-462-463-0236","email":"pede@icloud.org","address":"Ap #875-8527 Cras Rd.","postalZip":"67-71","country":"Turkey"},{"customerId":476,"customerName":"Kareem Marquez","phone":"(766) 672-5176","email":"nulla.semper.tellus@hotmail.com","address":"Ap #940-2093 Commodo Ave","postalZip":"5680","country":"Costa Rica"},{"customerId":477,"customerName":"Griffin Clark","phone":"1-512-157-9846","email":"erat@protonmail.com","address":"6407 Tristique St.","postalZip":"31564","country":"France"},{"customerId":478,"customerName":"Keaton Hardin","phone":"(875) 498-4537","email":"placerat.velit@yahoo.edu","address":"347-3408 Et, Ave","postalZip":"34790","country":"United States"},{"customerId":479,"customerName":"Kyra Hawkins","phone":"(324) 476-1898","email":"mauris.eu@protonmail.net","address":"618-4767 Dolor Ave","postalZip":"6385-2734","country":"New Zealand"},{"customerId":480,"customerName":"Ivy Pugh","phone":"(174) 460-2389","email":"tempus@google.net","address":"246-3973 Aenean Avenue","postalZip":"53579-717","country":"Indonesia"},{"customerId":481,"customerName":"Henry Kirk","phone":"(343) 498-2121","email":"pellentesque.tincidunt@protonmail.com","address":"657-4860 Integer Avenue","postalZip":"143526","country":"China"},{"customerId":482,"customerName":"Harrison Kinney","phone":"(431) 984-6387","email":"nunc.sed@icloud.couk","address":"P.O. Box 722, 4947 Dignissim Avenue","postalZip":"41706","country":"Singapore"},{"customerId":483,"customerName":"Anthony Nicholson","phone":"(582) 854-4315","email":"feugiat.placerat@yahoo.edu","address":"665-1352 Ipsum Ave","postalZip":"21512","country":"Ireland"},{"customerId":484,"customerName":"Lionel Hurley","phone":"(448) 310-1278","email":"a.mi.fringilla@icloud.edu","address":"P.O. Box 945, 7019 Luctus. St.","postalZip":"74344","country":"Canada"},{"customerId":485,"customerName":"Lunea Mcleod","phone":"(482) 278-4754","email":"et.nunc.quisque@yahoo.ca","address":"Ap #198-3491 Arcu. Av.","postalZip":"418946","country":"Canada"},{"customerId":486,"customerName":"Mannix Pate","phone":"1-758-697-1711","email":"curabitur@icloud.com","address":"P.O. Box 480, 1716 Sed, St.","postalZip":"56-212","country":"Mexico"},{"customerId":487,"customerName":"Audrey Rosario","phone":"(756) 546-7628","email":"ultricies.dignissim@google.ca","address":"Ap #969-5674 Sed, St.","postalZip":"464523","country":"Turkey"},{"customerId":488,"customerName":"Regina Mcgowan","phone":"(795) 882-8157","email":"id@yahoo.com","address":"965 Magna. Avenue","postalZip":"97171","country":"Austria"},{"customerId":489,"customerName":"Fuller Huffman","phone":"1-665-460-8027","email":"suspendisse.non@outlook.couk","address":"Ap #412-6907 Mauris Avenue","postalZip":"23357","country":"Austria"},{"customerId":490,"customerName":"Knox Mclean","phone":"(652) 257-4851","email":"duis.sit.amet@yahoo.net","address":"Ap #613-8130 Scelerisque, Road","postalZip":"36640","country":"Australia"},{"customerId":491,"customerName":"Bethany Strickland","phone":"(745) 788-0145","email":"lacinia@icloud.org","address":"1365 Diam. Road","postalZip":"3548","country":"Colombia"},{"customerId":492,"customerName":"Minerva Garrett","phone":"1-327-405-1467","email":"cursus.et@hotmail.couk","address":"Ap #541-3798 A, Street","postalZip":"74183","country":"Costa Rica"},{"customerId":493,"customerName":"Callie Case","phone":"(453) 680-7347","email":"eu.nibh.vulputate@yahoo.edu","address":"543 Neque. St.","postalZip":"530125","country":"Netherlands"},{"customerId":494,"customerName":"Noelle Ellis","phone":"(558) 382-1374","email":"velit@google.edu","address":"P.O. Box 862, 280 Libero Ave","postalZip":"701885","country":"Russian Federation"},{"customerId":495,"customerName":"Paul Roth","phone":"1-754-620-5397","email":"commodo.tincidunt@google.couk","address":"P.O. Box 762, 5952 Cras Avenue","postalZip":"62712","country":"Poland"},{"customerId":496,"customerName":"Teagan Bailey","phone":"1-836-387-6271","email":"sed@yahoo.net","address":"P.O. Box 598, 4857 Pede St.","postalZip":"8046","country":"Costa Rica"},{"customerId":497,"customerName":"Lila Goff","phone":"(887) 136-9291","email":"nec@aol.couk","address":"Ap #569-661 Elit, Road","postalZip":"37427","country":"Mexico"},{"customerId":498,"customerName":"Chancellor Richards","phone":"1-828-651-5128","email":"dui@aol.edu","address":"P.O. Box 765, 9239 Integer Road","postalZip":"k2K 7C5","country":"Austria"},{"customerId":499,"customerName":"Inga Harvey","phone":"(240) 782-4863","email":"est.tempor@outlook.ca","address":"396-3585 Pellentesque, Road","postalZip":"55929-261","country":"Poland"},{"customerId":500,"customerName":"Glenna Norris","phone":"1-927-316-4142","email":"nunc@google.net","address":"P.O. Box 929, 9946 Dis Rd.","postalZip":"8563","country":"Brazil"},{"customerId":501,"customerName":"Nyssa Stephenson","phone":"(488) 446-9193","email":"nisi.sem@aol.net","address":"651-4051 Nunc Rd.","postalZip":"143764","country":"Canada"},{"customerId":502,"customerName":"Harrison Kirk","phone":"(673) 560-0943","email":"sociis@icloud.couk","address":"788-5989 Dolor. Rd.","postalZip":"59P 2S4","country":"United States"},{"customerId":503,"customerName":"Adara Beach","phone":"1-246-878-6774","email":"lectus@protonmail.net","address":"135-3892 Turpis Rd.","postalZip":"435146","country":"China"},{"customerId":504,"customerName":"Connor Collier","phone":"1-880-821-9747","email":"cras.pellentesque.sed@outlook.net","address":"426-8911 Enim Rd.","postalZip":"57684","country":"Canada"},{"customerId":505,"customerName":"Hadassah Marshall","phone":"(301) 783-2235","email":"fermentum.vel@icloud.ca","address":"519-7138 Mauris, Rd.","postalZip":"3874 XP","country":"Russian Federation"},{"customerId":506,"customerName":"Veronica O'brien","phone":"1-375-561-3633","email":"tincidunt.orci@protonmail.ca","address":"P.O. Box 191, 9421 Convallis Avenue","postalZip":"27283","country":"Brazil"},{"customerId":507,"customerName":"Raven Valentine","phone":"(223) 657-8582","email":"vehicula.et@hotmail.ca","address":"125-8482 Sapien. Avenue","postalZip":"37883","country":"Netherlands"},{"customerId":508,"customerName":"Britanney Rollins","phone":"(168) 257-6713","email":"ante.nunc.mauris@aol.org","address":"286-6279 Donec Rd.","postalZip":"51218","country":"Nigeria"},{"customerId":509,"customerName":"Valentine Koch","phone":"(321) 147-3456","email":"risus@icloud.net","address":"Ap #456-4172 Neque Rd.","postalZip":"21961","country":"Italy"},{"customerId":510,"customerName":"Anika Best","phone":"(977) 515-1763","email":"ligula.aenean@icloud.edu","address":"Ap #251-8905 Aliquet Street","postalZip":"82869-325","country":"France"},{"customerId":511,"customerName":"MacKensie Mendoza","phone":"1-179-987-4866","email":"at@protonmail.couk","address":"393 Etiam Street","postalZip":"353482","country":"Poland"},{"customerId":512,"customerName":"Kelly Marshall","phone":"1-577-874-3916","email":"augue.id@icloud.org","address":"623-343 Facilisis Rd.","postalZip":"6315","country":"Russian Federation"},{"customerId":513,"customerName":"Hedda Mcknight","phone":"1-417-992-7045","email":"tincidunt.nunc.ac@hotmail.com","address":"Ap #317-6393 Malesuada Road","postalZip":"46362","country":"Singapore"},{"customerId":514,"customerName":"Joseph Fields","phone":"1-213-582-5211","email":"libero.est.congue@yahoo.org","address":"296-8925 Tellus Road","postalZip":"87823","country":"Peru"},{"customerId":515,"customerName":"Madeline Mcdonald","phone":"1-658-662-6768","email":"nec@aol.org","address":"Ap #781-9617 Et Av.","postalZip":"72278","country":"Spain"},{"customerId":516,"customerName":"Uriah Mathews","phone":"(605) 535-2516","email":"pede.cum@yahoo.ca","address":"769-6678 Praesent St.","postalZip":"05172","country":"Mexico"},{"customerId":517,"customerName":"Mannix Watson","phone":"1-212-818-9062","email":"est@outlook.org","address":"Ap #380-1306 Magna Rd.","postalZip":"23-450","country":"Colombia"},{"customerId":518,"customerName":"Shafira Lawson","phone":"1-862-248-6621","email":"lectus.sit@outlook.com","address":"280-5710 Vestibulum Rd.","postalZip":"917435","country":"Ukraine"},{"customerId":519,"customerName":"Hyatt Roberts","phone":"1-475-223-8566","email":"nec@google.couk","address":"686-8777 Sit Ave","postalZip":"28241","country":"United Kingdom"},{"customerId":520,"customerName":"Nathan Ferguson","phone":"1-593-743-5347","email":"dictum.augue@outlook.net","address":"Ap #403-6631 Tortor. Rd.","postalZip":"7747","country":"Sweden"},{"customerId":521,"customerName":"Ciara Estes","phone":"(373) 665-9438","email":"sed.sem@protonmail.org","address":"Ap #608-2106 Molestie Rd.","postalZip":"365735","country":"Netherlands"},{"customerId":522,"customerName":"Irma Joseph","phone":"1-250-492-4536","email":"sed@yahoo.org","address":"778-7888 Id, Av.","postalZip":"7528","country":"Turkey"},{"customerId":523,"customerName":"Felix Melendez","phone":"(250) 270-7740","email":"mi.ac.mattis@yahoo.com","address":"P.O. Box 965, 2381 Eget St.","postalZip":"36470","country":"Philippines"},{"customerId":524,"customerName":"Blaze Wright","phone":"(315) 172-3485","email":"gravida@google.org","address":"8120 Nisl Ave","postalZip":"776259","country":"Poland"},{"customerId":525,"customerName":"Teegan Hanson","phone":"(547) 593-2365","email":"vulputate.nisi@hotmail.couk","address":"997-5345 Donec Avenue","postalZip":"54164","country":"Russian Federation"},{"customerId":526,"customerName":"Kalia Benjamin","phone":"1-827-847-1767","email":"nulla@yahoo.couk","address":"P.O. Box 874, 5418 Cursus Avenue","postalZip":"27558-72291","country":"Poland"},{"customerId":527,"customerName":"Hakeem Hunter","phone":"1-798-638-1667","email":"facilisis.suspendisse@google.net","address":"Ap #263-6555 Nascetur Ave","postalZip":"UY17 6RB","country":"United Kingdom"},{"customerId":528,"customerName":"Ginger Brooks","phone":"1-792-783-8388","email":"phasellus.fermentum.convallis@google.ca","address":"Ap #499-2572 Sit Street","postalZip":"12457","country":"China"},{"customerId":529,"customerName":"Lucius Pena","phone":"1-192-813-4825","email":"phasellus@icloud.couk","address":"830-4696 Eleifend Avenue","postalZip":"4126","country":"Germany"},{"customerId":530,"customerName":"Jayme Melendez","phone":"1-712-732-1982","email":"eu.turpis@google.net","address":"2860 Et, St.","postalZip":"648327","country":"Austria"},{"customerId":531,"customerName":"Jeanette Fisher","phone":"(280) 695-8221","email":"eu.tellus.eu@icloud.com","address":"Ap #171-4982 Dolor. Rd.","postalZip":"85445","country":"South Africa"},{"customerId":532,"customerName":"Cedric Gates","phone":"(393) 170-5143","email":"sit.amet@outlook.com","address":"6696 Amet, Rd.","postalZip":"8982","country":"Russian Federation"},{"customerId":533,"customerName":"Baxter Jacobs","phone":"(853) 758-7675","email":"neque.sed@outlook.ca","address":"P.O. Box 835, 4149 Et St.","postalZip":"J72 5EB","country":"Ireland"},{"customerId":534,"customerName":"Davis Conner","phone":"(416) 253-4837","email":"in.ornare.sagittis@icloud.couk","address":"643-4536 Ut Road","postalZip":"8920","country":"China"},{"customerId":535,"customerName":"Leilani Newman","phone":"1-787-122-5970","email":"tincidunt@aol.org","address":"Ap #662-9508 Nunc Avenue","postalZip":"729769","country":"Pakistan"},{"customerId":536,"customerName":"Driscoll Ochoa","phone":"1-242-343-0177","email":"fusce.diam.nunc@hotmail.net","address":"P.O. Box 812, 2146 Eget, Rd.","postalZip":"63523","country":"Ukraine"},{"customerId":537,"customerName":"Victoria Mcdonald","phone":"(570) 557-7966","email":"est@yahoo.edu","address":"913-7220 Placerat Avenue","postalZip":"14343","country":"Peru"},{"customerId":538,"customerName":"Wallace Rollins","phone":"(381) 193-2399","email":"felis@hotmail.net","address":"649-3006 Feugiat. Ave","postalZip":"31625","country":"Indonesia"},{"customerId":539,"customerName":"Yasir Fitzgerald","phone":"1-195-178-4435","email":"dignissim.pharetra@icloud.org","address":"Ap #190-296 Curae Avenue","postalZip":"67-37","country":"Mexico"},{"customerId":540,"customerName":"Jacqueline Olsen","phone":"1-562-756-8492","email":"metus@outlook.ca","address":"109-8931 Interdum Ave","postalZip":"731498","country":"Austria"},{"customerId":541,"customerName":"Ciaran Mcguire","phone":"(946) 115-4129","email":"erat@protonmail.org","address":"917-832 A, Av.","postalZip":"279857","country":"South Korea"},{"customerId":542,"customerName":"Dale Sargent","phone":"1-916-558-6909","email":"posuere.cubilia.curae@hotmail.couk","address":"896-6396 Cursus Rd.","postalZip":"17231","country":"Canada"},{"customerId":543,"customerName":"Maite Byers","phone":"1-626-684-6956","email":"odio.phasellus.at@hotmail.com","address":"198-5028 Donec Avenue","postalZip":"A4N 9K2","country":"Nigeria"},{"customerId":544,"customerName":"Evelyn Kidd","phone":"1-611-680-5685","email":"morbi.neque@icloud.org","address":"4637 Dolor Street","postalZip":"61660","country":"Canada"},{"customerId":545,"customerName":"Beverly Kennedy","phone":"(763) 572-2412","email":"arcu.vestibulum@google.couk","address":"9133 Pharetra Rd.","postalZip":"7452","country":"China"},{"customerId":546,"customerName":"Desiree Munoz","phone":"1-836-604-3260","email":"euismod.mauris@hotmail.com","address":"635-5531 Rutrum. St.","postalZip":"112837","country":"Australia"},{"customerId":547,"customerName":"Scott Young","phone":"1-415-751-2421","email":"nisi.sem@google.org","address":"Ap #768-7965 Id Road","postalZip":"DS8 2WM","country":"Chile"},{"customerId":548,"customerName":"Fritz Guthrie","phone":"(902) 730-6354","email":"quis.accumsan@outlook.ca","address":"Ap #810-7058 Tortor. Rd.","postalZip":"3463","country":"Indonesia"},{"customerId":549,"customerName":"Delilah Olson","phone":"1-935-206-6679","email":"molestie.sed@outlook.couk","address":"749-4811 Elit, Avenue","postalZip":"989687","country":"Italy"},{"customerId":550,"customerName":"Ocean Hammond","phone":"(625) 612-8475","email":"mauris.eu@google.net","address":"P.O. Box 627, 8827 Dignissim Av.","postalZip":"43-273","country":"Vietnam"},{"customerId":551,"customerName":"Yetta Estrada","phone":"(479) 924-2674","email":"pretium.neque@outlook.ca","address":"Ap #159-4500 Sed St.","postalZip":"754962","country":"Italy"},{"customerId":552,"customerName":"Ora Farley","phone":"1-677-747-5388","email":"nullam.scelerisque.neque@aol.net","address":"371-7270 Quis St.","postalZip":"505824","country":"South Korea"},{"customerId":553,"customerName":"Garrett Smith","phone":"(618) 432-5482","email":"tellus.non@hotmail.net","address":"427-2190 Bibendum Street","postalZip":"214110","country":"Chile"},{"customerId":554,"customerName":"Wyoming Vinson","phone":"1-887-555-4779","email":"rhoncus.proin.nisl@icloud.ca","address":"P.O. Box 562, 5139 Tincidunt Street","postalZip":"455286","country":"Canada"},{"customerId":555,"customerName":"Bert Poole","phone":"(662) 763-9768","email":"feugiat.lorem.ipsum@aol.couk","address":"625-9145 Eget, Av.","postalZip":"7734","country":"Ireland"},{"customerId":556,"customerName":"Octavius Leach","phone":"1-325-773-2762","email":"sodales.elit@google.ca","address":"3879 Pellentesque St.","postalZip":"546511","country":"United States"},{"customerId":557,"customerName":"Tana Kidd","phone":"1-825-533-5192","email":"nullam.vitae.diam@aol.org","address":"Ap #313-1958 Ullamcorper St.","postalZip":"5298","country":"Pakistan"},{"customerId":558,"customerName":"Jacqueline Olsen","phone":"(433) 134-1288","email":"suspendisse.non@icloud.couk","address":"Ap #413-9184 Rhoncus. Street","postalZip":"6812","country":"Austria"},{"customerId":559,"customerName":"Marvin Gutierrez","phone":"1-617-681-2368","email":"placerat.cras@protonmail.edu","address":"879-1720 Risus. Avenue","postalZip":"88-455","country":"South Korea"},{"customerId":560,"customerName":"Noelani Cooke","phone":"1-539-824-3543","email":"tortor.integer@yahoo.net","address":"P.O. Box 336, 5241 Euismod Rd.","postalZip":"5518","country":"Indonesia"},{"customerId":561,"customerName":"Dorian Gallegos","phone":"(920) 221-2964","email":"est.arcu.ac@google.org","address":"Ap #640-2766 Dapibus Street","postalZip":"4182","country":"Vietnam"},{"customerId":562,"customerName":"Dalton Deleon","phone":"1-147-904-5687","email":"at.velit.cras@yahoo.couk","address":"Ap #520-8053 Etiam Street","postalZip":"13815","country":"India"},{"customerId":563,"customerName":"Aquila Hardy","phone":"1-892-471-1741","email":"sociosqu.ad.litora@protonmail.net","address":"163-4575 Mi, St.","postalZip":"358622","country":"Costa Rica"},{"customerId":564,"customerName":"Hilel Velasquez","phone":"(360) 462-0252","email":"ac.orci@aol.couk","address":"Ap #101-5936 Nonummy. Street","postalZip":"1330 HL","country":"Turkey"},{"customerId":565,"customerName":"Gray Adkins","phone":"(623) 381-8277","email":"ac.mattis@hotmail.couk","address":"Ap #502-8134 Ultrices. St.","postalZip":"85-604","country":"Belgium"},{"customerId":566,"customerName":"Maisie Figueroa","phone":"(362) 422-5624","email":"aenean.eget.magna@aol.com","address":"949 Dapibus St.","postalZip":"JD21 7CN","country":"China"},{"customerId":567,"customerName":"Wilma Waller","phone":"(628) 453-8081","email":"fringilla.donec@outlook.com","address":"999-1556 Consequat St.","postalZip":"2450","country":"United States"},{"customerId":568,"customerName":"Azalia Jefferson","phone":"1-388-342-7824","email":"at@outlook.edu","address":"Ap #997-4777 Auctor Rd.","postalZip":"631737","country":"New Zealand"},{"customerId":569,"customerName":"Jasmine Paul","phone":"1-263-736-6933","email":"natoque@protonmail.couk","address":"Ap #555-9404 Massa. Street","postalZip":"874231","country":"South Korea"},{"customerId":570,"customerName":"Dominic Reyes","phone":"1-256-778-6437","email":"curabitur@icloud.net","address":"Ap #760-9437 Pharetra. St.","postalZip":"20519","country":"Italy"},{"customerId":571,"customerName":"Samantha Cooke","phone":"1-434-524-2483","email":"egestas@outlook.net","address":"Ap #368-4676 Mauris. Rd.","postalZip":"17494","country":"Germany"},{"customerId":572,"customerName":"Shaine Gutierrez","phone":"1-434-746-3559","email":"cras@hotmail.couk","address":"521-7500 Vel, Ave","postalZip":"40094-65025","country":"Canada"},{"customerId":573,"customerName":"Gareth Merritt","phone":"(232) 648-2262","email":"eu.odio.phasellus@google.ca","address":"179-8793 Aliquet. Ave","postalZip":"80722-03176","country":"Vietnam"},{"customerId":574,"customerName":"Grant Spears","phone":"(446) 575-1687","email":"natoque.penatibus@icloud.net","address":"P.O. Box 882, 5281 Sed Av.","postalZip":"Y1X 6C2","country":"Indonesia"},{"customerId":575,"customerName":"Fatima Briggs","phone":"(817) 466-2347","email":"mauris@google.com","address":"Ap #499-6101 Nisl Rd.","postalZip":"685408","country":"Austria"},{"customerId":576,"customerName":"Adena Jenkins","phone":"1-827-384-4189","email":"phasellus@icloud.net","address":"639-4162 Fermentum Ave","postalZip":"S0T 7M7","country":"Indonesia"},{"customerId":577,"customerName":"Daniel Gould","phone":"1-642-838-4917","email":"elementum.sem@hotmail.com","address":"Ap #259-3320 Ornare, Road","postalZip":"3254","country":"Nigeria"},{"customerId":578,"customerName":"Teegan Ballard","phone":"(775) 167-9434","email":"eget.metus@yahoo.org","address":"7074 Ultrices Street","postalZip":"492735","country":"United States"},{"customerId":579,"customerName":"Mira Simpson","phone":"1-784-686-7061","email":"luctus@icloud.com","address":"393-8282 Arcu Av.","postalZip":"75566","country":"Colombia"},{"customerId":580,"customerName":"Orla Blackburn","phone":"(760) 519-1668","email":"lobortis@outlook.org","address":"Ap #225-2349 Lorem Rd.","postalZip":"31-275","country":"Indonesia"},{"customerId":581,"customerName":"Libby Ayala","phone":"1-881-348-0370","email":"litora@outlook.net","address":"944-9556 Mauris Street","postalZip":"64394","country":"France"},{"customerId":582,"customerName":"Fleur Bryant","phone":"1-570-373-5022","email":"quis.lectus@google.edu","address":"Ap #587-2992 Fusce St.","postalZip":"88-673","country":"South Africa"},{"customerId":583,"customerName":"Silas Solomon","phone":"1-687-266-0815","email":"ipsum.phasellus.vitae@protonmail.edu","address":"Ap #301-1947 Tincidunt Av.","postalZip":"5684","country":"France"},{"customerId":584,"customerName":"Ferdinand Huff","phone":"1-664-644-8882","email":"pellentesque.habitant.morbi@outlook.net","address":"Ap #561-9750 Lacinia Road","postalZip":"0825","country":"Chile"},{"customerId":585,"customerName":"Leandra Diaz","phone":"(240) 640-0661","email":"et.arcu@yahoo.org","address":"P.O. Box 267, 7684 Dui. Avenue","postalZip":"365186","country":"Australia"},{"customerId":586,"customerName":"Minerva Harrington","phone":"(754) 263-5758","email":"lorem.eu@outlook.net","address":"P.O. Box 451, 1025 Proin Road","postalZip":"764417","country":"Colombia"},{"customerId":587,"customerName":"Thomas Simpson","phone":"1-208-772-3126","email":"luctus.aliquet.odio@hotmail.couk","address":"P.O. Box 703, 5490 Adipiscing Rd.","postalZip":"A2X 5G8","country":"Russian Federation"},{"customerId":588,"customerName":"Erin Henson","phone":"1-350-661-7063","email":"pellentesque.ultricies@outlook.ca","address":"2751 Cum Avenue","postalZip":"4198","country":"Sweden"},{"customerId":589,"customerName":"Calista Scott","phone":"1-620-596-3205","email":"diam.eu@protonmail.edu","address":"Ap #129-5858 Ligula. Rd.","postalZip":"3724-8534","country":"Australia"},{"customerId":590,"customerName":"Bruno Stewart","phone":"1-553-168-7857","email":"gravida.sagittis@protonmail.couk","address":"702-8683 Vulputate St.","postalZip":"144072","country":"Italy"},{"customerId":591,"customerName":"Bianca Aguirre","phone":"(331) 966-6162","email":"aliquam.adipiscing@icloud.net","address":"458-2329 Luctus, Road","postalZip":"85566-704","country":"South Korea"},{"customerId":592,"customerName":"Beverly Rios","phone":"(601) 583-8069","email":"lacus@protonmail.couk","address":"Ap #636-9265 Duis Road","postalZip":"2672-8608","country":"United States"},{"customerId":593,"customerName":"Roth Phillips","phone":"1-734-760-8340","email":"nec@google.org","address":"1107 Ac Avenue","postalZip":"752238","country":"Philippines"},{"customerId":594,"customerName":"Kasimir Gibson","phone":"(776) 752-1682","email":"quis.arcu@icloud.org","address":"P.O. Box 109, 5024 Aliquet. Avenue","postalZip":"34655","country":"United Kingdom"},{"customerId":595,"customerName":"Tasha Franco","phone":"1-621-287-0694","email":"sodales@aol.org","address":"207-3833 Felis. St.","postalZip":"20171","country":"Belgium"},{"customerId":596,"customerName":"Keith Price","phone":"(493) 756-7826","email":"donec.elementum@yahoo.net","address":"736-8931 Tempus, Rd.","postalZip":"24195","country":"United States"},{"customerId":597,"customerName":"Lara Goodman","phone":"(494) 243-3514","email":"nascetur.ridiculus.mus@google.couk","address":"573-4759 Morbi Rd.","postalZip":"06169","country":"Ireland"},{"customerId":598,"customerName":"Latifah Carney","phone":"(821) 755-4774","email":"lectus.sit.amet@icloud.couk","address":"587 Bibendum Ave","postalZip":"394378","country":"Chile"},{"customerId":599,"customerName":"Marshall O'donnell","phone":"(757) 348-3863","email":"posuere.enim.nisl@yahoo.couk","address":"319-3666 Nisi St.","postalZip":"30151","country":"Peru"},{"customerId":600,"customerName":"Holmes Fry","phone":"(912) 516-3702","email":"mauris.blandit.mattis@google.edu","address":"952-4860 Nec Avenue","postalZip":"44746","country":"Singapore"},{"customerId":601,"customerName":"Addison Deleon","phone":"(212) 482-6884","email":"suscipit@google.net","address":"Ap #371-3261 Netus St.","postalZip":"215748","country":"Chile"},{"customerId":602,"customerName":"Emmanuel Padilla","phone":"1-798-831-9342","email":"velit.quisque@protonmail.org","address":"Ap #102-5764 Enim Street","postalZip":"0368","country":"Spain"},{"customerId":603,"customerName":"Reese Bowman","phone":"1-148-532-8595","email":"ornare.sagittis@icloud.ca","address":"Ap #279-411 Pede Av.","postalZip":"R1H 5M3","country":"Sweden"},{"customerId":604,"customerName":"Veronica Patel","phone":"1-877-740-5385","email":"nibh.phasellus@google.com","address":"P.O. Box 673, 4242 Praesent St.","postalZip":"606153","country":"Australia"},{"customerId":605,"customerName":"Scarlet Reilly","phone":"1-182-353-3428","email":"commodo.hendrerit@protonmail.edu","address":"Ap #827-4924 Neque St.","postalZip":"738494","country":"Norway"},{"customerId":606,"customerName":"Gwendolyn Mathews","phone":"1-508-473-4884","email":"accumsan@outlook.edu","address":"645-2639 Arcu. St.","postalZip":"15178","country":"Austria"},{"customerId":607,"customerName":"Isabella Rios","phone":"(246) 593-1542","email":"arcu.et@yahoo.edu","address":"P.O. Box 370, 2215 Erat Ave","postalZip":"T0C 8Z7","country":"Canada"},{"customerId":608,"customerName":"Lucas Mendez","phone":"1-425-765-6172","email":"vehicula@aol.ca","address":"P.O. Box 897, 1093 Natoque Av.","postalZip":"1224","country":"Singapore"},{"customerId":609,"customerName":"Roth Navarro","phone":"1-547-632-4738","email":"condimentum.donec@protonmail.net","address":"Ap #585-2964 Nunc St.","postalZip":"29266","country":"Costa Rica"},{"customerId":610,"customerName":"Zahir Hart","phone":"(297) 368-8321","email":"faucibus.leo@hotmail.edu","address":"5085 A Rd.","postalZip":"164438","country":"Spain"},{"customerId":611,"customerName":"Stuart Patton","phone":"(251) 356-9123","email":"in.cursus.et@protonmail.ca","address":"2626 Posuere St.","postalZip":"5630","country":"South Africa"},{"customerId":612,"customerName":"Acton Mcclure","phone":"1-547-240-2255","email":"eget.varius@aol.edu","address":"483-2879 Morbi St.","postalZip":"WW8 8AE","country":"United Kingdom"},{"customerId":613,"customerName":"Kirk Glass","phone":"(427) 981-2115","email":"aenean.egestas@hotmail.com","address":"136-6488 Vel Ave","postalZip":"156088","country":"Philippines"},{"customerId":614,"customerName":"Shaine Doyle","phone":"(323) 236-1058","email":"odio.auctor@google.ca","address":"821-8566 Vivamus Rd.","postalZip":"68-46","country":"Netherlands"},{"customerId":615,"customerName":"Charissa Nelson","phone":"(101) 779-7370","email":"est.congue@protonmail.org","address":"P.O. Box 750, 4014 Sit Av.","postalZip":"91652","country":"Poland"},{"customerId":616,"customerName":"Kylan Hess","phone":"1-636-781-3576","email":"erat.vel@icloud.com","address":"5559 Est. St.","postalZip":"43166","country":"Belgium"},{"customerId":617,"customerName":"Oliver Kidd","phone":"(774) 826-1866","email":"magna.malesuada@protonmail.couk","address":"5401 Felis Ave","postalZip":"1612","country":"Turkey"},{"customerId":618,"customerName":"Reuben Weiss","phone":"(446) 844-1200","email":"donec@outlook.net","address":"P.O. Box 963, 2495 Cum Ave","postalZip":"7660","country":"New Zealand"},{"customerId":619,"customerName":"Urielle Hoover","phone":"(434) 254-0953","email":"enim.nec.tempus@yahoo.couk","address":"110-3560 Vel St.","postalZip":"3673","country":"Pakistan"},{"customerId":620,"customerName":"Herrod Salinas","phone":"(669) 771-1778","email":"iaculis.lacus.pede@protonmail.org","address":"225 Vestibulum St.","postalZip":"1120","country":"Chile"},{"customerId":621,"customerName":"Hilel Dawson","phone":"1-123-123-2258","email":"aliquam.eros@google.edu","address":"4536 Euismod Av.","postalZip":"1625 LF","country":"Germany"},{"customerId":622,"customerName":"MacKenzie Goodwin","phone":"(564) 222-3923","email":"luctus@aol.org","address":"Ap #703-4059 Sed St.","postalZip":"12821","country":"Nigeria"},{"customerId":623,"customerName":"Charles Alvarado","phone":"1-427-285-1374","email":"imperdiet.nec.leo@google.edu","address":"Ap #705-1155 Lobortis St.","postalZip":"AW89 4SR","country":"Canada"},{"customerId":624,"customerName":"Wallace Pacheco","phone":"(772) 608-4537","email":"eu.euismod.ac@protonmail.net","address":"989-328 Dictum Ave","postalZip":"SG6M 6PC","country":"India"},{"customerId":625,"customerName":"Alika Hopkins","phone":"(430) 434-4238","email":"lobortis.quis.pede@outlook.com","address":"369-2013 Vestibulum Av.","postalZip":"43017","country":"China"},{"customerId":626,"customerName":"Nigel Sanchez","phone":"(348) 575-6596","email":"aliquet.diam@yahoo.couk","address":"Ap #770-6731 Viverra. Av.","postalZip":"45454","country":"Sweden"},{"customerId":627,"customerName":"Serina Mcdaniel","phone":"(211) 826-1378","email":"non.feugiat.nec@google.ca","address":"380-2587 Tincidunt Av.","postalZip":"834268","country":"Singapore"},{"customerId":628,"customerName":"Mary Chandler","phone":"1-596-179-8727","email":"egestas.a@yahoo.net","address":"Ap #644-2525 Nunc. St.","postalZip":"57885","country":"Nigeria"},{"customerId":629,"customerName":"Brennan Orr","phone":"(897) 271-4681","email":"nam@yahoo.net","address":"4038 Ac, Ave","postalZip":"0458-4457","country":"Turkey"},{"customerId":630,"customerName":"Kaseem Bray","phone":"1-232-894-6176","email":"aenean@aol.com","address":"177-2498 Libero. Av.","postalZip":"26777-65688","country":"Chile"},{"customerId":631,"customerName":"Perry Graham","phone":"(879) 766-4653","email":"feugiat.placerat@icloud.com","address":"P.O. Box 246, 2060 Enim Road","postalZip":"744244","country":"United States"},{"customerId":632,"customerName":"Alea Valdez","phone":"1-461-710-7814","email":"diam.vel@protonmail.com","address":"110-6708 Auctor Avenue","postalZip":"183890","country":"Vietnam"},{"customerId":633,"customerName":"Regan Chan","phone":"(363) 671-1723","email":"orci@yahoo.edu","address":"P.O. Box 264, 9041 Phasellus St.","postalZip":"81183","country":"Ukraine"},{"customerId":634,"customerName":"Joseph Vaughan","phone":"1-366-717-1684","email":"tempor.arcu.vestibulum@aol.com","address":"P.O. Box 798, 7326 Nunc Street","postalZip":"20167","country":"Ukraine"},{"customerId":635,"customerName":"Amela Waller","phone":"1-840-538-2183","email":"ornare.facilisis@protonmail.net","address":"864-3029 Luctus Ave","postalZip":"31322","country":"Netherlands"},{"customerId":636,"customerName":"Quamar Frederick","phone":"(179) 524-8652","email":"cras@yahoo.ca","address":"Ap #931-4100 Nunc Ave","postalZip":"47297","country":"Belgium"},{"customerId":637,"customerName":"Burton Nixon","phone":"1-737-195-4332","email":"dui.suspendisse.ac@google.net","address":"P.O. Box 106, 3415 Nunc Street","postalZip":"18416","country":"Canada"},{"customerId":638,"customerName":"John Mcknight","phone":"1-545-501-7021","email":"aliquam.ultrices@hotmail.edu","address":"Ap #217-8190 Malesuada Road","postalZip":"744443","country":"Turkey"},{"customerId":639,"customerName":"Abigail Melton","phone":"(147) 938-2385","email":"rutrum@hotmail.ca","address":"282-5786 Senectus Rd.","postalZip":"57910","country":"Pakistan"},{"customerId":640,"customerName":"Tanner Wilcox","phone":"(798) 267-7743","email":"accumsan@outlook.net","address":"690-1638 A, Avenue","postalZip":"2488","country":"Netherlands"},{"customerId":641,"customerName":"Callum Reid","phone":"(156) 229-7883","email":"mattis.velit.justo@google.com","address":"3702 Sit Av.","postalZip":"54-28","country":"Austria"},{"customerId":642,"customerName":"Cain Galloway","phone":"(363) 249-6466","email":"id@aol.com","address":"Ap #842-8547 Aenean Street","postalZip":"58954-577","country":"United Kingdom"},{"customerId":643,"customerName":"Remedios Mason","phone":"1-774-284-8441","email":"posuere.vulputate@aol.edu","address":"458-2050 Posuere Road","postalZip":"701631","country":"New Zealand"},{"customerId":644,"customerName":"Deanna Cooper","phone":"1-782-834-4857","email":"tempor@icloud.ca","address":"464-4869 Adipiscing, Rd.","postalZip":"8445","country":"Germany"},{"customerId":645,"customerName":"Steven Woodward","phone":"1-523-213-6682","email":"eu.tellus.eu@aol.couk","address":"P.O. Box 369, 838 Eget, Ave","postalZip":"412482","country":"Norway"},{"customerId":646,"customerName":"Irma West","phone":"1-651-575-1113","email":"orci@hotmail.ca","address":"337-6977 Vivamus Rd.","postalZip":"7325","country":"South Africa"},{"customerId":647,"customerName":"Hall Jordan","phone":"1-987-762-8380","email":"praesent.interdum.ligula@yahoo.net","address":"8740 Tortor, Rd.","postalZip":"972310","country":"Chile"},{"customerId":648,"customerName":"Hammett Hoover","phone":"(543) 389-3255","email":"eros@outlook.org","address":"873-6316 Aptent St.","postalZip":"34254","country":"Russian Federation"},{"customerId":649,"customerName":"Jared Vazquez","phone":"(124) 883-2424","email":"sit@icloud.com","address":"145-4203 Ac St.","postalZip":"08126","country":"Costa Rica"},{"customerId":650,"customerName":"Stuart Solis","phone":"1-785-565-7532","email":"elit@protonmail.net","address":"Ap #773-7339 Ut Avenue","postalZip":"459651","country":"Pakistan"},{"customerId":651,"customerName":"Ezra Randall","phone":"1-286-196-2577","email":"nulla.aliquet.proin@aol.ca","address":"361-3578 Non, St.","postalZip":"3974152","country":"Indonesia"},{"customerId":652,"customerName":"Rosalyn Cline","phone":"(445) 586-6211","email":"lacus.quisque.imperdiet@protonmail.edu","address":"Ap #521-8621 Nullam St.","postalZip":"88690-78194","country":"South Africa"},{"customerId":653,"customerName":"Levi Montoya","phone":"1-388-255-0464","email":"erat.etiam@google.net","address":"416 Gravida Rd.","postalZip":"18-34","country":"Italy"},{"customerId":654,"customerName":"Carissa Simpson","phone":"1-753-856-2484","email":"consequat@outlook.com","address":"548-646 Molestie Rd.","postalZip":"3661","country":"United Kingdom"},{"customerId":655,"customerName":"Justina Spencer","phone":"1-511-332-1866","email":"hendrerit.neque.in@yahoo.com","address":"5947 Ullamcorper Ave","postalZip":"603471","country":"France"},{"customerId":656,"customerName":"Brandon Shaw","phone":"1-730-528-0576","email":"mauris@yahoo.net","address":"4160 Mattis. St.","postalZip":"47742","country":"Costa Rica"},{"customerId":657,"customerName":"Edward Vang","phone":"1-715-387-4508","email":"nonummy@protonmail.couk","address":"Ap #440-5219 Phasellus Rd.","postalZip":"A23 2QR","country":"Nigeria"},{"customerId":658,"customerName":"Aurora Grimes","phone":"(515) 242-7709","email":"proin.velit@protonmail.org","address":"Ap #597-539 Consectetuer Av.","postalZip":"22090","country":"Brazil"},{"customerId":659,"customerName":"Benedict Stewart","phone":"1-541-537-9186","email":"cubilia.curae.donec@outlook.couk","address":"371-3926 Tincidunt Rd.","postalZip":"58487","country":"Nigeria"},{"customerId":660,"customerName":"Ali Greer","phone":"1-752-415-4598","email":"cras@google.org","address":"Ap #476-6926 Sem. Rd.","postalZip":"23072","country":"Vietnam"},{"customerId":661,"customerName":"Amanda Stout","phone":"1-714-859-7121","email":"in.lorem@outlook.net","address":"158-4725 Metus Road","postalZip":"60379-412","country":"Singapore"},{"customerId":662,"customerName":"Zephania Melton","phone":"1-162-285-7203","email":"vitae@icloud.com","address":"Ap #508-2203 Dolor Av.","postalZip":"752838","country":"United States"},{"customerId":663,"customerName":"Ila Wells","phone":"(408) 892-5835","email":"augue.scelerisque.mollis@outlook.couk","address":"169-2929 Dictum Street","postalZip":"6523","country":"Ireland"},{"customerId":664,"customerName":"Zelda Osborne","phone":"1-694-428-8215","email":"pellentesque.massa@protonmail.ca","address":"957-3193 Vitae Ave","postalZip":"63838","country":"Turkey"},{"customerId":665,"customerName":"Hayfa Morse","phone":"(504) 553-1070","email":"sit@google.ca","address":"101-6493 Nisl. Rd.","postalZip":"42781","country":"South Korea"},{"customerId":666,"customerName":"Laura Pearson","phone":"1-516-646-4418","email":"leo@yahoo.org","address":"Ap #279-8832 Fusce Rd.","postalZip":"184383","country":"Russian Federation"},{"customerId":667,"customerName":"Germaine Browning","phone":"(467) 471-6433","email":"donec@aol.org","address":"9800 Dolor St.","postalZip":"345658","country":"Brazil"},{"customerId":668,"customerName":"Colleen Gay","phone":"(173) 837-5983","email":"aliquam.adipiscing.lobortis@aol.org","address":"854-9919 Diam Rd.","postalZip":"439477","country":"Singapore"},{"customerId":669,"customerName":"Jin Gomez","phone":"1-508-953-4683","email":"scelerisque.scelerisque@outlook.com","address":"Ap #492-9808 Lorem Street","postalZip":"50513","country":"Austria"},{"customerId":670,"customerName":"Beverly O'Neill","phone":"(424) 629-8591","email":"sodales.elit@icloud.edu","address":"3160 Nulla Av.","postalZip":"M08 5IQ","country":"Canada"},{"customerId":671,"customerName":"Abel Wilkerson","phone":"1-828-866-8232","email":"rhoncus.nullam@protonmail.edu","address":"918-1271 Enim, Street","postalZip":"726762","country":"Italy"},{"customerId":672,"customerName":"Serena Olson","phone":"(497) 648-1175","email":"neque.sed.sem@aol.couk","address":"Ap #599-5709 Lorem Ave","postalZip":"7852","country":"Belgium"},{"customerId":673,"customerName":"Melodie Banks","phone":"(981) 482-2153","email":"ipsum.donec@yahoo.org","address":"304-4015 Nulla Street","postalZip":"66745-17125","country":"Belgium"},{"customerId":674,"customerName":"Samuel Padilla","phone":"(631) 341-4296","email":"non.sollicitudin@aol.couk","address":"Ap #354-4137 A, Rd.","postalZip":"08422","country":"Pakistan"},{"customerId":675,"customerName":"Kiara Wilkins","phone":"(769) 278-5299","email":"mauris@icloud.couk","address":"1414 Ullamcorper Rd.","postalZip":"46725","country":"Brazil"},{"customerId":676,"customerName":"Brenna Noble","phone":"(772) 413-0763","email":"arcu.ac@protonmail.net","address":"Ap #704-1686 Eu Rd.","postalZip":"645582","country":"Costa Rica"},{"customerId":677,"customerName":"Ferris Cochran","phone":"1-252-258-7184","email":"feugiat.metus.sit@yahoo.couk","address":"Ap #608-624 Varius Ave","postalZip":"444011","country":"Netherlands"},{"customerId":678,"customerName":"Alfreda Dunlap","phone":"(872) 136-2334","email":"at.pretium@hotmail.couk","address":"Ap #172-6043 Nunc Avenue","postalZip":"697784","country":"Singapore"},{"customerId":679,"customerName":"Ishmael Huffman","phone":"1-826-514-6037","email":"ornare.in@google.ca","address":"Ap #708-1539 Mi St.","postalZip":"2417-5672","country":"Philippines"},{"customerId":680,"customerName":"Fredericka Rojas","phone":"1-922-673-8608","email":"et@icloud.edu","address":"Ap #991-728 Primis Rd.","postalZip":"16231","country":"Russian Federation"},{"customerId":681,"customerName":"Emmanuel Bray","phone":"(429) 581-3113","email":"aliquam.gravida@outlook.net","address":"P.O. Box 617, 9505 Pellentesque Rd.","postalZip":"6622","country":"Italy"},{"customerId":682,"customerName":"Gage Holland","phone":"(275) 344-5235","email":"ac.ipsum@google.net","address":"3807 Porttitor St.","postalZip":"645584","country":"France"},{"customerId":683,"customerName":"Kellie Fleming","phone":"(543) 716-3161","email":"eu.erat@icloud.ca","address":"250-9433 Conubia Street","postalZip":"53L 5N9","country":"Belgium"},{"customerId":684,"customerName":"Dennis Stephens","phone":"1-665-763-3476","email":"pede.cras@yahoo.ca","address":"P.O. Box 797, 5672 Dolor. Rd.","postalZip":"65441","country":"Sweden"},{"customerId":685,"customerName":"Graiden Kerr","phone":"(806) 625-2677","email":"sed@aol.couk","address":"993-1068 Vulputate Rd.","postalZip":"46138","country":"Chile"},{"customerId":686,"customerName":"Chancellor Cooper","phone":"(673) 268-1631","email":"gravida.molestie.arcu@protonmail.edu","address":"Ap #284-6591 Eu, Street","postalZip":"386178","country":"Australia"},{"customerId":687,"customerName":"Kaitlin Hogan","phone":"(316) 511-2546","email":"turpis.egestas@yahoo.couk","address":"P.O. Box 720, 7028 Fermentum Av.","postalZip":"41673","country":"Australia"},{"customerId":688,"customerName":"Bianca Andrews","phone":"(359) 741-5673","email":"non.ante@protonmail.com","address":"4456 Odio. Rd.","postalZip":"M3T 0P7","country":"Nigeria"},{"customerId":689,"customerName":"Daria Lewis","phone":"(575) 419-6548","email":"urna.vivamus.molestie@yahoo.org","address":"105-7264 Erat Street","postalZip":"2825 XE","country":"New Zealand"},{"customerId":690,"customerName":"Ivan Long","phone":"(164) 596-2633","email":"ac@icloud.net","address":"484 Facilisis, Road","postalZip":"3575","country":"Peru"},{"customerId":691,"customerName":"Chiquita Bird","phone":"1-324-512-8855","email":"fusce.dolor@hotmail.ca","address":"P.O. Box 348, 4763 Velit Rd.","postalZip":"27917","country":"Chile"},{"customerId":692,"customerName":"Illiana Schultz","phone":"(440) 283-9144","email":"libero@yahoo.edu","address":"Ap #975-2907 Eu Street","postalZip":"43936","country":"Pakistan"},{"customerId":693,"customerName":"Halee Vazquez","phone":"1-882-448-9353","email":"nulla.facilisi@hotmail.couk","address":"Ap #164-3419 Risus. Rd.","postalZip":"4594","country":"Spain"},{"customerId":694,"customerName":"Jamalia Salas","phone":"1-146-328-6621","email":"ultricies.ligula.nullam@protonmail.edu","address":"6789 Lacus Av.","postalZip":"21204","country":"Colombia"},{"customerId":695,"customerName":"Gavin Russell","phone":"1-323-845-2223","email":"elementum.at.egestas@outlook.ca","address":"Ap #416-4357 Odio. Ave","postalZip":"34376","country":"Sweden"},{"customerId":696,"customerName":"Yvette Nieves","phone":"(336) 891-7526","email":"varius.ultrices@icloud.couk","address":"3116 Iaculis Rd.","postalZip":"11213","country":"Austria"},{"customerId":697,"customerName":"Fatima Tillman","phone":"(357) 418-1563","email":"donec@yahoo.org","address":"P.O. Box 975, 5025 Ligula St.","postalZip":"7337 BA","country":"Chile"},{"customerId":698,"customerName":"Zorita Robbins","phone":"1-976-388-2265","email":"et.rutrum@protonmail.ca","address":"Ap #509-2128 Urna. St.","postalZip":"7164","country":"Singapore"},{"customerId":699,"customerName":"Maile Holman","phone":"1-254-562-4216","email":"semper.dui.lectus@aol.couk","address":"2754 Ac, St.","postalZip":"15478","country":"Colombia"},{"customerId":700,"customerName":"Henry Cotton","phone":"1-734-963-6549","email":"sit.amet@outlook.net","address":"Ap #741-4742 Etiam Street","postalZip":"CT9 9FZ","country":"Ukraine"},{"customerId":701,"customerName":"Bryar Leon","phone":"1-729-516-3877","email":"commodo.tincidunt.nibh@google.ca","address":"Ap #519-5538 Aliquam Avenue","postalZip":"T3X 8B3","country":"Russian Federation"},{"customerId":702,"customerName":"Chelsea Holmes","phone":"(202) 348-1646","email":"ultrices@hotmail.edu","address":"P.O. Box 651, 8269 Mauris Av.","postalZip":"52452","country":"South Korea"},{"customerId":703,"customerName":"Basil Haney","phone":"(591) 637-0485","email":"sodales@outlook.org","address":"646-6912 Semper, Ave","postalZip":"4352","country":"Peru"},{"customerId":704,"customerName":"Cassidy Farley","phone":"1-814-856-3941","email":"sed.facilisis@icloud.edu","address":"1655 Pellentesque Rd.","postalZip":"6372","country":"United Kingdom"},{"customerId":705,"customerName":"Emery Good","phone":"(434) 474-4664","email":"auctor@hotmail.org","address":"Ap #777-8861 Rhoncus. Avenue","postalZip":"202163","country":"Chile"},{"customerId":706,"customerName":"Shelly Bruce","phone":"1-628-875-1071","email":"magna.et.ipsum@protonmail.couk","address":"Ap #111-4955 Mauris Rd.","postalZip":"80444","country":"Peru"},{"customerId":707,"customerName":"Colby Kelley","phone":"(680) 511-1099","email":"urna.ut@google.ca","address":"P.O. Box 717, 1718 Sed Rd.","postalZip":"570435","country":"Mexico"},{"customerId":708,"customerName":"Brendan Cobb","phone":"(870) 875-3861","email":"felis.donec@aol.ca","address":"Ap #885-3934 Inceptos St.","postalZip":"7686","country":"Ireland"},{"customerId":709,"customerName":"Forrest Espinoza","phone":"1-504-595-2337","email":"augue.ut.lacus@protonmail.couk","address":"3498 Ullamcorper St.","postalZip":"703717","country":"United Kingdom"},{"customerId":710,"customerName":"Tad Malone","phone":"(361) 344-7431","email":"adipiscing@icloud.org","address":"895-742 At Street","postalZip":"438731","country":"Peru"},{"customerId":711,"customerName":"Astra Newman","phone":"(572) 140-0633","email":"imperdiet@aol.com","address":"903-9715 Lacus St.","postalZip":"69074","country":"Indonesia"},{"customerId":712,"customerName":"Patrick Watkins","phone":"1-458-248-9709","email":"eget.laoreet.posuere@protonmail.edu","address":"Ap #896-231 Etiam Rd.","postalZip":"25365","country":"South Africa"},{"customerId":713,"customerName":"Isabelle Hutchinson","phone":"1-561-668-9303","email":"elit.etiam@yahoo.net","address":"P.O. Box 487, 8571 Amet St.","postalZip":"747278","country":"Philippines"},{"customerId":714,"customerName":"Jordan Wilder","phone":"(851) 986-1221","email":"donec.vitae@icloud.edu","address":"7147 Sollicitudin Rd.","postalZip":"16816","country":"Germany"},{"customerId":715,"customerName":"Fay Phelps","phone":"(544) 381-8265","email":"interdum.ligula.eu@icloud.org","address":"224-5460 Ante Rd.","postalZip":"766345","country":"Ukraine"},{"customerId":716,"customerName":"Jenna Roy","phone":"(815) 281-8427","email":"elementum.at.egestas@google.edu","address":"Ap #386-4543 Sollicitudin Street","postalZip":"56322","country":"Philippines"},{"customerId":717,"customerName":"Felicia Waller","phone":"1-358-255-0045","email":"non.lobortis.quis@outlook.couk","address":"9807 Velit Av.","postalZip":"168116","country":"United Kingdom"},{"customerId":718,"customerName":"Alan Keith","phone":"(193) 661-4113","email":"et@protonmail.couk","address":"Ap #894-6893 Velit Ave","postalZip":"7515","country":"Italy"},{"customerId":719,"customerName":"Kenneth Mcpherson","phone":"1-742-284-2165","email":"leo@google.net","address":"Ap #416-2641 Sed Rd.","postalZip":"8513","country":"South Africa"},{"customerId":720,"customerName":"Anthony Le","phone":"(251) 880-6573","email":"aliquam@aol.net","address":"728-9448 Ornare Avenue","postalZip":"8771","country":"Poland"},{"customerId":721,"customerName":"Ginger Lawson","phone":"(323) 888-3662","email":"interdum@yahoo.couk","address":"639-3476 Faucibus. Ave","postalZip":"9727","country":"Costa Rica"},{"customerId":722,"customerName":"Jamal Suarez","phone":"1-548-947-7622","email":"fames@icloud.edu","address":"P.O. Box 583, 2803 Posuere Street","postalZip":"23725","country":"India"},{"customerId":723,"customerName":"Wylie Stokes","phone":"(351) 661-8245","email":"et.libero.proin@aol.edu","address":"154-4462 Egestas Ave","postalZip":"36-24","country":"India"},{"customerId":724,"customerName":"Bernard Harris","phone":"1-843-327-6984","email":"molestie.orci@icloud.com","address":"P.O. Box 336, 2665 At Rd.","postalZip":"16885-551","country":"United Kingdom"},{"customerId":725,"customerName":"Ronan Arnold","phone":"1-537-142-6668","email":"vestibulum.nec@protonmail.ca","address":"149-5046 Sed Ave","postalZip":"582183","country":"Pakistan"},{"customerId":726,"customerName":"Jeanette Stanley","phone":"1-812-894-5900","email":"facilisis.lorem.tristique@outlook.org","address":"683-4049 Phasellus Rd.","postalZip":"07715","country":"Netherlands"},{"customerId":727,"customerName":"Shana Merritt","phone":"1-543-784-1204","email":"ullamcorper.nisl@aol.com","address":"539-6837 Non, Rd.","postalZip":"362432","country":"Turkey"},{"customerId":728,"customerName":"Xavier Fuentes","phone":"(313) 657-6636","email":"eros@protonmail.ca","address":"211-6474 At Road","postalZip":"4521","country":"Ukraine"},{"customerId":729,"customerName":"Eleanor Hayden","phone":"1-983-243-3953","email":"nec@yahoo.org","address":"P.O. Box 382, 8343 Ac Avenue","postalZip":"7403","country":"Singapore"},{"customerId":730,"customerName":"Rafael Roach","phone":"1-101-312-1215","email":"ut.semper.pretium@outlook.org","address":"9218 Tellus Road","postalZip":"386632","country":"Singapore"},{"customerId":731,"customerName":"Cecilia Hester","phone":"(813) 702-3565","email":"lorem.eget@google.org","address":"Ap #655-5528 Imperdiet Ave","postalZip":"84851","country":"Netherlands"},{"customerId":732,"customerName":"Uriah Mcpherson","phone":"1-656-842-2712","email":"tincidunt.nibh.phasellus@hotmail.com","address":"804-2950 Tellus. Road","postalZip":"28588","country":"Ukraine"},{"customerId":733,"customerName":"Beck Walton","phone":"1-457-558-9798","email":"fermentum@google.com","address":"Ap #193-3401 Bibendum Street","postalZip":"51J 8H8","country":"Pakistan"},{"customerId":734,"customerName":"Yetta Lowery","phone":"(117) 748-0961","email":"erat.sed.nunc@outlook.couk","address":"7459 Vivamus Rd.","postalZip":"1703-2538","country":"Belgium"},{"customerId":735,"customerName":"Cleo Guerrero","phone":"(253) 193-4524","email":"pede.praesent.eu@icloud.couk","address":"266-8321 Mauris Road","postalZip":"85055","country":"Costa Rica"},{"customerId":736,"customerName":"Cruz Aguilar","phone":"1-516-686-9331","email":"in.lobortis@aol.couk","address":"282-3045 Tristique St.","postalZip":"446632","country":"Netherlands"},{"customerId":737,"customerName":"Perry Morales","phone":"1-814-853-8324","email":"molestie.sodales.mauris@yahoo.edu","address":"Ap #865-6691 Sollicitudin Rd.","postalZip":"8718","country":"United States"},{"customerId":738,"customerName":"Velma Weeks","phone":"(511) 467-9457","email":"purus.accumsan@google.org","address":"Ap #794-128 Ullamcorper Road","postalZip":"622268","country":"Ukraine"},{"customerId":739,"customerName":"Emily Byers","phone":"(243) 570-2798","email":"scelerisque.neque@protonmail.org","address":"9669 Cursus St.","postalZip":"3655 XW","country":"Philippines"},{"customerId":740,"customerName":"Jasmine Moss","phone":"(481) 349-4651","email":"nibh.aliquam@protonmail.org","address":"684-8132 Fringilla Rd.","postalZip":"25798","country":"Costa Rica"},{"customerId":741,"customerName":"Galvin Maynard","phone":"(845) 816-4842","email":"vitae.risus@outlook.com","address":"8005 Bibendum Street","postalZip":"16562","country":"Turkey"},{"customerId":742,"customerName":"Lareina Ross","phone":"(460) 444-2286","email":"velit.quisque@aol.ca","address":"790-7763 Vulputate Rd.","postalZip":"26927","country":"Nigeria"},{"customerId":743,"customerName":"Yen Hayes","phone":"(807) 198-9279","email":"in.lobortis.tellus@aol.couk","address":"Ap #355-191 Velit. St.","postalZip":"802563","country":"South Korea"},{"customerId":744,"customerName":"Basil Green","phone":"1-223-457-6313","email":"ac.mattis@yahoo.edu","address":"Ap #754-3145 Tristique Av.","postalZip":"5171","country":"Netherlands"},{"customerId":745,"customerName":"Madaline Boyle","phone":"1-154-476-4752","email":"nunc.id.enim@hotmail.net","address":"698-9976 Pharetra Rd.","postalZip":"841437","country":"Spain"},{"customerId":746,"customerName":"Melanie Good","phone":"1-778-867-2546","email":"mauris@outlook.net","address":"P.O. Box 401, 3994 Vivamus Av.","postalZip":"37996","country":"Netherlands"},{"customerId":747,"customerName":"Xena Mills","phone":"1-853-852-6659","email":"phasellus.dolor@yahoo.net","address":"981-5350 Justo Street","postalZip":"46145","country":"Netherlands"},{"customerId":748,"customerName":"Victor Campos","phone":"1-246-872-7204","email":"dolor@yahoo.edu","address":"P.O. Box 945, 8808 Nibh Road","postalZip":"8661","country":"New Zealand"},{"customerId":749,"customerName":"Jelani Kaufman","phone":"(773) 553-6441","email":"justo.nec@yahoo.ca","address":"168-3069 Gravida Avenue","postalZip":"43864-439","country":"Ukraine"},{"customerId":750,"customerName":"Whoopi Ratliff","phone":"(556) 928-7102","email":"adipiscing.fringilla.porttitor@hotmail.couk","address":"Ap #828-8835 At Av.","postalZip":"83531","country":"Vietnam"},{"customerId":751,"customerName":"Basia Finch","phone":"1-123-511-6769","email":"tortor@outlook.couk","address":"1308 Tincidunt Rd.","postalZip":"54632","country":"Norway"},{"customerId":752,"customerName":"Gavin Elliott","phone":"1-631-521-2887","email":"sapien.molestie@outlook.org","address":"Ap #102-9337 Massa. Ave","postalZip":"3315","country":"Norway"},{"customerId":753,"customerName":"Jayme William","phone":"1-532-882-9532","email":"vitae@yahoo.com","address":"Ap #185-1545 Orci Rd.","postalZip":"671325","country":"Germany"},{"customerId":754,"customerName":"Patrick Abbott","phone":"(415) 867-6685","email":"massa.rutrum@icloud.edu","address":"736-9586 Lacinia Rd.","postalZip":"T5M 5Z4","country":"Canada"},{"customerId":755,"customerName":"Marvin Shields","phone":"1-826-727-7976","email":"libero.mauris@aol.ca","address":"6858 Curabitur St.","postalZip":"945894","country":"Ukraine"},{"customerId":756,"customerName":"Yael Bauer","phone":"(558) 586-8252","email":"nec.ante@yahoo.edu","address":"6253 Blandit Ave","postalZip":"60787","country":"South Korea"},{"customerId":757,"customerName":"Price Hansen","phone":"(591) 797-0973","email":"porttitor@icloud.ca","address":"Ap #519-1535 Sapien, St.","postalZip":"37692","country":"United Kingdom"},{"customerId":758,"customerName":"Jameson Harris","phone":"1-956-770-7240","email":"consectetuer.cursus.et@hotmail.edu","address":"Ap #610-3611 Ornare, St.","postalZip":"668360","country":"Australia"},{"customerId":759,"customerName":"Isaac Beach","phone":"(403) 241-7154","email":"lectus.pede@icloud.ca","address":"254-1041 Ligula Road","postalZip":"678392","country":"Pakistan"},{"customerId":760,"customerName":"Jada Larsen","phone":"(448) 672-7335","email":"a@aol.couk","address":"8908 Tellus St.","postalZip":"75833","country":"Mexico"},{"customerId":761,"customerName":"Kenneth Rowe","phone":"1-842-206-3504","email":"auctor.odio@google.ca","address":"774-7848 Dolor Street","postalZip":"41589","country":"Singapore"},{"customerId":762,"customerName":"Inez Wagner","phone":"(158) 587-2881","email":"augue@icloud.net","address":"6221 Per St.","postalZip":"732338","country":"China"},{"customerId":763,"customerName":"Ann Townsend","phone":"1-617-277-5296","email":"justo.eu@aol.net","address":"764-8751 Suspendisse Av.","postalZip":"27-17","country":"Italy"},{"customerId":764,"customerName":"Warren Mccall","phone":"1-558-855-1859","email":"nec.ante@outlook.com","address":"4006 Amet, Rd.","postalZip":"7661","country":"Indonesia"},{"customerId":765,"customerName":"Gillian Caldwell","phone":"(343) 379-1567","email":"aliquam.nisl@outlook.edu","address":"439-5857 Velit. Rd.","postalZip":"65120-808","country":"Philippines"},{"customerId":766,"customerName":"Philip Mcneil","phone":"(118) 138-6654","email":"pharetra.quisque.ac@icloud.ca","address":"126-9845 Dolor. Street","postalZip":"5922","country":"Sweden"},{"customerId":767,"customerName":"Carla Griffith","phone":"(935) 961-6277","email":"aliquam.iaculis.lacus@protonmail.edu","address":"3978 Velit St.","postalZip":"1869-7334","country":"United States"},{"customerId":768,"customerName":"Althea Turner","phone":"(433) 381-4446","email":"per.conubia.nostra@google.couk","address":"330-4113 Et Ave","postalZip":"638243","country":"Poland"},{"customerId":769,"customerName":"Quinn Sandoval","phone":"(721) 758-4826","email":"enim.commodo.hendrerit@yahoo.org","address":"Ap #363-3098 Ornare Road","postalZip":"y3S 6L5","country":"Costa Rica"},{"customerId":770,"customerName":"Zeph Gay","phone":"1-999-235-9676","email":"nulla.eu@aol.ca","address":"483-1542 Mauris Street","postalZip":"VG14 3WR","country":"Nigeria"},{"customerId":771,"customerName":"Lester Herring","phone":"1-735-246-5755","email":"erat.in@google.org","address":"Ap #939-6519 Lorem. Road","postalZip":"366614","country":"Spain"},{"customerId":772,"customerName":"Gareth Huff","phone":"1-356-343-4077","email":"eleifend.vitae@aol.net","address":"324-8669 Cras Rd.","postalZip":"346843","country":"India"},{"customerId":773,"customerName":"Sigourney Pruitt","phone":"1-676-416-8753","email":"ullamcorper.viverra.maecenas@icloud.org","address":"Ap #480-7841 Ullamcorper Av.","postalZip":"573673","country":"China"},{"customerId":774,"customerName":"Joan Medina","phone":"1-427-641-3357","email":"nec.imperdiet@yahoo.edu","address":"Ap #312-9806 Fringilla St.","postalZip":"4473 BC","country":"Norway"},{"customerId":775,"customerName":"Quinlan Espinoza","phone":"1-497-643-1247","email":"ultricies.sem@protonmail.org","address":"Ap #716-8093 Mus. Avenue","postalZip":"02-223","country":"Vietnam"},{"customerId":776,"customerName":"Cooper Bernard","phone":"1-742-847-2173","email":"tristique.pharetra@protonmail.com","address":"Ap #612-624 Arcu Road","postalZip":"B3J 1M4","country":"Ukraine"},{"customerId":777,"customerName":"Zephr Frost","phone":"(598) 227-1472","email":"porttitor.interdum@yahoo.edu","address":"974-1307 Vitae Ave","postalZip":"528762","country":"Singapore"},{"customerId":778,"customerName":"Reese Battle","phone":"1-732-761-0485","email":"tristique@yahoo.edu","address":"Ap #569-9593 Sodales St.","postalZip":"77-53","country":"Canada"},{"customerId":779,"customerName":"Sydney Harmon","phone":"1-471-558-5615","email":"duis.ac@icloud.ca","address":"Ap #585-7272 Rutrum Av.","postalZip":"400134","country":"Italy"},{"customerId":780,"customerName":"Meghan Farrell","phone":"1-267-536-8443","email":"dictum@protonmail.couk","address":"267-778 Neque. Avenue","postalZip":"70162","country":"Indonesia"},{"customerId":781,"customerName":"Plato Guthrie","phone":"1-228-530-2717","email":"diam@icloud.edu","address":"237-8041 Lacus. Avenue","postalZip":"416567","country":"Germany"},{"customerId":782,"customerName":"Philip Slater","phone":"1-657-181-5496","email":"auctor.non@aol.com","address":"865-9756 Ut St.","postalZip":"487316","country":"Spain"},{"customerId":783,"customerName":"Lillian Wells","phone":"1-583-520-3487","email":"risus.donec@outlook.com","address":"589-2712 Odio. Rd.","postalZip":"4335 UU","country":"South Africa"},{"customerId":784,"customerName":"Kalia Terry","phone":"(663) 776-7659","email":"etiam@google.net","address":"P.O. Box 859, 7194 Duis Ave","postalZip":"345505","country":"Poland"},{"customerId":785,"customerName":"Darius Bridges","phone":"1-493-751-5738","email":"cursus@protonmail.com","address":"800-8647 Sit Street","postalZip":"18323","country":"Brazil"},{"customerId":786,"customerName":"Piper Dunlap","phone":"1-222-965-7102","email":"consectetuer.cursus@protonmail.com","address":"380-3734 Mollis. Av.","postalZip":"12882","country":"Norway"},{"customerId":787,"customerName":"Slade Rocha","phone":"1-268-556-1838","email":"pharetra.quisque@hotmail.couk","address":"4235 Dis Ave","postalZip":"1159","country":"Singapore"},{"customerId":788,"customerName":"Priscilla Mcguire","phone":"1-542-281-8822","email":"arcu.sed@outlook.org","address":"431-2224 Ac Avenue","postalZip":"07202","country":"France"},{"customerId":789,"customerName":"Flavia Gamble","phone":"(626) 374-7779","email":"a.malesuada.id@yahoo.com","address":"267-3312 Id, Street","postalZip":"R5T 7H3","country":"Peru"},{"customerId":790,"customerName":"Scarlett Baird","phone":"(447) 503-0226","email":"iaculis.lacus@google.net","address":"911-7429 At, Ave","postalZip":"51E 1T3","country":"China"},{"customerId":791,"customerName":"Keegan Daugherty","phone":"1-116-624-7627","email":"et.libero@outlook.com","address":"P.O. Box 404, 5035 Lacus, Rd.","postalZip":"843551","country":"Norway"},{"customerId":792,"customerName":"Hiram Chen","phone":"(871) 345-8822","email":"consequat@protonmail.net","address":"625-6632 Vel Avenue","postalZip":"32159","country":"Turkey"},{"customerId":793,"customerName":"Branden Rodriquez","phone":"(664) 889-1642","email":"aliquam.arcu@outlook.ca","address":"320-2559 Nibh Rd.","postalZip":"8232","country":"United Kingdom"},{"customerId":794,"customerName":"Cassidy Peters","phone":"1-767-872-5576","email":"sem.nulla@outlook.couk","address":"Ap #116-8989 Lectus St.","postalZip":"924516","country":"China"},{"customerId":795,"customerName":"Ila Wall","phone":"1-601-548-5284","email":"consequat.lectus@protonmail.com","address":"Ap #976-3079 Lorem Rd.","postalZip":"339167","country":"Turkey"},{"customerId":796,"customerName":"Kenneth Newman","phone":"1-177-673-9169","email":"eleifend@icloud.couk","address":"P.O. Box 466, 8754 Ullamcorper, Street","postalZip":"665660","country":"Nigeria"},{"customerId":797,"customerName":"Vivian Barrett","phone":"(480) 851-0581","email":"massa.integer@yahoo.net","address":"300-8590 Mollis. Rd.","postalZip":"26586","country":"Ireland"},{"customerId":798,"customerName":"Henry Barlow","phone":"1-245-974-2855","email":"vulputate@icloud.com","address":"7076 Egestas St.","postalZip":"6561-2875","country":"Netherlands"},{"customerId":799,"customerName":"Vivien House","phone":"1-852-433-5728","email":"nunc.lectus.pede@aol.couk","address":"Ap #468-6391 Parturient Road","postalZip":"254680","country":"Ireland"},{"customerId":800,"customerName":"Roth Burt","phone":"1-771-306-5541","email":"lacus.etiam.bibendum@outlook.com","address":"P.O. Box 817, 1806 Eros St.","postalZip":"88247","country":"Russian Federation"},{"customerId":801,"customerName":"Dylan Long","phone":"(443) 982-3151","email":"ut.nulla@aol.com","address":"7136 Non, Avenue","postalZip":"12618","country":"South Africa"},{"customerId":802,"customerName":"Basil Owen","phone":"(153) 354-8786","email":"elementum.dui@outlook.couk","address":"Ap #394-7158 Libero Avenue","postalZip":"184276","country":"United Kingdom"},{"customerId":803,"customerName":"Nerea Sparks","phone":"1-166-874-2120","email":"mauris@protonmail.com","address":"Ap #316-199 Risus St.","postalZip":"678162","country":"Norway"},{"customerId":804,"customerName":"Jack Powers","phone":"1-829-458-5289","email":"accumsan.interdum@icloud.couk","address":"4061 Amet Av.","postalZip":"85876","country":"Mexico"},{"customerId":805,"customerName":"Haley Garcia","phone":"1-967-828-8134","email":"cras.vulputate.velit@icloud.com","address":"Ap #795-2694 Blandit. Street","postalZip":"70786","country":"Brazil"},{"customerId":806,"customerName":"Knox Madden","phone":"(451) 576-9610","email":"varius@protonmail.org","address":"P.O. Box 852, 9518 Maecenas Rd.","postalZip":"6897","country":"Chile"},{"customerId":807,"customerName":"Sacha Morin","phone":"1-462-304-0622","email":"vehicula.pellentesque.tincidunt@aol.edu","address":"9224 Non, Ave","postalZip":"54356","country":"Brazil"},{"customerId":808,"customerName":"Quon Short","phone":"1-777-131-3837","email":"parturient.montes@protonmail.edu","address":"Ap #175-5392 Et, Avenue","postalZip":"311598","country":"Turkey"},{"customerId":809,"customerName":"Imani Giles","phone":"1-544-870-1471","email":"viverra.donec@protonmail.edu","address":"241-4421 Mauris St.","postalZip":"626817","country":"Pakistan"},{"customerId":810,"customerName":"Aurelia Foreman","phone":"1-315-273-2481","email":"elit.sed.consequat@hotmail.ca","address":"848-6809 Primis Rd.","postalZip":"897573","country":"Nigeria"},{"customerId":811,"customerName":"Axel Brooks","phone":"(256) 312-8477","email":"fringilla.mi.lacinia@outlook.org","address":"611-1564 Aliquam Rd.","postalZip":"15461","country":"Pakistan"},{"customerId":812,"customerName":"Alexander Snyder","phone":"(131) 112-1368","email":"aliquet.lobortis.nisi@yahoo.edu","address":"P.O. Box 903, 4493 Auctor Rd.","postalZip":"381361","country":"Netherlands"},{"customerId":813,"customerName":"Priscilla Meadows","phone":"(627) 987-1735","email":"in.cursus@yahoo.org","address":"Ap #698-7856 Ligula Road","postalZip":"661825","country":"Indonesia"},{"customerId":814,"customerName":"Mohammad Anthony","phone":"(167) 228-0486","email":"nec.ante.blandit@icloud.couk","address":"Ap #822-8154 Suspendisse Av.","postalZip":"43572-322","country":"Pakistan"},{"customerId":815,"customerName":"Illana Craig","phone":"(798) 435-2076","email":"posuere.vulputate@hotmail.ca","address":"1300 Eleifend, Street","postalZip":"5122-1837","country":"Brazil"},{"customerId":816,"customerName":"Pamela Haney","phone":"1-247-228-3672","email":"montes@outlook.org","address":"260-6269 Sagittis Rd.","postalZip":"952330","country":"Ireland"},{"customerId":817,"customerName":"Lucas Sargent","phone":"(810) 477-6551","email":"tincidunt.nunc@outlook.com","address":"4814 Amet Av.","postalZip":"31234","country":"Peru"},{"customerId":818,"customerName":"Benedict Carver","phone":"(724) 912-8252","email":"ut.semper.pretium@aol.edu","address":"763-1191 Lectus Road","postalZip":"7822","country":"Nigeria"},{"customerId":819,"customerName":"Giacomo Stark","phone":"(312) 765-7184","email":"lorem.semper@protonmail.edu","address":"Ap #453-9694 Placerat, Road","postalZip":"55-36","country":"New Zealand"},{"customerId":820,"customerName":"Emerson Herring","phone":"(778) 540-8339","email":"ultrices.a@hotmail.couk","address":"9245 Massa. St.","postalZip":"84780","country":"Canada"},{"customerId":821,"customerName":"Claudia Hinton","phone":"(549) 452-8272","email":"eget.nisi@hotmail.couk","address":"395-4879 Posuere Av.","postalZip":"74738-315","country":"Netherlands"},{"customerId":822,"customerName":"Desirae Vasquez","phone":"(208) 953-6477","email":"nec.tellus@yahoo.couk","address":"Ap #708-215 Pede. Road","postalZip":"3331","country":"Ireland"},{"customerId":823,"customerName":"Stuart Lewis","phone":"1-919-738-2208","email":"elementum@protonmail.net","address":"P.O. Box 486, 2329 Dictum St.","postalZip":"461808","country":"Mexico"},{"customerId":824,"customerName":"Katell Velasquez","phone":"1-942-515-6421","email":"cum.sociis@yahoo.org","address":"809-6388 Dolor. Ave","postalZip":"3525 QV","country":"Costa Rica"},{"customerId":825,"customerName":"Bianca Riley","phone":"1-961-928-5087","email":"facilisis.suspendisse@aol.couk","address":"2351 Nullam St.","postalZip":"266575","country":"Canada"},{"customerId":826,"customerName":"Sage Knight","phone":"1-458-540-4775","email":"porttitor@icloud.edu","address":"Ap #680-5468 Consequat St.","postalZip":"8227","country":"Netherlands"},{"customerId":827,"customerName":"Ocean Long","phone":"(424) 378-6757","email":"sem.molestie@hotmail.org","address":"P.O. Box 161, 1610 Donec Av.","postalZip":"542154","country":"China"},{"customerId":828,"customerName":"Cassidy Baird","phone":"(185) 545-0611","email":"nibh.sit.amet@outlook.net","address":"Ap #531-3794 Vivamus Ave","postalZip":"14518","country":"Ireland"},{"customerId":829,"customerName":"Sheila Clark","phone":"1-315-340-3827","email":"quisque.nonummy@protonmail.edu","address":"891-7010 Fermentum St.","postalZip":"5458","country":"South Korea"},{"customerId":830,"customerName":"Merrill Mendoza","phone":"1-796-387-2608","email":"non.sapien.molestie@google.org","address":"905-4272 Odio Avenue","postalZip":"281587","country":"New Zealand"},{"customerId":831,"customerName":"Alexis Rogers","phone":"(614) 746-0825","email":"sagittis.semper@google.edu","address":"9027 Nunc Avenue","postalZip":"53731","country":"India"},{"customerId":832,"customerName":"Jerome Dudley","phone":"1-822-174-5274","email":"quis@aol.org","address":"Ap #370-3923 Arcu. Av.","postalZip":"6170","country":"South Korea"},{"customerId":833,"customerName":"Felix Ayers","phone":"1-760-107-8310","email":"lorem.ipsum@outlook.ca","address":"719-7108 Nunc Ave","postalZip":"5464","country":"Canada"},{"customerId":834,"customerName":"Emerson Hartman","phone":"(856) 922-7278","email":"tincidunt.dui@hotmail.edu","address":"3703 Nec, Rd.","postalZip":"625522","country":"United States"},{"customerId":835,"customerName":"Evan Decker","phone":"1-593-244-9271","email":"adipiscing.fringilla@protonmail.net","address":"889-4084 Donec St.","postalZip":"39112","country":"Pakistan"},{"customerId":836,"customerName":"Cecilia Hickman","phone":"1-974-482-7515","email":"arcu.ac@protonmail.couk","address":"Ap #130-7762 Orci Rd.","postalZip":"36396","country":"South Africa"},{"customerId":837,"customerName":"Brynn Lawson","phone":"1-247-415-5994","email":"ornare.egestas@google.ca","address":"375-6552 Lorem Rd.","postalZip":"52726-88363","country":"Sweden"},{"customerId":838,"customerName":"Debra Lewis","phone":"1-641-381-8565","email":"libero.et.tristique@yahoo.net","address":"628-1249 Dolor Avenue","postalZip":"115819","country":"Norway"},{"customerId":839,"customerName":"Samuel Holt","phone":"(512) 274-3759","email":"vel@protonmail.com","address":"3363 Amet Rd.","postalZip":"5440","country":"Philippines"},{"customerId":840,"customerName":"Moana Mcintosh","phone":"(314) 630-6702","email":"duis.gravida.praesent@yahoo.net","address":"8414 Convallis St.","postalZip":"50119","country":"Vietnam"},{"customerId":841,"customerName":"Kerry Walls","phone":"(555) 885-6918","email":"magna.ut@hotmail.net","address":"703-5970 Tristique Avenue","postalZip":"JS8 8ZE","country":"Philippines"},{"customerId":842,"customerName":"McKenzie Castillo","phone":"(262) 547-3385","email":"ac.arcu.nunc@hotmail.couk","address":"Ap #616-9585 Varius. Road","postalZip":"47163","country":"Chile"},{"customerId":843,"customerName":"Zia Marshall","phone":"(830) 836-2689","email":"enim@aol.ca","address":"Ap #524-9069 Nulla Rd.","postalZip":"327185","country":"New Zealand"},{"customerId":844,"customerName":"Daquan Conrad","phone":"1-838-536-5118","email":"urna@google.org","address":"4082 Metus Ave","postalZip":"46445-67493","country":"Peru"},{"customerId":845,"customerName":"Warren Tyler","phone":"1-453-673-7100","email":"elit.curabitur@icloud.com","address":"652-3013 At, Rd.","postalZip":"34141","country":"India"},{"customerId":846,"customerName":"Nero Allen","phone":"(670) 446-3652","email":"id@yahoo.ca","address":"101-7152 Eu, Av.","postalZip":"3302","country":"France"},{"customerId":847,"customerName":"Renee Avila","phone":"1-806-978-6067","email":"sapien.molestie@icloud.ca","address":"834-9784 Dis Rd.","postalZip":"89711-812","country":"Costa Rica"},{"customerId":848,"customerName":"Kylan Warren","phone":"1-231-558-4253","email":"fusce@protonmail.couk","address":"1007 Velit. Av.","postalZip":"51206","country":"Norway"},{"customerId":849,"customerName":"Chelsea Best","phone":"(665) 586-1871","email":"neque@google.couk","address":"674-5498 At St.","postalZip":"2559-3940","country":"Singapore"},{"customerId":850,"customerName":"Juliet Hansen","phone":"1-751-353-7508","email":"egestas.a@aol.net","address":"908-9856 Laoreet Ave","postalZip":"437630","country":"India"},{"customerId":851,"customerName":"Emerson Flores","phone":"(842) 341-9728","email":"bibendum.sed@icloud.net","address":"409-6884 Ipsum Road","postalZip":"6975-8454","country":"Pakistan"},{"customerId":852,"customerName":"Jasmine Conway","phone":"(830) 723-0622","email":"pellentesque@google.edu","address":"P.O. Box 238, 1636 Ridiculus Rd.","postalZip":"06889","country":"South Korea"},{"customerId":853,"customerName":"Kim Strong","phone":"(255) 458-6411","email":"vitae.sodales@yahoo.com","address":"6054 Integer Rd.","postalZip":"8456-0817","country":"India"},{"customerId":854,"customerName":"Josiah Sanders","phone":"(234) 920-3784","email":"non@aol.couk","address":"Ap #370-7210 Magna. Ave","postalZip":"8360","country":"Poland"},{"customerId":855,"customerName":"Eugenia Harrison","phone":"1-535-715-1251","email":"interdum.feugiat@yahoo.com","address":"1740 Neque. St.","postalZip":"94176","country":"Brazil"},{"customerId":856,"customerName":"Baker Herring","phone":"(497) 584-8574","email":"a.auctor.non@yahoo.ca","address":"Ap #128-1480 Sit Road","postalZip":"30207","country":"Brazil"},{"customerId":857,"customerName":"Wynne Rodriquez","phone":"1-623-964-7218","email":"non@protonmail.org","address":"889-8829 Cras Road","postalZip":"17387","country":"Pakistan"},{"customerId":858,"customerName":"Mollie Harrell","phone":"1-482-630-3926","email":"felis.eget.varius@icloud.ca","address":"Ap #366-9332 Et, Ave","postalZip":"641087","country":"Brazil"},{"customerId":859,"customerName":"Colby Miranda","phone":"1-775-556-5921","email":"erat.etiam.vestibulum@yahoo.net","address":"5333 Egestas St.","postalZip":"568221","country":"Belgium"},{"customerId":860,"customerName":"Olympia Bowen","phone":"1-601-957-5517","email":"arcu.vel.quam@aol.org","address":"P.O. Box 289, 1594 Et, Av.","postalZip":"1577","country":"Brazil"},{"customerId":861,"customerName":"Prescott French","phone":"1-257-342-1139","email":"malesuada@hotmail.ca","address":"P.O. Box 595, 3504 Posuere Road","postalZip":"4364","country":"Mexico"},{"customerId":862,"customerName":"Simone Compton","phone":"(893) 915-7716","email":"suspendisse@outlook.net","address":"135-3881 Elit. Road","postalZip":"593220","country":"Australia"},{"customerId":863,"customerName":"Jared Duffy","phone":"1-857-779-6827","email":"convallis.ante@yahoo.org","address":"Ap #225-6226 Phasellus Av.","postalZip":"5248","country":"Australia"},{"customerId":864,"customerName":"Armand Baird","phone":"1-868-386-7557","email":"placerat.augue@hotmail.org","address":"P.O. Box 795, 5865 Quis Ave","postalZip":"27354","country":"Mexico"},{"customerId":865,"customerName":"Isaiah Woodard","phone":"(972) 736-5497","email":"quis.diam@outlook.couk","address":"785-3996 Mi. Street","postalZip":"11041","country":"Singapore"},{"customerId":866,"customerName":"Lars Hart","phone":"1-320-941-1073","email":"sapien@google.couk","address":"Ap #191-3940 Nec Rd.","postalZip":"72957","country":"China"},{"customerId":867,"customerName":"Zenia Joyner","phone":"(358) 582-3514","email":"magna.ut@icloud.couk","address":"1620 Nonummy. St.","postalZip":"7672","country":"Vietnam"},{"customerId":868,"customerName":"Kylan Stevens","phone":"1-625-591-6631","email":"pellentesque@aol.net","address":"8512 Diam Street","postalZip":"4327","country":"Pakistan"},{"customerId":869,"customerName":"Eric Moss","phone":"1-552-565-1277","email":"varius.ultrices.mauris@aol.ca","address":"Ap #632-7134 A St.","postalZip":"9771","country":"Turkey"},{"customerId":870,"customerName":"Jacob Banks","phone":"(727) 919-4579","email":"molestie@icloud.net","address":"Ap #827-3069 Diam St.","postalZip":"9648 TQ","country":"France"},{"customerId":871,"customerName":"Moana Stark","phone":"1-813-722-1263","email":"molestie.pharetra.nibh@protonmail.edu","address":"Ap #791-2094 A Av.","postalZip":"27580","country":"Colombia"},{"customerId":872,"customerName":"Amaya Palmer","phone":"1-873-252-3643","email":"sapien@icloud.edu","address":"527-2942 Consequat Av.","postalZip":"580131","country":"Mexico"},{"customerId":873,"customerName":"Hollee Duncan","phone":"(625) 822-8336","email":"nunc.sed@aol.net","address":"P.O. Box 610, 8482 Auctor. Avenue","postalZip":"68798","country":"Ukraine"},{"customerId":874,"customerName":"Isabella Schmidt","phone":"1-777-838-7484","email":"donec.egestas@google.couk","address":"8838 Ipsum. Av.","postalZip":"AI67 1UV","country":"Sweden"},{"customerId":875,"customerName":"Mason Pruitt","phone":"(645) 751-8778","email":"blandit.nam@hotmail.ca","address":"9611 Euismod St.","postalZip":"49-617","country":"Netherlands"},{"customerId":876,"customerName":"Candice Glover","phone":"(356) 348-3131","email":"curabitur.ut@hotmail.ca","address":"405-9717 Integer Av.","postalZip":"9657","country":"Sweden"},{"customerId":877,"customerName":"Hamilton Park","phone":"(142) 125-5266","email":"sit.amet@outlook.couk","address":"Ap #148-8251 Donec Road","postalZip":"8559","country":"Spain"},{"customerId":878,"customerName":"Finn Hardy","phone":"(925) 523-6709","email":"phasellus.in@hotmail.com","address":"P.O. Box 802, 3447 Vel Av.","postalZip":"1619","country":"United Kingdom"},{"customerId":879,"customerName":"Garrison Best","phone":"(340) 332-7016","email":"phasellus.vitae@aol.edu","address":"6526 Vestibulum Road","postalZip":"632215","country":"Australia"},{"customerId":880,"customerName":"Shelly Landry","phone":"1-397-259-9786","email":"non@protonmail.couk","address":"Ap #345-1957 Fringilla Av.","postalZip":"6285 JI","country":"Pakistan"},{"customerId":881,"customerName":"Stacey Walter","phone":"1-685-786-8947","email":"in.scelerisque@aol.net","address":"337-5711 Convallis Avenue","postalZip":"748917","country":"Canada"},{"customerId":882,"customerName":"Rhonda Chambers","phone":"(781) 268-1152","email":"a@aol.ca","address":"936-5244 Placerat Road","postalZip":"56371-69464","country":"United Kingdom"},{"customerId":883,"customerName":"Virginia Norman","phone":"1-907-553-9287","email":"lectus@yahoo.net","address":"Ap #944-7355 Sit Avenue","postalZip":"4328","country":"Philippines"},{"customerId":884,"customerName":"Roary Reese","phone":"(228) 767-1658","email":"justo.praesent@outlook.edu","address":"252-3778 Duis Av.","postalZip":"3885","country":"China"},{"customerId":885,"customerName":"Macey Young","phone":"(332) 788-9582","email":"sed.molestie@yahoo.couk","address":"547-9496 Quis St.","postalZip":"362467","country":"Turkey"},{"customerId":886,"customerName":"Xander Andrews","phone":"1-412-136-2272","email":"neque@outlook.net","address":"Ap #469-2682 Enim St.","postalZip":"694036","country":"United States"},{"customerId":887,"customerName":"Giacomo Santana","phone":"1-243-994-3413","email":"sociis.natoque.penatibus@outlook.org","address":"Ap #520-804 Non Rd.","postalZip":"1922 QJ","country":"Netherlands"},{"customerId":888,"customerName":"Austin Ashley","phone":"(413) 713-1285","email":"eu.enim@aol.ca","address":"864-7367 Tristique Av.","postalZip":"07942-73448","country":"Poland"},{"customerId":889,"customerName":"Kennan Cochran","phone":"1-388-351-9077","email":"penatibus@hotmail.net","address":"259-7129 Dictum Rd.","postalZip":"906305","country":"Poland"},{"customerId":890,"customerName":"Emi Clay","phone":"(254) 847-2864","email":"enim.suspendisse@yahoo.net","address":"6605 In Rd.","postalZip":"07608","country":"China"},{"customerId":891,"customerName":"Hilel Parrish","phone":"1-123-656-0967","email":"tortor.integer.aliquam@google.net","address":"920-9375 Turpis Avenue","postalZip":"3174","country":"United Kingdom"},{"customerId":892,"customerName":"Vera Garrison","phone":"(215) 206-2836","email":"felis.eget@outlook.com","address":"P.O. Box 285, 4574 Libero. Rd.","postalZip":"51208","country":"Australia"},{"customerId":893,"customerName":"Nasim Salas","phone":"1-703-889-1643","email":"eu@outlook.net","address":"Ap #374-9346 Non Rd.","postalZip":"6368","country":"Peru"},{"customerId":894,"customerName":"McKenzie Lloyd","phone":"1-432-573-2779","email":"egestas.a@icloud.edu","address":"127-6709 Nulla Ave","postalZip":"22446","country":"Italy"},{"customerId":895,"customerName":"Isadora Meyer","phone":"1-526-824-5811","email":"ante@hotmail.net","address":"Ap #121-5287 Et Street","postalZip":"977540","country":"Colombia"},{"customerId":896,"customerName":"Thomas Sullivan","phone":"1-747-833-2156","email":"eget.volutpat.ornare@aol.couk","address":"875-6723 Eget, St.","postalZip":"798142","country":"Singapore"},{"customerId":897,"customerName":"Nolan Robles","phone":"1-665-326-8766","email":"metus.vivamus@yahoo.net","address":"Ap #958-8902 Consectetuer Av.","postalZip":"667486","country":"Costa Rica"},{"customerId":898,"customerName":"Armando Bird","phone":"1-270-981-5850","email":"vitae@outlook.com","address":"Ap #174-3966 Posuere Av.","postalZip":"3453","country":"Brazil"},{"customerId":899,"customerName":"Tallulah Kirkland","phone":"(710) 371-8747","email":"turpis.vitae@protonmail.net","address":"Ap #778-7766 Est St.","postalZip":"57311","country":"Indonesia"},{"customerId":900,"customerName":"Laith Bell","phone":"(893) 690-8661","email":"sed.eu.eros@hotmail.com","address":"Ap #325-1564 Ut St.","postalZip":"497439","country":"South Africa"},{"customerId":901,"customerName":"Quon Stephens","phone":"(818) 985-7538","email":"sit.amet@outlook.net","address":"901-7663 Dictum Avenue","postalZip":"38284","country":"Belgium"},{"customerId":902,"customerName":"Shad Chang","phone":"1-527-865-4263","email":"risus.morbi@google.com","address":"623-5201 Aliquet. Av.","postalZip":"48228","country":"Norway"},{"customerId":903,"customerName":"Aurelia Silva","phone":"(839) 527-4353","email":"non.dapibus@google.org","address":"Ap #222-9662 Varius St.","postalZip":"16773","country":"Australia"},{"customerId":904,"customerName":"Forrest Kelley","phone":"1-621-820-6822","email":"et.magnis@outlook.net","address":"7082 Sagittis St.","postalZip":"546966","country":"Ireland"},{"customerId":905,"customerName":"Upton Miles","phone":"1-743-519-6755","email":"elit.erat.vitae@yahoo.edu","address":"P.O. Box 317, 6564 Interdum St.","postalZip":"7957","country":"Austria"},{"customerId":906,"customerName":"Zia Randall","phone":"(288) 382-5107","email":"primis.in@protonmail.net","address":"952-8194 Arcu. Rd.","postalZip":"43263","country":"Singapore"},{"customerId":907,"customerName":"Lacey Maddox","phone":"1-303-603-3635","email":"dolor.tempus@protonmail.org","address":"Ap #608-7831 Facilisis St.","postalZip":"64856","country":"Ireland"},{"customerId":908,"customerName":"Scott Haley","phone":"1-745-309-7551","email":"eu@google.couk","address":"1856 Ac Street","postalZip":"935096","country":"Russian Federation"},{"customerId":909,"customerName":"Maite Dyer","phone":"(254) 654-5465","email":"in.scelerisque@yahoo.ca","address":"Ap #293-7870 Tincidunt St.","postalZip":"76173-41626","country":"Chile"},{"customerId":910,"customerName":"Timon Tanner","phone":"1-533-624-6173","email":"eget.massa@hotmail.org","address":"481-6415 Nascetur St.","postalZip":"85563","country":"France"},{"customerId":911,"customerName":"Caldwell Mcpherson","phone":"1-241-617-6537","email":"elit.sed.consequat@outlook.org","address":"P.O. Box 857, 9466 Ipsum Avenue","postalZip":"3375","country":"Mexico"},{"customerId":912,"customerName":"Clinton Sloan","phone":"1-272-313-5420","email":"turpis.non@icloud.ca","address":"657-8967 Risus. St.","postalZip":"27833","country":"Mexico"},{"customerId":913,"customerName":"Jocelyn Moore","phone":"1-895-833-3862","email":"erat.volutpat@hotmail.com","address":"P.O. Box 469, 1402 At Rd.","postalZip":"69151-88340","country":"China"},{"customerId":914,"customerName":"Lamar Frost","phone":"(781) 854-8743","email":"eu.nibh@outlook.com","address":"6341 At St.","postalZip":"06496","country":"South Africa"},{"customerId":915,"customerName":"Axel Roth","phone":"1-845-403-2013","email":"non.cursus@aol.couk","address":"P.O. Box 162, 6074 Vulputate St.","postalZip":"8434","country":"France"},{"customerId":916,"customerName":"Wade Sloan","phone":"(726) 945-5788","email":"in.magna@google.net","address":"234-4912 Nunc. Road","postalZip":"429441","country":"Austria"},{"customerId":917,"customerName":"Elizabeth Rich","phone":"1-721-199-1325","email":"integer.id.magna@google.org","address":"Ap #205-4303 Natoque Av.","postalZip":"32356","country":"United Kingdom"},{"customerId":918,"customerName":"Buffy Gutierrez","phone":"1-877-762-8235","email":"ac.fermentum.vel@aol.com","address":"700-1480 Est, Rd.","postalZip":"10151","country":"Nigeria"},{"customerId":919,"customerName":"Sara Schneider","phone":"(987) 216-9299","email":"aenean.gravida@hotmail.org","address":"708-7047 Ac Road","postalZip":"7942","country":"Indonesia"},{"customerId":920,"customerName":"Colton Jefferson","phone":"(580) 735-6818","email":"nisl.nulla@hotmail.net","address":"1117 Parturient Ave","postalZip":"73725","country":"Russian Federation"},{"customerId":921,"customerName":"Dexter Ochoa","phone":"1-725-148-6256","email":"lacinia.at@yahoo.org","address":"P.O. Box 456, 3422 Sit Ave","postalZip":"1254","country":"France"},{"customerId":922,"customerName":"Adele English","phone":"1-503-633-2654","email":"gravida.molestie@icloud.net","address":"2238 Amet Road","postalZip":"30697","country":"Canada"},{"customerId":923,"customerName":"Omar Mcleod","phone":"1-134-392-7889","email":"laoreet.posuere@google.org","address":"5954 Pede, St.","postalZip":"872786","country":"Vietnam"},{"customerId":924,"customerName":"Ciara Holcomb","phone":"1-583-372-7555","email":"luctus.ut.pellentesque@protonmail.ca","address":"4796 Metus St.","postalZip":"62874","country":"Philippines"},{"customerId":925,"customerName":"Regina Atkinson","phone":"(534) 258-5425","email":"lorem@google.edu","address":"Ap #402-8294 Mauris Ave","postalZip":"15267","country":"Pakistan"},{"customerId":926,"customerName":"Damian Hampton","phone":"(462) 903-4041","email":"tempus.non@icloud.org","address":"Ap #438-7817 Pede Street","postalZip":"6321","country":"Norway"},{"customerId":927,"customerName":"Lavinia Barton","phone":"1-531-751-3961","email":"augue@hotmail.net","address":"Ap #426-4097 Aliquet Rd.","postalZip":"3872","country":"Canada"},{"customerId":928,"customerName":"Orli Lewis","phone":"(473) 492-3227","email":"auctor@aol.org","address":"8765 Egestas St.","postalZip":"42374","country":"Ukraine"},{"customerId":929,"customerName":"Patience Maxwell","phone":"1-443-417-6659","email":"tempus.risus@outlook.ca","address":"615-716 A, St.","postalZip":"747669","country":"Spain"},{"customerId":930,"customerName":"Urielle Mckinney","phone":"1-587-151-6352","email":"dui.cum@outlook.ca","address":"Ap #876-9997 Ac Avenue","postalZip":"5325","country":"Peru"},{"customerId":931,"customerName":"Sade Tran","phone":"1-508-329-7233","email":"ipsum.cursus@aol.edu","address":"P.O. Box 807, 5999 Vitae, Road","postalZip":"53736-56842","country":"Ireland"},{"customerId":932,"customerName":"Graham Morales","phone":"(993) 262-1871","email":"arcu.eu.odio@yahoo.edu","address":"Ap #711-5399 Arcu. St.","postalZip":"54-235","country":"Poland"},{"customerId":933,"customerName":"Merrill Booth","phone":"(969) 655-6452","email":"massa@yahoo.edu","address":"3631 Libero St.","postalZip":"485279","country":"United Kingdom"},{"customerId":934,"customerName":"Quin Farley","phone":"1-427-843-1463","email":"malesuada@yahoo.edu","address":"933-1916 Donec St.","postalZip":"34864","country":"China"},{"customerId":935,"customerName":"Chase Jordan","phone":"1-366-526-4663","email":"dolor.elit.pellentesque@yahoo.ca","address":"P.O. Box 163, 9960 Pellentesque Road","postalZip":"04599-64083","country":"United States"},{"customerId":936,"customerName":"Travis Walters","phone":"1-831-614-0583","email":"erat.vel@protonmail.org","address":"P.O. Box 848, 5042 In Av.","postalZip":"728258","country":"China"},{"customerId":937,"customerName":"Aspen Campbell","phone":"1-985-344-7859","email":"mus.aenean@yahoo.couk","address":"533 Ipsum Avenue","postalZip":"927535","country":"Peru"},{"customerId":938,"customerName":"Graham Mcmahon","phone":"(124) 415-1304","email":"maecenas@protonmail.edu","address":"Ap #582-5744 Nec Rd.","postalZip":"882466","country":"Colombia"},{"customerId":939,"customerName":"Francis Evans","phone":"(521) 395-7885","email":"sem.nulla.interdum@protonmail.com","address":"811-190 Non Rd.","postalZip":"47576","country":"Netherlands"},{"customerId":940,"customerName":"Martha Lee","phone":"(300) 237-1457","email":"fringilla.ornare@google.net","address":"Ap #926-7942 Est. Ave","postalZip":"851530","country":"South Africa"},{"customerId":941,"customerName":"Helen Foley","phone":"1-609-820-7112","email":"id.ante@outlook.net","address":"9531 Non Ave","postalZip":"46431-684","country":"Indonesia"},{"customerId":942,"customerName":"Zeus Byers","phone":"1-613-708-2182","email":"id.sapien@hotmail.edu","address":"9951 Consequat St.","postalZip":"62922","country":"South Korea"},{"customerId":943,"customerName":"Marsden Norman","phone":"1-341-273-4286","email":"ipsum.nunc@google.couk","address":"Ap #795-1007 Facilisis Avenue","postalZip":"44277","country":"China"},{"customerId":944,"customerName":"Gabriel Melendez","phone":"(770) 224-3114","email":"arcu.ac@outlook.couk","address":"Ap #155-1057 Vel Road","postalZip":"519282","country":"Sweden"},{"customerId":945,"customerName":"Macaulay Dalton","phone":"(551) 710-9454","email":"ornare.elit@aol.net","address":"330-4789 Scelerisque Street","postalZip":"344643","country":"Mexico"},{"customerId":946,"customerName":"Indira Larson","phone":"(612) 289-2228","email":"egestas.sed@outlook.couk","address":"Ap #694-987 Lorem Avenue","postalZip":"J1M 6S6","country":"Mexico"},{"customerId":947,"customerName":"Lisandra Jones","phone":"1-245-157-4874","email":"tempus.eu@aol.com","address":"9993 Faucibus Ave","postalZip":"30387","country":"France"},{"customerId":948,"customerName":"Bruce Abbott","phone":"(200) 764-1300","email":"lorem.fringilla@hotmail.com","address":"P.O. Box 307, 208 Enim. Rd.","postalZip":"34587","country":"Norway"},{"customerId":949,"customerName":"Amos Gibbs","phone":"1-836-859-9683","email":"nec.urna@google.ca","address":"954-2928 Eu, Street","postalZip":"89445-593","country":"France"},{"customerId":950,"customerName":"Brenda Dejesus","phone":"(768) 867-6715","email":"at.sem@icloud.com","address":"P.O. Box 525, 3212 Aliquet Avenue","postalZip":"11951","country":"Russian Federation"},{"customerId":951,"customerName":"Madonna Aguirre","phone":"1-958-725-7792","email":"aliquam.nec.enim@hotmail.ca","address":"8532 Inceptos St.","postalZip":"162175","country":"South Africa"},{"customerId":952,"customerName":"Adria Wells","phone":"1-274-813-1556","email":"faucibus@icloud.edu","address":"849-4155 Mollis. Avenue","postalZip":"41918","country":"Poland"},{"customerId":953,"customerName":"Ayanna Case","phone":"1-230-785-5557","email":"arcu.iaculis.enim@outlook.edu","address":"373-2601 Consectetuer Rd.","postalZip":"612727","country":"Mexico"},{"customerId":954,"customerName":"Dawn Rhodes","phone":"1-602-268-1478","email":"massa.rutrum@icloud.ca","address":"P.O. Box 708, 6403 Conubia Road","postalZip":"65888","country":"Brazil"},{"customerId":955,"customerName":"Kelly Delacruz","phone":"1-413-974-6640","email":"elit.elit@yahoo.net","address":"6302 Scelerisque Ave","postalZip":"4437","country":"Ukraine"},{"customerId":956,"customerName":"Fatima Parsons","phone":"1-453-618-5576","email":"lobortis@hotmail.com","address":"P.O. Box 126, 3973 Ante St.","postalZip":"65221-108","country":"Australia"},{"customerId":957,"customerName":"Stone Christian","phone":"1-853-758-5363","email":"consectetuer.ipsum@protonmail.ca","address":"Ap #604-6420 Nunc St.","postalZip":"97748","country":"Norway"},{"customerId":958,"customerName":"Philip Mejia","phone":"1-836-348-1421","email":"est.mollis.non@outlook.org","address":"P.O. Box 875, 7017 Vel St.","postalZip":"2518","country":"South Korea"},{"customerId":959,"customerName":"Xantha Burnett","phone":"(950) 347-1125","email":"nibh@google.edu","address":"144-6941 Sapien, Rd.","postalZip":"1112","country":"Peru"},{"customerId":960,"customerName":"Kameko Collier","phone":"1-920-939-8935","email":"luctus.felis.purus@aol.ca","address":"P.O. Box 984, 1468 Parturient Rd.","postalZip":"5676","country":"Mexico"},{"customerId":961,"customerName":"Holmes Butler","phone":"1-161-335-8829","email":"sem.magna@google.net","address":"943 Ut, St.","postalZip":"64877","country":"Spain"},{"customerId":962,"customerName":"Olivia Gallagher","phone":"1-868-686-0406","email":"ac.mi@icloud.net","address":"P.O. Box 740, 6114 Adipiscing St.","postalZip":"7271","country":"Netherlands"},{"customerId":963,"customerName":"Kelsey Moran","phone":"(453) 764-1048","email":"est@aol.net","address":"605-1372 Sodales Avenue","postalZip":"48430","country":"India"},{"customerId":964,"customerName":"Gray Rollins","phone":"1-918-258-3389","email":"eget.lacus@aol.ca","address":"Ap #903-7570 Lectus Av.","postalZip":"V7 7SH","country":"Pakistan"},{"customerId":965,"customerName":"Martena Ochoa","phone":"(561) 338-6364","email":"arcu@protonmail.org","address":"157-5745 Ipsum Rd.","postalZip":"460925","country":"Pakistan"},{"customerId":966,"customerName":"Hamilton Morin","phone":"(503) 821-2144","email":"integer.urna@aol.net","address":"242-6500 Cras Avenue","postalZip":"15523","country":"China"},{"customerId":967,"customerName":"Cecilia Marks","phone":"(835) 984-3049","email":"nec@yahoo.net","address":"P.O. Box 917, 3781 Phasellus Street","postalZip":"94686","country":"Pakistan"},{"customerId":968,"customerName":"Jessamine Saunders","phone":"(585) 363-1684","email":"in.lobortis.tellus@yahoo.couk","address":"Ap #947-7107 Molestie Rd.","postalZip":"353800","country":"Spain"},{"customerId":969,"customerName":"Kennan Alston","phone":"1-439-615-5885","email":"lobortis.quis.pede@hotmail.org","address":"Ap #585-6008 Natoque Av.","postalZip":"42433","country":"Netherlands"},{"customerId":970,"customerName":"Frances Mcmillan","phone":"(484) 538-7663","email":"erat.volutpat.nulla@aol.com","address":"1911 Phasellus Road","postalZip":"76L 8W8","country":"India"},{"customerId":971,"customerName":"Inga Bauer","phone":"(302) 374-9235","email":"ipsum.primis@aol.net","address":"Ap #774-3768 Ridiculus Avenue","postalZip":"15052","country":"Spain"},{"customerId":972,"customerName":"Anthony Blevins","phone":"1-556-833-4262","email":"vitae.odio@outlook.com","address":"6624 Vivamus Street","postalZip":"191871","country":"Costa Rica"},{"customerId":973,"customerName":"Ann Mason","phone":"(231) 641-4517","email":"sed.molestie.sed@yahoo.ca","address":"705-8650 Cursus St.","postalZip":"426539","country":"Belgium"},{"customerId":974,"customerName":"Ursa Stafford","phone":"(488) 575-8823","email":"libero@icloud.ca","address":"3815 Dignissim. St.","postalZip":"77-498","country":"Australia"},{"customerId":975,"customerName":"Jonah Duncan","phone":"(462) 764-2513","email":"condimentum.eget@protonmail.net","address":"789-7025 Dolor Av.","postalZip":"44100-948","country":"Australia"},{"customerId":976,"customerName":"Rogan Calhoun","phone":"1-473-293-9553","email":"vel.turpis@google.net","address":"Ap #212-936 Nunc. Road","postalZip":"85607","country":"Brazil"},{"customerId":977,"customerName":"Thane Rivera","phone":"1-718-239-6854","email":"ultrices@google.org","address":"4381 Pede Street","postalZip":"749581","country":"Belgium"},{"customerId":978,"customerName":"Justina Gay","phone":"(937) 387-5284","email":"cursus.et@hotmail.org","address":"3656 Mus. Rd.","postalZip":"14487","country":"Chile"},{"customerId":979,"customerName":"Adria Banks","phone":"1-859-887-5987","email":"dolor.sit@outlook.edu","address":"216-4692 Duis St.","postalZip":"86436","country":"South Korea"},{"customerId":980,"customerName":"Kelsey Moran","phone":"(478) 819-4431","email":"metus.sit@protonmail.com","address":"Ap #541-5522 Lacus. Street","postalZip":"82117","country":"Peru"},{"customerId":981,"customerName":"Cynthia Meyers","phone":"1-292-171-4752","email":"risus.at@aol.couk","address":"257-7916 Nullam Street","postalZip":"3456","country":"Poland"},{"customerId":982,"customerName":"Arthur Robbins","phone":"(223) 239-3905","email":"euismod.enim@yahoo.edu","address":"Ap #687-7105 At Ave","postalZip":"12866","country":"Indonesia"},{"customerId":983,"customerName":"Quemby Macdonald","phone":"(547) 527-5482","email":"et@google.ca","address":"8385 Leo Av.","postalZip":"6980","country":"Italy"},{"customerId":984,"customerName":"Gage Nicholson","phone":"(524) 160-7989","email":"pellentesque.tellus@outlook.org","address":"P.O. Box 395, 230 Nunc St.","postalZip":"710437","country":"Colombia"},{"customerId":985,"customerName":"Charles Mccullough","phone":"1-427-715-4713","email":"tempor.diam@icloud.ca","address":"526-8007 Ut Rd.","postalZip":"535843","country":"Ireland"},{"customerId":986,"customerName":"Holly Bolton","phone":"(374) 520-7920","email":"in.faucibus.orci@aol.ca","address":"Ap #713-4176 Eleifend. St.","postalZip":"87493","country":"Belgium"},{"customerId":987,"customerName":"Lysandra Mcpherson","phone":"1-403-226-4192","email":"vulputate@google.couk","address":"4290 Ligula Street","postalZip":"42-13","country":"Australia"},{"customerId":988,"customerName":"Dora Rollins","phone":"(744) 645-0189","email":"metus@google.net","address":"144-3498 Sem, St.","postalZip":"8725 WM","country":"Norway"},{"customerId":989,"customerName":"Germane Clay","phone":"1-401-848-6048","email":"orci.luctus@icloud.com","address":"4451 Pharetra Road","postalZip":"73-094","country":"Singapore"},{"customerId":990,"customerName":"Hu Carrillo","phone":"(803) 178-4184","email":"ultrices.mauris@google.com","address":"Ap #570-6629 Non, Avenue","postalZip":"399243","country":"Brazil"},{"customerId":991,"customerName":"Ezekiel Webster","phone":"1-572-614-4388","email":"commodo.auctor.velit@hotmail.org","address":"Ap #935-3203 Vivamus Rd.","postalZip":"3527","country":"Ukraine"},{"customerId":992,"customerName":"Lacy Snow","phone":"(743) 434-6333","email":"augue.porttitor@hotmail.ca","address":"522-4690 Purus. Street","postalZip":"493283","country":"Vietnam"},{"customerId":993,"customerName":"Quin Joyner","phone":"1-185-311-5577","email":"non.enim@yahoo.couk","address":"705-2787 Nulla. Rd.","postalZip":"11647-35869","country":"Italy"},{"customerId":994,"customerName":"Fiona Mathis","phone":"1-824-222-5041","email":"libero.proin@google.edu","address":"P.O. Box 647, 4198 Sed Rd.","postalZip":"597431","country":"France"},{"customerId":995,"customerName":"Basia Skinner","phone":"(555) 185-9729","email":"nunc.nulla@outlook.ca","address":"9754 Proin Street","postalZip":"225528","country":"France"},{"customerId":996,"customerName":"Hashim Mcbride","phone":"(346) 751-6442","email":"metus@outlook.couk","address":"Ap #838-4039 Lobortis, St.","postalZip":"53-024","country":"Norway"},{"customerId":997,"customerName":"Rooney Lynch","phone":"1-487-422-2875","email":"aliquam.arcu@aol.ca","address":"648-2993 Sed, Road","postalZip":"6513","country":"Ireland"},{"customerId":998,"customerName":"Leila Fox","phone":"1-341-444-3115","email":"sem@outlook.edu","address":"Ap #459-9582 Non Rd.","postalZip":"81222","country":"Pakistan"},{"customerId":999,"customerName":"Brynne Branch","phone":"(288) 310-8139","email":"non.luctus@yahoo.org","address":"Ap #177-7697 Scelerisque Road","postalZip":"52949","country":"Italy"},{"customerId":1000,"customerName":"Keane Shelton","phone":"1-346-394-1095","email":"duis.cursus@aol.ca","address":"P.O. Box 746, 9534 Id, Rd.","postalZip":"72-99","country":"Sweden"},{"customerId":1001,"customerName":"Ariana Gallagher","phone":"(641) 245-7160","email":"nunc.est.mollis@hotmail.ca","address":"957-8413 Tincidunt, Ave","postalZip":"13388-198","country":"Turkey"},{"customerId":1002,"customerName":"Dieter Cleveland","phone":"1-241-428-6807","email":"tortor.integer@yahoo.ca","address":"Ap #877-9843 Ligula Road","postalZip":"1582-2940","country":"Netherlands"},{"customerId":1003,"customerName":"Rahim Tanner","phone":"1-570-418-6621","email":"donec.fringilla@icloud.org","address":"6638 Orci Avenue","postalZip":"258854","country":"China"},{"customerId":1004,"customerName":"Brady Ruiz","phone":"1-354-841-1142","email":"iaculis.enim@yahoo.couk","address":"4636 Donec Road","postalZip":"87618","country":"Costa Rica"},{"customerId":1005,"customerName":"Dora Walsh","phone":"1-256-412-0822","email":"nunc.risus.varius@icloud.org","address":"576-5293 Velit St.","postalZip":"68582","country":"Ireland"},{"customerId":1006,"customerName":"Ora Ochoa","phone":"(364) 571-9386","email":"nibh.aliquam@protonmail.com","address":"7788 Sed Avenue","postalZip":"67334","country":"South Korea"},{"customerId":1007,"customerName":"Moses Blair","phone":"1-220-451-1713","email":"commodo.at.libero@aol.ca","address":"928-296 Sit St.","postalZip":"174531","country":"Turkey"},{"customerId":1008,"customerName":"Jenna Clay","phone":"1-844-514-1457","email":"at@aol.net","address":"712-4619 Mauris, Rd.","postalZip":"912471","country":"Poland"},{"customerId":1009,"customerName":"Quynn Contreras","phone":"1-177-616-7856","email":"donec.nibh@yahoo.ca","address":"4981 Commodo Avenue","postalZip":"023512","country":"Colombia"},{"customerId":1010,"customerName":"Jeanette Gray","phone":"(762) 811-9255","email":"nullam@aol.org","address":"522-5179 Neque St.","postalZip":"R1Y 2KI","country":"Pakistan"},{"customerId":1011,"customerName":"Minerva Shaw","phone":"1-531-439-8381","email":"et.netus@outlook.ca","address":"885-6589 Suspendisse Rd.","postalZip":"1873","country":"Ukraine"},{"customerId":1012,"customerName":"Lamar Maddox","phone":"(530) 332-4351","email":"sed.sem@aol.edu","address":"840-1307 Mauris Street","postalZip":"91128-55184","country":"New Zealand"},{"customerId":1013,"customerName":"Gregory Gomez","phone":"(891) 431-4536","email":"fermentum.fermentum@protonmail.ca","address":"P.O. Box 969, 845 Pharetra Rd.","postalZip":"03115","country":"Singapore"},{"customerId":1014,"customerName":"Cody Holden","phone":"(550) 427-4608","email":"gravida.nunc.sed@icloud.net","address":"742-9148 Aenean St.","postalZip":"25260","country":"Colombia"},{"customerId":1015,"customerName":"Emmanuel Riggs","phone":"1-912-331-6058","email":"taciti.sociosqu@yahoo.edu","address":"Ap #971-8106 Nec Av.","postalZip":"622627","country":"Ireland"},{"customerId":1016,"customerName":"Caldwell Duran","phone":"1-468-665-2707","email":"egestas.hendrerit@protonmail.net","address":"1006 Proin Avenue","postalZip":"50207","country":"Peru"},{"customerId":1017,"customerName":"Daniel Mcdonald","phone":"(543) 736-7397","email":"accumsan.sed@google.org","address":"8050 Vivamus Av.","postalZip":"C3T 9V1","country":"South Korea"},{"customerId":1018,"customerName":"Oprah Hebert","phone":"(325) 345-6944","email":"vehicula.aliquet@hotmail.ca","address":"P.O. Box 516, 8769 Fames Av.","postalZip":"2423","country":"Ukraine"},{"customerId":1019,"customerName":"Cadman Conrad","phone":"(728) 281-1819","email":"volutpat.nunc.sit@hotmail.net","address":"Ap #590-914 Velit. Street","postalZip":"9805 RI","country":"Singapore"},{"customerId":1020,"customerName":"Kasimir Cortez","phone":"1-206-137-2017","email":"ante.lectus@google.com","address":"351-6955 Posuere, Av.","postalZip":"826698","country":"Colombia"},{"customerId":1021,"customerName":"Cynthia Boone","phone":"(508) 698-5167","email":"sed.orci@aol.net","address":"1708 Tincidunt Ave","postalZip":"44341-764","country":"Mexico"},{"customerId":1022,"customerName":"Herman Glass","phone":"1-168-238-3032","email":"mauris@google.com","address":"P.O. Box 206, 2392 Felis Street","postalZip":"56547","country":"Ireland"},{"customerId":1023,"customerName":"Nash English","phone":"(553) 788-2625","email":"et.magnis@yahoo.edu","address":"Ap #508-8133 Ac, Rd.","postalZip":"42-211","country":"Brazil"},{"customerId":1024,"customerName":"Gavin Mcgee","phone":"1-147-539-3812","email":"tempus.scelerisque@protonmail.org","address":"850-422 Feugiat Street","postalZip":"10347-23032","country":"Colombia"},{"customerId":1025,"customerName":"Paul Moss","phone":"(473) 820-2758","email":"eu.odio@google.edu","address":"832-8547 Non Rd.","postalZip":"82761","country":"Sweden"},{"customerId":1026,"customerName":"Marah Summers","phone":"1-445-248-4535","email":"iaculis.aliquet@hotmail.com","address":"P.O. Box 537, 8161 Risus Avenue","postalZip":"72571","country":"Peru"},{"customerId":1027,"customerName":"Hannah Hobbs","phone":"(636) 221-8122","email":"velit@aol.couk","address":"8199 Mattis Avenue","postalZip":"52254","country":"Vietnam"},{"customerId":1028,"customerName":"Ishmael David","phone":"1-634-546-7937","email":"sollicitudin.a@icloud.couk","address":"Ap #630-2933 Amet Av.","postalZip":"9962","country":"New Zealand"},{"customerId":1029,"customerName":"Cassidy Sparks","phone":"1-711-258-2412","email":"eleifend.egestas.sed@hotmail.org","address":"489-3034 Elit, Rd.","postalZip":"4729","country":"Peru"},{"customerId":1030,"customerName":"Mira Holland","phone":"(364) 476-7833","email":"dignissim.maecenas@outlook.edu","address":"164-643 Sed, St.","postalZip":"48024","country":"Peru"},{"customerId":1031,"customerName":"Robert Marquez","phone":"(921) 589-2158","email":"at.sem.molestie@outlook.com","address":"Ap #439-2737 Blandit St.","postalZip":"75-687","country":"France"},{"customerId":1032,"customerName":"Yoko Ashley","phone":"(730) 635-2298","email":"velit.justo.nec@hotmail.com","address":"Ap #373-2310 Sapien, Rd.","postalZip":"1448","country":"Germany"},{"customerId":1033,"customerName":"Joel Jenkins","phone":"(707) 809-3532","email":"maecenas.malesuada@icloud.couk","address":"P.O. Box 129, 7723 Ac Rd.","postalZip":"9486","country":"United Kingdom"},{"customerId":1034,"customerName":"Odette Gallegos","phone":"(851) 787-2816","email":"tincidunt.vehicula.risus@icloud.net","address":"591-844 Fringilla. Road","postalZip":"3047","country":"Pakistan"},{"customerId":1035,"customerName":"Mariko Velazquez","phone":"1-165-379-5034","email":"donec.tempus.lorem@aol.ca","address":"9630 Gravida Road","postalZip":"87735","country":"Singapore"},{"customerId":1036,"customerName":"Cain Beach","phone":"1-588-385-1677","email":"bibendum@aol.edu","address":"P.O. Box 817, 5584 Ipsum Road","postalZip":"68480","country":"Spain"},{"customerId":1037,"customerName":"Sierra Mills","phone":"(726) 555-1837","email":"mauris@google.org","address":"240-2253 Fermentum Rd.","postalZip":"25246-087","country":"Ireland"},{"customerId":1038,"customerName":"Kadeem Richards","phone":"(684) 147-4282","email":"morbi@aol.org","address":"315-1103 Suspendisse Rd.","postalZip":"DM1V 9BE","country":"Spain"},{"customerId":1039,"customerName":"Allistair Rutledge","phone":"(514) 528-5537","email":"mollis.integer@protonmail.net","address":"199-4270 Lobortis Road","postalZip":"88827","country":"Singapore"},{"customerId":1040,"customerName":"Chastity Whitley","phone":"(490) 767-2223","email":"quam.quis@aol.org","address":"Ap #910-8270 Pede Street","postalZip":"29536","country":"Italy"},{"customerId":1041,"customerName":"Beatrice Powers","phone":"1-587-326-9593","email":"velit.eu.sem@protonmail.com","address":"260-8757 Conubia Av.","postalZip":"46-44","country":"Netherlands"},{"customerId":1042,"customerName":"Reese Cohen","phone":"1-363-964-4177","email":"bibendum.fermentum@icloud.ca","address":"P.O. Box 594, 900 Et Ave","postalZip":"831474","country":"Nigeria"},{"customerId":1043,"customerName":"Yael Casey","phone":"(322) 547-1593","email":"consequat.lectus.sit@outlook.org","address":"P.O. Box 811, 9733 Tincidunt Avenue","postalZip":"548718","country":"Nigeria"},{"customerId":1044,"customerName":"Eagan Watts","phone":"(145) 750-8246","email":"egestas.fusce.aliquet@hotmail.edu","address":"P.O. Box 213, 5059 Eu Street","postalZip":"25246-41217","country":"Brazil"},{"customerId":1045,"customerName":"Amber Walters","phone":"1-148-169-2585","email":"massa@hotmail.edu","address":"Ap #420-7879 Vulputate, St.","postalZip":"04734","country":"Norway"},{"customerId":1046,"customerName":"Todd Bradford","phone":"(788) 884-3024","email":"ut.erat@outlook.com","address":"7278 Posuere Ave","postalZip":"781684","country":"China"},{"customerId":1047,"customerName":"Brendan Diaz","phone":"1-826-216-4856","email":"tempus@aol.org","address":"923-6416 Diam Street","postalZip":"03262-31584","country":"Sweden"},{"customerId":1048,"customerName":"Keaton Greer","phone":"(117) 892-7302","email":"nec.urna@outlook.com","address":"Ap #828-6847 Mauris Road","postalZip":"875327","country":"United Kingdom"},{"customerId":1049,"customerName":"Danielle Higgins","phone":"1-575-353-5252","email":"sed.dictum.proin@outlook.org","address":"P.O. Box 609, 8360 Libero Rd.","postalZip":"73660-08243","country":"Indonesia"},{"customerId":1050,"customerName":"Lucius Keith","phone":"(203) 293-5528","email":"nulla.eget.metus@google.couk","address":"616-8765 Turpis. Ave","postalZip":"45511","country":"Peru"},{"customerId":1051,"customerName":"Aspen James","phone":"1-517-328-5524","email":"lorem.fringilla.ornare@google.ca","address":"591-522 Primis Avenue","postalZip":"16341","country":"Netherlands"},{"customerId":1052,"customerName":"Kitra Marshall","phone":"(783) 862-4799","email":"nulla.donec@yahoo.couk","address":"P.O. Box 473, 5243 Aliquam Road","postalZip":"73-56","country":"Indonesia"},{"customerId":1053,"customerName":"Ivana Gibson","phone":"(267) 430-1406","email":"diam@protonmail.edu","address":"Ap #169-612 Accumsan St.","postalZip":"768017","country":"Singapore"},{"customerId":1054,"customerName":"Stacey Pennington","phone":"1-266-858-4381","email":"est.congue@outlook.com","address":"528-9940 Vivamus Rd.","postalZip":"25744","country":"Colombia"},{"customerId":1055,"customerName":"Jin Witt","phone":"(248) 264-8545","email":"vel.est@protonmail.org","address":"Ap #376-7684 Nunc St.","postalZip":"7689","country":"South Africa"},{"customerId":1056,"customerName":"Cody Adams","phone":"1-447-838-3049","email":"elit.fermentum@icloud.net","address":"Ap #690-8326 Velit St.","postalZip":"SP28 9UU","country":"India"},{"customerId":1057,"customerName":"Dora Winters","phone":"(426) 866-7651","email":"risus.quis@outlook.com","address":"7692 Vivamus St.","postalZip":"2742 GW","country":"India"},{"customerId":1058,"customerName":"Alika Noble","phone":"1-763-392-2802","email":"urna.justo@google.com","address":"6135 Velit. St.","postalZip":"905227","country":"China"},{"customerId":1059,"customerName":"Kibo Johnson","phone":"1-864-565-1385","email":"quisque.libero@outlook.net","address":"Ap #702-7679 Ultrices Street","postalZip":"07050","country":"Netherlands"},{"customerId":1060,"customerName":"Rylee Anderson","phone":"1-611-755-1689","email":"libero.et@hotmail.org","address":"P.O. Box 975, 3746 In Street","postalZip":"477914","country":"United States"},{"customerId":1061,"customerName":"Marshall Koch","phone":"(411) 523-4501","email":"nam.consequat.dolor@protonmail.net","address":"Ap #247-5935 Nec Street","postalZip":"446337","country":"United Kingdom"},{"customerId":1062,"customerName":"Alexander Nicholson","phone":"1-569-580-2732","email":"dignissim.maecenas.ornare@icloud.org","address":"986-9730 Molestie. Avenue","postalZip":"33859","country":"Ireland"},{"customerId":1063,"customerName":"Owen Bridges","phone":"1-576-206-1581","email":"lorem.auctor@icloud.edu","address":"Ap #535-4368 Ac Rd.","postalZip":"723362","country":"Ireland"},{"customerId":1064,"customerName":"Jennifer Mosley","phone":"(585) 231-8686","email":"lobortis.quam.a@outlook.ca","address":"P.O. Box 115, 6594 Quis Road","postalZip":"354543","country":"France"},{"customerId":1065,"customerName":"Elijah Randolph","phone":"(202) 442-4167","email":"vulputate.posuere@icloud.org","address":"P.O. Box 164, 5081 Amet Street","postalZip":"49914","country":"France"},{"customerId":1066,"customerName":"Hadley Knox","phone":"(191) 667-1973","email":"consectetuer.adipiscing@protonmail.edu","address":"495-4729 A, Av.","postalZip":"0110","country":"Turkey"},{"customerId":1067,"customerName":"Zelda Stone","phone":"1-558-567-7988","email":"nunc@google.edu","address":"Ap #482-9942 Dui Ave","postalZip":"3613 DE","country":"Mexico"},{"customerId":1068,"customerName":"Tate Mann","phone":"(117) 635-3662","email":"vitae.nibh.donec@protonmail.edu","address":"Ap #590-307 Semper Ave","postalZip":"KP76 6WI","country":"Vietnam"},{"customerId":1069,"customerName":"Elton Gould","phone":"(477) 266-7917","email":"erat.vel.pede@icloud.net","address":"P.O. Box 850, 4739 Consectetuer Road","postalZip":"3493","country":"Vietnam"},{"customerId":1070,"customerName":"Allistair Cohen","phone":"(863) 878-8640","email":"magna.praesent.interdum@protonmail.ca","address":"6475 Laoreet Av.","postalZip":"85794","country":"Philippines"},{"customerId":1071,"customerName":"Kalia Benjamin","phone":"1-853-794-3044","email":"ut.quam.vel@aol.net","address":"348-7185 Parturient St.","postalZip":"646015","country":"Turkey"},{"customerId":1072,"customerName":"Raven Henderson","phone":"(588) 366-6885","email":"integer.aliquam.adipiscing@icloud.edu","address":"Ap #913-7124 Nam Street","postalZip":"61843","country":"Belgium"},{"customerId":1073,"customerName":"Unity Pennington","phone":"(725) 834-8565","email":"nisi.magna@icloud.com","address":"617-6753 Etiam Rd.","postalZip":"S5C 4G0","country":"United Kingdom"},{"customerId":1074,"customerName":"Selma David","phone":"(521) 757-6781","email":"nunc@hotmail.com","address":"5999 Nulla Av.","postalZip":"633676","country":"Sweden"},{"customerId":1075,"customerName":"Mollie Moran","phone":"(543) 252-3367","email":"donec.egestas@icloud.edu","address":"9056 Duis Av.","postalZip":"301876","country":"Australia"},{"customerId":1076,"customerName":"Glenna Sosa","phone":"1-732-431-1548","email":"adipiscing.elit@yahoo.org","address":"507-9280 Auctor Street","postalZip":"36412","country":"Costa Rica"},{"customerId":1077,"customerName":"Daniel Tanner","phone":"1-234-351-8186","email":"suspendisse.commodo.tincidunt@icloud.couk","address":"752 Quis Rd.","postalZip":"23081","country":"Canada"},{"customerId":1078,"customerName":"Alana Herman","phone":"1-856-728-5444","email":"ultrices.posuere@outlook.org","address":"Ap #412-3114 Egestas. Street","postalZip":"181699","country":"Norway"},{"customerId":1079,"customerName":"Chester Bullock","phone":"1-656-895-8798","email":"vel.arcu@icloud.couk","address":"8472 Dolor. Avenue","postalZip":"42826","country":"Netherlands"},{"customerId":1080,"customerName":"Kamal Joyner","phone":"(845) 232-1459","email":"auctor@yahoo.ca","address":"Ap #334-6950 Amet, Rd.","postalZip":"8305","country":"Ukraine"},{"customerId":1081,"customerName":"Hedley Burks","phone":"(335) 570-2917","email":"imperdiet.dictum.magna@google.net","address":"6202 Est, Rd.","postalZip":"53446-285","country":"Australia"},{"customerId":1082,"customerName":"Igor Crosby","phone":"1-777-810-0582","email":"vivamus.rhoncus@icloud.org","address":"Ap #343-5545 Lobortis Avenue","postalZip":"1681-3208","country":"Sweden"},{"customerId":1083,"customerName":"Julian Dodson","phone":"1-906-263-3321","email":"ut@icloud.net","address":"604-4393 Natoque Av.","postalZip":"9431","country":"Peru"},{"customerId":1084,"customerName":"Steven Callahan","phone":"1-868-626-8530","email":"leo@yahoo.ca","address":"P.O. Box 688, 317 Metus Rd.","postalZip":"41466","country":"Russian Federation"},{"customerId":1085,"customerName":"Rosalyn Douglas","phone":"1-848-817-4238","email":"ante.lectus@outlook.edu","address":"368-3802 Aliquam Street","postalZip":"66617-480","country":"Austria"},{"customerId":1086,"customerName":"Raya Gillespie","phone":"(266) 563-1628","email":"vitae.risus@outlook.net","address":"Ap #522-9239 Fusce Road","postalZip":"116166","country":"Netherlands"},{"customerId":1087,"customerName":"Rhea Munoz","phone":"1-614-533-2099","email":"eu@yahoo.couk","address":"Ap #876-5161 Proin Street","postalZip":"4188","country":"United States"},{"customerId":1088,"customerName":"Kylan Brock","phone":"(662) 681-0156","email":"vulputate.risus@google.couk","address":"Ap #468-6891 Cubilia Rd.","postalZip":"30-286","country":"South Africa"},{"customerId":1089,"customerName":"Cairo Roth","phone":"1-617-885-9422","email":"inceptos.hymenaeos.mauris@protonmail.couk","address":"154-7919 Cursus. Street","postalZip":"1926-4231","country":"China"},{"customerId":1090,"customerName":"Amos Barrera","phone":"(629) 636-2417","email":"donec.nibh@protonmail.couk","address":"628-1708 Eget Street","postalZip":"43122","country":"United Kingdom"},{"customerId":1091,"customerName":"Adara Schultz","phone":"(315) 848-4318","email":"sem.molestie.sodales@aol.ca","address":"Ap #658-5506 Vestibulum Rd.","postalZip":"24540","country":"Netherlands"},{"customerId":1092,"customerName":"MacKensie Jacobs","phone":"(757) 258-9474","email":"consequat@hotmail.ca","address":"192-6726 Ipsum. Street","postalZip":"66-736","country":"Brazil"},{"customerId":1093,"customerName":"Lamar Knapp","phone":"1-671-486-7612","email":"nunc.pulvinar@hotmail.ca","address":"Ap #511-9259 Ultricies St.","postalZip":"1128","country":"Vietnam"},{"customerId":1094,"customerName":"Yoshio Noble","phone":"1-128-337-5122","email":"cursus.nunc.mauris@icloud.com","address":"Ap #878-2882 Aliquam Rd.","postalZip":"8266 ZQ","country":"Ireland"},{"customerId":1095,"customerName":"Eve Jarvis","phone":"(515) 785-2254","email":"vel.faucibus.id@hotmail.couk","address":"Ap #630-5639 Mollis Road","postalZip":"724885","country":"Sweden"},{"customerId":1096,"customerName":"Yvette Duke","phone":"1-355-784-3674","email":"pede.praesent@yahoo.net","address":"743-377 Iaculis, Rd.","postalZip":"4258 BV","country":"United States"},{"customerId":1097,"customerName":"Alyssa Hinton","phone":"(872) 832-0260","email":"faucibus.id.libero@yahoo.edu","address":"P.O. Box 589, 8074 Consectetuer Avenue","postalZip":"4233","country":"Mexico"},{"customerId":1098,"customerName":"Hyacinth Stafford","phone":"(634) 554-7716","email":"aenean.euismod@outlook.couk","address":"Ap #223-9590 Id, St.","postalZip":"278437","country":"Sweden"},{"customerId":1099,"customerName":"Cora Madden","phone":"1-877-714-2826","email":"lacus.quisque@yahoo.org","address":"P.O. Box 831, 9368 Est Ave","postalZip":"86745-14284","country":"United States"},{"customerId":1100,"customerName":"Dane Blackburn","phone":"(152) 405-2513","email":"pellentesque.ut@icloud.com","address":"Ap #901-9101 Eget, St.","postalZip":"5567","country":"Colombia"},{"customerId":1101,"customerName":"Melvin Weaver","phone":"(722) 372-6198","email":"ac.arcu@yahoo.edu","address":"Ap #933-3117 Ultricies Avenue","postalZip":"5411","country":"Austria"},{"customerId":1102,"customerName":"Castor Stevenson","phone":"1-956-610-1734","email":"nulla.aliquet@outlook.couk","address":"Ap #210-4589 Non Street","postalZip":"Y7C 6L1","country":"South Africa"},{"customerId":1103,"customerName":"Latifah Boyle","phone":"(268) 358-3508","email":"enim.commodo.hendrerit@yahoo.couk","address":"P.O. Box 675, 5130 Lorem Avenue","postalZip":"2264","country":"Nigeria"},{"customerId":1104,"customerName":"Juliet Roberson","phone":"1-546-184-6608","email":"mauris.ut@icloud.edu","address":"902-8841 Etiam Road","postalZip":"74147","country":"Philippines"},{"customerId":1105,"customerName":"Beatrice Bush","phone":"1-443-678-3571","email":"dapibus.rutrum@yahoo.ca","address":"Ap #104-522 Risus St.","postalZip":"518181","country":"Poland"},{"customerId":1106,"customerName":"Alice Ayala","phone":"1-568-422-7254","email":"dictum.sapien@google.edu","address":"Ap #488-8241 Natoque St.","postalZip":"510030","country":"Chile"},{"customerId":1107,"customerName":"Quentin Santana","phone":"1-662-407-7562","email":"amet.metus@aol.edu","address":"Ap #961-9610 Nullam St.","postalZip":"44814","country":"Pakistan"},{"customerId":1108,"customerName":"Darius Underwood","phone":"1-271-437-4785","email":"aliquam.fringilla@google.com","address":"P.O. Box 578, 4380 Sapien, Street","postalZip":"2894","country":"Poland"},{"customerId":1109,"customerName":"Adrienne Mccullough","phone":"1-445-842-8402","email":"lectus.rutrum.urna@aol.ca","address":"9973 Dui St.","postalZip":"0077-0443","country":"China"},{"customerId":1110,"customerName":"Logan Mcdaniel","phone":"(214) 932-2487","email":"faucibus@yahoo.org","address":"Ap #915-4053 Tellus Rd.","postalZip":"48153","country":"United Kingdom"},{"customerId":1111,"customerName":"Xavier William","phone":"(271) 624-0074","email":"id.magna.et@aol.ca","address":"387-7976 Scelerisque Av.","postalZip":"4688","country":"Brazil"},{"customerId":1112,"customerName":"Wyoming Solomon","phone":"1-724-835-9394","email":"consequat.purus.maecenas@outlook.net","address":"6859 Tempor Avenue","postalZip":"0667","country":"Nigeria"},{"customerId":1113,"customerName":"Lucy Mercado","phone":"1-718-647-2771","email":"ornare.lectus@google.net","address":"388-281 Ut Ave","postalZip":"76182","country":"Italy"},{"customerId":1114,"customerName":"Lee Barry","phone":"(482) 632-4144","email":"arcu.vivamus.sit@icloud.org","address":"Ap #733-294 Donec Ave","postalZip":"5267","country":"Ukraine"},{"customerId":1115,"customerName":"Mallory Meyers","phone":"(845) 369-9308","email":"aliquam.tincidunt@icloud.ca","address":"273-9646 Parturient Ave","postalZip":"68223-16370","country":"Turkey"},{"customerId":1116,"customerName":"Tanek Russo","phone":"1-161-720-6327","email":"orci.tincidunt@aol.net","address":"Ap #621-444 Aliquam Avenue","postalZip":"15882","country":"Belgium"},{"customerId":1117,"customerName":"Fleur Cash","phone":"1-172-397-9439","email":"magna.suspendisse.tristique@protonmail.edu","address":"4428 Pellentesque. Rd.","postalZip":"QG77 5VG","country":"Mexico"},{"customerId":1118,"customerName":"Robert Bray","phone":"(903) 618-3631","email":"non.bibendum@outlook.edu","address":"Ap #208-4373 Nulla Av.","postalZip":"399453","country":"Mexico"},{"customerId":1119,"customerName":"Portia Young","phone":"1-274-193-1726","email":"massa.non.ante@hotmail.org","address":"948-8716 Suspendisse Av.","postalZip":"72-41","country":"Chile"},{"customerId":1120,"customerName":"Dane Harris","phone":"1-805-371-3427","email":"est.tempor@icloud.org","address":"Ap #237-4085 Elit. St.","postalZip":"34624","country":"Philippines"},{"customerId":1121,"customerName":"Kelly Lloyd","phone":"1-480-842-3168","email":"ac.turpis@icloud.ca","address":"186-8823 Erat. St.","postalZip":"6342","country":"Colombia"},{"customerId":1122,"customerName":"Edward Walters","phone":"1-772-171-9420","email":"porttitor.tellus.non@outlook.couk","address":"Ap #513-3763 Risus, Av.","postalZip":"13236-44113","country":"New Zealand"},{"customerId":1123,"customerName":"Tatum Mcguire","phone":"(458) 318-8761","email":"at.velit@outlook.com","address":"310-6225 Quam Ave","postalZip":"7351","country":"New Zealand"},{"customerId":1124,"customerName":"Hayden Howell","phone":"(645) 782-7079","email":"nisi.sem@yahoo.net","address":"Ap #151-929 Ipsum Avenue","postalZip":"8813","country":"Spain"},{"customerId":1125,"customerName":"Lawrence Stein","phone":"1-823-902-6126","email":"turpis.egestas@yahoo.org","address":"Ap #543-1025 Mauris St.","postalZip":"483528","country":"Ukraine"},{"customerId":1126,"customerName":"Fulton Navarro","phone":"(289) 500-0651","email":"cras@outlook.couk","address":"385-7251 Vel Avenue","postalZip":"5140","country":"Chile"},{"customerId":1127,"customerName":"Aileen Walton","phone":"(572) 957-0289","email":"tellus@protonmail.com","address":"Ap #796-1199 Nisi Road","postalZip":"9637 RJ","country":"Turkey"},{"customerId":1128,"customerName":"Otto Guerrero","phone":"(828) 670-3167","email":"in.ornare@icloud.com","address":"Ap #983-2171 Non, Rd.","postalZip":"14756-28750","country":"Colombia"},{"customerId":1129,"customerName":"Hamish Higgins","phone":"1-680-308-1103","email":"posuere.cubilia.curae@aol.edu","address":"Ap #886-9957 Libero. Rd.","postalZip":"73731-574","country":"South Korea"},{"customerId":1130,"customerName":"Melodie Sears","phone":"(337) 229-1564","email":"lacinia.orci@protonmail.net","address":"134 Eu Street","postalZip":"8507","country":"Spain"},{"customerId":1131,"customerName":"Juliet Pierce","phone":"(375) 234-0415","email":"ac.mi@protonmail.org","address":"P.O. Box 825, 4047 Et, Rd.","postalZip":"174333","country":"Norway"},{"customerId":1132,"customerName":"Paki Branch","phone":"(884) 433-8414","email":"lacus.quisque@outlook.edu","address":"P.O. Box 682, 7617 Sed St.","postalZip":"12145","country":"Russian Federation"},{"customerId":1133,"customerName":"Tamara Baldwin","phone":"1-218-677-1038","email":"dui@outlook.ca","address":"377 Aliquam Rd.","postalZip":"84276","country":"Italy"},{"customerId":1134,"customerName":"Daquan Beard","phone":"(443) 748-1456","email":"at.velit@aol.com","address":"673-8314 Integer Avenue","postalZip":"31222","country":"Norway"},{"customerId":1135,"customerName":"Alexandra Mcfadden","phone":"1-226-470-0333","email":"tellus.justo.sit@outlook.couk","address":"3365 Phasellus Road","postalZip":"877389","country":"Germany"},{"customerId":1136,"customerName":"Isaac Brennan","phone":"1-923-403-2154","email":"habitant.morbi@aol.org","address":"6954 Urna. St.","postalZip":"218717","country":"Belgium"},{"customerId":1137,"customerName":"Eagan Hess","phone":"1-588-671-5306","email":"ut@aol.couk","address":"Ap #725-1376 Vivamus Rd.","postalZip":"2588","country":"Singapore"},{"customerId":1138,"customerName":"Hamilton Davis","phone":"(832) 289-5235","email":"magna.cras@google.ca","address":"P.O. Box 702, 5818 Erat St.","postalZip":"547183","country":"India"},{"customerId":1139,"customerName":"Maya Mcintyre","phone":"1-339-163-7246","email":"nunc@yahoo.ca","address":"P.O. Box 175, 5889 Et Avenue","postalZip":"30206","country":"Austria"},{"customerId":1140,"customerName":"Benedict Conrad","phone":"(361) 760-9402","email":"libero@aol.ca","address":"930-9828 Enim. Rd.","postalZip":"316434","country":"Peru"},{"customerId":1141,"customerName":"Cally Nichols","phone":"(188) 296-3978","email":"pede@icloud.ca","address":"147-3879 Tortor. St.","postalZip":"0466 DY","country":"United Kingdom"},{"customerId":1142,"customerName":"Lev Huff","phone":"1-644-984-3841","email":"tincidunt.nunc@hotmail.ca","address":"Ap #451-588 Aenean Rd.","postalZip":"510223","country":"Austria"},{"customerId":1143,"customerName":"Burton Kerr","phone":"1-308-551-1118","email":"consectetuer.adipiscing@protonmail.org","address":"Ap #130-3436 Curae Road","postalZip":"8132","country":"Austria"},{"customerId":1144,"customerName":"Dara Horn","phone":"1-437-393-2415","email":"scelerisque@protonmail.edu","address":"P.O. Box 856, 8744 Nulla. Rd.","postalZip":"706580","country":"Norway"},{"customerId":1145,"customerName":"Marshall Barrett","phone":"1-674-153-7213","email":"ipsum.primis@icloud.ca","address":"801-8227 Nullam Av.","postalZip":"76-64","country":"Nigeria"},{"customerId":1146,"customerName":"Ivy Olsen","phone":"(779) 236-5665","email":"non.quam@icloud.com","address":"Ap #399-2054 Sit Avenue","postalZip":"9517","country":"Pakistan"},{"customerId":1147,"customerName":"Callum Hurley","phone":"(228) 268-0845","email":"nam.ac.nulla@outlook.ca","address":"221-4220 Gravida Rd.","postalZip":"692817","country":"Nigeria"},{"customerId":1148,"customerName":"Hilary Barry","phone":"1-921-538-7222","email":"non.vestibulum@google.edu","address":"Ap #731-2219 At Road","postalZip":"39-652","country":"Ukraine"},{"customerId":1149,"customerName":"Yetta Wilson","phone":"1-381-155-2506","email":"odio.vel@hotmail.edu","address":"258-3369 Dis Road","postalZip":"723487","country":"Nigeria"},{"customerId":1150,"customerName":"Armando Chavez","phone":"(612) 867-3153","email":"donec.luctus@protonmail.org","address":"410-1737 Ante Avenue","postalZip":"81327","country":"Philippines"},{"customerId":1151,"customerName":"Chelsea Good","phone":"(428) 567-4223","email":"tempor.bibendum@yahoo.ca","address":"Ap #893-6132 Ligula. Road","postalZip":"43101-22691","country":"New Zealand"},{"customerId":1152,"customerName":"Craig Schmidt","phone":"1-378-734-1470","email":"turpis.vitae.purus@hotmail.couk","address":"Ap #438-8189 Est. Rd.","postalZip":"916126","country":"Ukraine"},{"customerId":1153,"customerName":"Brenda Wells","phone":"(567) 863-1757","email":"non.hendrerit@aol.com","address":"Ap #492-5578 Quis, Rd.","postalZip":"9964","country":"United States"},{"customerId":1154,"customerName":"Jackson Sullivan","phone":"1-187-130-3494","email":"mus.proin.vel@outlook.ca","address":"P.O. Box 760, 5924 Non Ave","postalZip":"17977","country":"United States"},{"customerId":1155,"customerName":"Marvin Mcknight","phone":"1-848-886-2358","email":"orci@protonmail.com","address":"1595 Quisque Street","postalZip":"4396","country":"Australia"},{"customerId":1156,"customerName":"Summer Christian","phone":"(416) 828-7112","email":"eu.enim@outlook.edu","address":"567-5210 At Av.","postalZip":"03325-08467","country":"United Kingdom"},{"customerId":1157,"customerName":"Finn Marks","phone":"1-841-738-7143","email":"scelerisque.sed@outlook.ca","address":"Ap #954-8922 Id, Av.","postalZip":"22322","country":"United Kingdom"},{"customerId":1158,"customerName":"Nita Bates","phone":"(654) 725-8233","email":"magna.a.tortor@aol.com","address":"Ap #309-3421 Commodo Road","postalZip":"975193","country":"South Korea"},{"customerId":1159,"customerName":"Briar Langley","phone":"(608) 472-7010","email":"vivamus@yahoo.ca","address":"2879 Lectus St.","postalZip":"H6C 4M4","country":"New Zealand"},{"customerId":1160,"customerName":"Laurel Cummings","phone":"1-988-134-4690","email":"velit.eget@icloud.couk","address":"Ap #788-9364 Donec Road","postalZip":"531859","country":"Indonesia"},{"customerId":1161,"customerName":"Ulric Kim","phone":"(346) 441-9341","email":"sagittis@aol.couk","address":"100-1804 Neque Street","postalZip":"1122","country":"France"},{"customerId":1162,"customerName":"Sybil Sykes","phone":"1-875-204-7862","email":"laoreet.ipsum.curabitur@outlook.ca","address":"Ap #126-5269 Fusce Rd.","postalZip":"117416","country":"Russian Federation"},{"customerId":1163,"customerName":"Leonard Hoffman","phone":"1-341-772-3286","email":"a@aol.ca","address":"444-2072 Justo St.","postalZip":"11668","country":"Russian Federation"},{"customerId":1164,"customerName":"Quon Blackwell","phone":"(831) 635-3562","email":"neque.sed@protonmail.edu","address":"204-5991 Aliquam Rd.","postalZip":"3155","country":"Philippines"},{"customerId":1165,"customerName":"Miriam Bryan","phone":"1-527-513-2857","email":"vitae.dolor@icloud.couk","address":"461-5695 Cras Avenue","postalZip":"75-27","country":"Belgium"},{"customerId":1166,"customerName":"Armand Pugh","phone":"(482) 501-1233","email":"ridiculus.mus@outlook.edu","address":"P.O. Box 947, 9910 Amet Ave","postalZip":"3411","country":"Germany"},{"customerId":1167,"customerName":"Blaze Battle","phone":"(428) 853-6886","email":"adipiscing.lacus.ut@yahoo.org","address":"P.O. Box 602, 8847 Arcu St.","postalZip":"37286","country":"Costa Rica"},{"customerId":1168,"customerName":"Calista Hensley","phone":"1-327-399-7565","email":"vulputate.ullamcorper.magna@icloud.com","address":"847-2586 Suspendisse Av.","postalZip":"776816","country":"United Kingdom"},{"customerId":1169,"customerName":"Bo Rios","phone":"1-170-647-6987","email":"in.condimentum.donec@aol.edu","address":"Ap #945-706 Ut, Rd.","postalZip":"8076","country":"Germany"},{"customerId":1170,"customerName":"Larissa Rodgers","phone":"(126) 443-8736","email":"tellus.id@protonmail.couk","address":"721-8783 Rutrum Av.","postalZip":"6659","country":"China"},{"customerId":1171,"customerName":"Shelby Cummings","phone":"(734) 275-3839","email":"a.felis@google.com","address":"Ap #533-2648 Semper St.","postalZip":"4102","country":"Chile"},{"customerId":1172,"customerName":"Rajah Haynes","phone":"(912) 376-0821","email":"erat.vel@aol.edu","address":"798-6238 Lobortis Avenue","postalZip":"879367","country":"South Africa"},{"customerId":1173,"customerName":"Eric Porter","phone":"(438) 829-8875","email":"est.congue@icloud.couk","address":"152-3129 Eget Road","postalZip":"51575","country":"Belgium"},{"customerId":1174,"customerName":"Sade Tanner","phone":"(176) 628-4565","email":"nulla.at.sem@aol.edu","address":"Ap #897-5047 Pede. St.","postalZip":"14691","country":"Russian Federation"},{"customerId":1175,"customerName":"Rooney Whitley","phone":"1-603-488-8598","email":"inceptos@icloud.net","address":"Ap #305-7788 Metus. Rd.","postalZip":"495747","country":"Netherlands"},{"customerId":1176,"customerName":"Lareina Roth","phone":"1-683-817-8779","email":"mus.aenean@hotmail.com","address":"Ap #500-9224 Nam Rd.","postalZip":"622405","country":"India"},{"customerId":1177,"customerName":"Yuli Ashley","phone":"1-527-243-1156","email":"laoreet@hotmail.net","address":"Ap #462-2830 Lorem Rd.","postalZip":"8659","country":"South Korea"},{"customerId":1178,"customerName":"Hanae Reed","phone":"1-274-288-6220","email":"cubilia.curae@outlook.edu","address":"562-9851 Vestibulum St.","postalZip":"2730","country":"Sweden"},{"customerId":1179,"customerName":"Marsden Kelley","phone":"(802) 265-9337","email":"lectus.a.sollicitudin@icloud.ca","address":"921-3613 Dis Rd.","postalZip":"36516","country":"Austria"},{"customerId":1180,"customerName":"Chandler Cooke","phone":"1-886-874-8176","email":"ultrices.vivamus@hotmail.couk","address":"Ap #440-2350 Aliquet Ave","postalZip":"75956","country":"Russian Federation"},{"customerId":1181,"customerName":"Oren Craig","phone":"(355) 808-0474","email":"sed.libero@outlook.com","address":"Ap #284-5512 Etiam Ave","postalZip":"72646","country":"United Kingdom"},{"customerId":1182,"customerName":"Cecilia Drake","phone":"(846) 325-0244","email":"magnis.dis@aol.couk","address":"P.O. Box 664, 1872 Dictum Avenue","postalZip":"865143","country":"Costa Rica"},{"customerId":1183,"customerName":"Myles Huber","phone":"(558) 433-4791","email":"non.luctus.sit@protonmail.org","address":"Ap #721-322 Arcu. Road","postalZip":"8272","country":"Russian Federation"},{"customerId":1184,"customerName":"Garrett Horton","phone":"1-303-643-5354","email":"quisque@google.com","address":"579-5270 In Road","postalZip":"5426","country":"Brazil"},{"customerId":1185,"customerName":"Summer Downs","phone":"(799) 252-8435","email":"sociis.natoque@icloud.edu","address":"1530 Mauris Rd.","postalZip":"4644","country":"Belgium"},{"customerId":1186,"customerName":"Stephen Ramirez","phone":"1-958-659-2032","email":"blandit.enim@aol.ca","address":"P.O. Box 617, 7127 Lobortis Avenue","postalZip":"142618","country":"Sweden"},{"customerId":1187,"customerName":"Alden Ochoa","phone":"(751) 226-3554","email":"phasellus.elit.pede@google.edu","address":"P.O. Box 838, 1887 Tellus. Rd.","postalZip":"83996","country":"China"},{"customerId":1188,"customerName":"Doris Moreno","phone":"(471) 824-1287","email":"nullam.feugiat.placerat@outlook.edu","address":"Ap #260-386 Orci Av.","postalZip":"210139","country":"Norway"},{"customerId":1189,"customerName":"Indigo Carey","phone":"(662) 936-5124","email":"mi.pede@yahoo.org","address":"Ap #322-3050 Magna. Road","postalZip":"45-25","country":"Turkey"},{"customerId":1190,"customerName":"Dolan Jordan","phone":"(478) 872-8613","email":"nec.malesuada@yahoo.net","address":"898-938 Nulla Ave","postalZip":"7887","country":"South Korea"},{"customerId":1191,"customerName":"Bo Dudley","phone":"(610) 335-7788","email":"euismod.et@aol.net","address":"3468 Nulla Street","postalZip":"141974","country":"China"},{"customerId":1192,"customerName":"Gillian Clemons","phone":"1-919-152-8757","email":"placerat.velit.quisque@yahoo.ca","address":"710-190 Massa. Road","postalZip":"2353","country":"Chile"},{"customerId":1193,"customerName":"Caldwell Hansen","phone":"1-661-497-3770","email":"volutpat.nulla@outlook.org","address":"919-6956 Sit Ave","postalZip":"30035","country":"Costa Rica"},{"customerId":1194,"customerName":"Chadwick Langley","phone":"1-740-424-6843","email":"pede@aol.edu","address":"Ap #557-4847 Arcu Rd.","postalZip":"75647","country":"South Africa"},{"customerId":1195,"customerName":"Robert Glass","phone":"(322) 300-6525","email":"blandit@icloud.org","address":"746-2653 Eu Av.","postalZip":"432218","country":"Norway"},{"customerId":1196,"customerName":"Rogan Gibson","phone":"(173) 446-7654","email":"ipsum.suspendisse.non@google.edu","address":"P.O. Box 548, 8634 Fringilla Rd.","postalZip":"1554-0130","country":"France"},{"customerId":1197,"customerName":"Shay Chase","phone":"1-817-937-9663","email":"eu@outlook.couk","address":"Ap #130-5565 Faucibus Rd.","postalZip":"3221","country":"Italy"},{"customerId":1198,"customerName":"Hayes Griffin","phone":"(219) 652-0611","email":"ultrices.duis@hotmail.ca","address":"Ap #405-6309 Est. Rd.","postalZip":"19755","country":"Netherlands"},{"customerId":1199,"customerName":"Emerson Trujillo","phone":"(142) 333-1545","email":"suspendisse.aliquet.molestie@google.couk","address":"536-2607 Ligula. Av.","postalZip":"17575","country":"Indonesia"},{"customerId":1200,"customerName":"Charde Sellers","phone":"(765) 208-5630","email":"leo.in@outlook.couk","address":"782-8699 Consequat, Rd.","postalZip":"63413-332","country":"Norway"},{"customerId":1201,"customerName":"Kimberly Bruce","phone":"1-463-679-5074","email":"vivamus.sit.amet@aol.net","address":"923-5701 Aliquam St.","postalZip":"70587","country":"Indonesia"},{"customerId":1202,"customerName":"Cynthia Guzman","phone":"1-331-975-8907","email":"suspendisse@google.com","address":"8055 Dapibus Av.","postalZip":"06404","country":"Norway"},{"customerId":1203,"customerName":"Quyn Cotton","phone":"(914) 432-9528","email":"convallis.ligula@google.ca","address":"7102 Et, Av.","postalZip":"03544","country":"United Kingdom"},{"customerId":1204,"customerName":"Harding Hunter","phone":"1-777-787-2274","email":"egestas.aliquam@protonmail.org","address":"956-2959 Aliquam Avenue","postalZip":"8823","country":"Norway"},{"customerId":1205,"customerName":"Sara Blankenship","phone":"1-766-993-7718","email":"ante.blandit.viverra@icloud.edu","address":"Ap #765-4621 Nulla St.","postalZip":"WA7U 5DD","country":"Turkey"},{"customerId":1206,"customerName":"Karen Mcfarland","phone":"1-101-451-0174","email":"sed.dui@aol.edu","address":"379-132 Vulputate Avenue","postalZip":"30200","country":"Poland"},{"customerId":1207,"customerName":"Freya Skinner","phone":"1-859-639-2765","email":"quis.arcu@outlook.ca","address":"733-152 In Rd.","postalZip":"66842","country":"France"},{"customerId":1208,"customerName":"Minerva Blankenship","phone":"(547) 979-5625","email":"luctus.ipsum@yahoo.com","address":"311-4470 Arcu Avenue","postalZip":"12886","country":"Netherlands"},{"customerId":1209,"customerName":"Cody Figueroa","phone":"(312) 873-1696","email":"ipsum.dolor@hotmail.net","address":"5812 Est, St.","postalZip":"444566","country":"Italy"},{"customerId":1210,"customerName":"Christian Berger","phone":"(827) 212-4278","email":"bibendum.ullamcorper@outlook.org","address":"Ap #976-925 Eu Ave","postalZip":"73246","country":"Costa Rica"},{"customerId":1211,"customerName":"Geraldine Benson","phone":"(686) 771-0523","email":"rutrum.justo@google.com","address":"468-9285 Sit Av.","postalZip":"4178 LZ","country":"China"},{"customerId":1212,"customerName":"Rhona Mckay","phone":"1-249-718-6439","email":"eu.arcu@protonmail.net","address":"783-2662 Malesuada St.","postalZip":"4734","country":"France"},{"customerId":1213,"customerName":"Mohammad Holland","phone":"1-616-294-7414","email":"elit.a@google.net","address":"456-4028 Cursus St.","postalZip":"37507","country":"Germany"},{"customerId":1214,"customerName":"Fulton Lowery","phone":"(971) 538-3365","email":"placerat.velit@yahoo.net","address":"435-6035 Blandit Rd.","postalZip":"481178","country":"Canada"},{"customerId":1215,"customerName":"Shaine Stevenson","phone":"1-224-316-1576","email":"eleifend.cras.sed@google.org","address":"Ap #800-1048 Accumsan St.","postalZip":"5507","country":"Poland"},{"customerId":1216,"customerName":"Shad Moses","phone":"1-663-446-6058","email":"dui.in@google.com","address":"P.O. Box 202, 4862 Vitae Rd.","postalZip":"42806","country":"United States"},{"customerId":1217,"customerName":"Colt Stewart","phone":"1-531-643-7652","email":"est.arcu@outlook.org","address":"166-7253 Senectus St.","postalZip":"71-760","country":"Ukraine"},{"customerId":1218,"customerName":"Prescott Newton","phone":"(673) 986-0514","email":"felis.purus@hotmail.org","address":"P.O. Box 359, 7008 Etiam St.","postalZip":"69759","country":"New Zealand"},{"customerId":1219,"customerName":"Hashim Myers","phone":"1-299-612-8826","email":"aliquet.magna@google.couk","address":"Ap #799-8129 Mi. St.","postalZip":"76081","country":"Pakistan"},{"customerId":1220,"customerName":"Gisela Simpson","phone":"(781) 688-2283","email":"lorem@protonmail.org","address":"994-7036 Laoreet, Road","postalZip":"0628","country":"France"},{"customerId":1221,"customerName":"Alice Beasley","phone":"(861) 125-1151","email":"lectus@aol.net","address":"191-8262 Quam. Av.","postalZip":"61784","country":"Russian Federation"},{"customerId":1222,"customerName":"Baxter Alvarez","phone":"1-597-217-4715","email":"aliquam.adipiscing@aol.org","address":"497-5274 Et, Street","postalZip":"50606","country":"United Kingdom"},{"customerId":1223,"customerName":"Eric Wallace","phone":"(828) 814-2311","email":"sociosqu.ad@google.edu","address":"Ap #851-8445 Fusce Avenue","postalZip":"371855","country":"Russian Federation"},{"customerId":1224,"customerName":"Virginia Nichols","phone":"(158) 415-6514","email":"mattis.ornare@hotmail.com","address":"2551 Orci Rd.","postalZip":"93284","country":"China"},{"customerId":1225,"customerName":"Joelle Aguirre","phone":"(854) 516-7135","email":"velit@aol.ca","address":"989-339 Non Ave","postalZip":"31922","country":"Philippines"},{"customerId":1226,"customerName":"Amanda Hebert","phone":"1-232-775-8274","email":"ut.erat.sed@hotmail.org","address":"586-9506 Ridiculus Ave","postalZip":"9885","country":"Peru"},{"customerId":1227,"customerName":"Ryder Vang","phone":"1-575-823-1726","email":"libero@google.net","address":"P.O. Box 223, 8835 Vestibulum Road","postalZip":"7134","country":"Turkey"},{"customerId":1228,"customerName":"Cole Hebert","phone":"1-795-415-3404","email":"aliquet.sem.ut@google.net","address":"759-1631 Eget Rd.","postalZip":"26-729","country":"India"},{"customerId":1229,"customerName":"Zelenia Goff","phone":"(970) 563-5745","email":"nisi.aenean.eget@google.org","address":"453-9241 Non, Road","postalZip":"95-537","country":"Philippines"},{"customerId":1230,"customerName":"Duncan Little","phone":"1-282-913-6876","email":"gravida.nunc.sed@outlook.org","address":"P.O. Box 551, 1705 Morbi St.","postalZip":"36-75","country":"Indonesia"},{"customerId":1231,"customerName":"Zephania Burch","phone":"(348) 442-1242","email":"pede.cras.vulputate@yahoo.ca","address":"5084 Vitae Rd.","postalZip":"21965","country":"Peru"},{"customerId":1232,"customerName":"Basil Lloyd","phone":"1-341-344-7427","email":"nulla.tempor@icloud.ca","address":"Ap #843-7443 Integer Rd.","postalZip":"345108","country":"Netherlands"},{"customerId":1233,"customerName":"Melyssa Brooks","phone":"(508) 884-1383","email":"montes.nascetur.ridiculus@hotmail.edu","address":"Ap #456-6388 Rutrum St.","postalZip":"16-211","country":"New Zealand"},{"customerId":1234,"customerName":"Aurora Leonard","phone":"(316) 665-6644","email":"ipsum.primis@icloud.org","address":"428-6242 Sit Street","postalZip":"973687","country":"Sweden"},{"customerId":1235,"customerName":"Anika Le","phone":"(685) 626-7388","email":"primis.in@yahoo.couk","address":"Ap #640-168 Phasellus Street","postalZip":"8873","country":"Sweden"},{"customerId":1236,"customerName":"Quintessa Shepard","phone":"1-226-348-8571","email":"consectetuer.mauris@outlook.couk","address":"Ap #794-1498 Turpis. St.","postalZip":"35015","country":"Ukraine"},{"customerId":1237,"customerName":"Quintessa Walter","phone":"1-757-517-3627","email":"accumsan.convallis@protonmail.edu","address":"788 Ornare. Av.","postalZip":"340373","country":"Spain"},{"customerId":1238,"customerName":"Jeanette Ingram","phone":"1-408-761-8781","email":"lacinia.orci@icloud.org","address":"751-744 Molestie. Rd.","postalZip":"7822","country":"Ukraine"},{"customerId":1239,"customerName":"Magee Logan","phone":"1-762-419-3843","email":"tincidunt.vehicula@google.org","address":"369-2642 Proin Ave","postalZip":"BW82 2KE","country":"Mexico"},{"customerId":1240,"customerName":"Reagan Clements","phone":"1-412-723-3895","email":"pharetra.quisque@google.org","address":"Ap #110-6548 Tempus, Av.","postalZip":"E3W 5E7","country":"Austria"},{"customerId":1241,"customerName":"Dennis Taylor","phone":"(739) 486-3238","email":"eleifend.non@google.net","address":"Ap #933-6271 Consequat Rd.","postalZip":"265283","country":"France"},{"customerId":1242,"customerName":"Alvin Ray","phone":"1-475-608-8144","email":"ligula.aenean@icloud.net","address":"389-1590 Rutrum Street","postalZip":"24343-512","country":"Chile"},{"customerId":1243,"customerName":"Devin Sweeney","phone":"1-836-658-2998","email":"dolor@outlook.com","address":"3386 Fermentum Road","postalZip":"Y64 1TQ","country":"Norway"},{"customerId":1244,"customerName":"Rajah Duke","phone":"(828) 875-5614","email":"nec@google.net","address":"Ap #103-6999 Tempus Road","postalZip":"403585","country":"Ukraine"},{"customerId":1245,"customerName":"Yoshio Olson","phone":"1-641-435-1196","email":"cubilia.curae@google.edu","address":"176-3215 Sed Road","postalZip":"15288-379","country":"United Kingdom"},{"customerId":1246,"customerName":"Reuben Hodge","phone":"1-239-725-4351","email":"sit.amet@outlook.org","address":"P.O. Box 809, 4971 Maecenas Rd.","postalZip":"15787-48453","country":"Sweden"},{"customerId":1247,"customerName":"Aline Mccarty","phone":"1-710-583-3497","email":"odio.semper.cursus@aol.couk","address":"7836 Faucibus Rd.","postalZip":"7178","country":"Ukraine"},{"customerId":1248,"customerName":"Kylie Kim","phone":"1-539-363-6835","email":"mi.enim.condimentum@icloud.couk","address":"P.O. Box 463, 3487 Dictum Road","postalZip":"18877","country":"Nigeria"},{"customerId":1249,"customerName":"Sage Bowers","phone":"1-224-410-8556","email":"eget.laoreet@outlook.net","address":"Ap #539-2641 A, Avenue","postalZip":"18446","country":"South Korea"},{"customerId":1250,"customerName":"Brynn Miller","phone":"(386) 396-7094","email":"lectus@hotmail.couk","address":"168-7085 Egestas. Rd.","postalZip":"14794","country":"Colombia"},{"customerId":1251,"customerName":"Cruz Durham","phone":"(678) 223-1384","email":"in.cursus@icloud.ca","address":"Ap #116-2724 Aliquam St.","postalZip":"726827","country":"India"},{"customerId":1252,"customerName":"Raphael Lambert","phone":"(647) 930-4484","email":"eleifend.nec.malesuada@yahoo.couk","address":"Ap #342-2310 Integer Av.","postalZip":"829183","country":"Netherlands"},{"customerId":1253,"customerName":"Barrett Barber","phone":"(257) 348-8468","email":"massa.mauris@yahoo.ca","address":"822-9335 Nunc Rd.","postalZip":"455544","country":"Chile"},{"customerId":1254,"customerName":"Alfonso Tran","phone":"(375) 735-1642","email":"a@aol.couk","address":"723-2618 In Rd.","postalZip":"07310","country":"France"},{"customerId":1255,"customerName":"Quamar Duran","phone":"(575) 354-6717","email":"sapien@protonmail.net","address":"Ap #889-6343 Sociosqu Avenue","postalZip":"88438-60533","country":"China"},{"customerId":1256,"customerName":"Doris Huff","phone":"1-734-846-7929","email":"lorem.donec@outlook.ca","address":"P.O. Box 557, 9450 Dictum Road","postalZip":"460487","country":"Spain"},{"customerId":1257,"customerName":"Anastasia Morrow","phone":"(930) 605-1289","email":"lectus.nullam.suscipit@yahoo.org","address":"482-1037 Blandit Ave","postalZip":"7115","country":"Philippines"},{"customerId":1258,"customerName":"Ashely Trujillo","phone":"1-516-852-1250","email":"vitae.sodales.at@yahoo.couk","address":"Ap #859-4386 Rutrum Street","postalZip":"03111","country":"South Africa"},{"customerId":1259,"customerName":"Adrienne Mcconnell","phone":"1-286-881-6866","email":"at.fringilla@icloud.ca","address":"464-6392 Convallis Road","postalZip":"8538-8927","country":"Spain"},{"customerId":1260,"customerName":"Cassandra Sanders","phone":"1-635-255-4629","email":"consectetuer@icloud.edu","address":"303-3212 Sollicitudin St.","postalZip":"14457","country":"United States"},{"customerId":1261,"customerName":"Cameron Valentine","phone":"1-600-664-6489","email":"sollicitudin.orci@aol.edu","address":"P.O. Box 834, 1814 Et Rd.","postalZip":"37162","country":"New Zealand"},{"customerId":1262,"customerName":"Norman Griffin","phone":"(419) 768-0314","email":"neque.vitae@aol.net","address":"P.O. Box 556, 1579 Scelerisque Ave","postalZip":"881244","country":"India"},{"customerId":1263,"customerName":"Carlos Ramsey","phone":"1-435-347-3869","email":"vestibulum@yahoo.couk","address":"3943 Et St.","postalZip":"33416","country":"Germany"},{"customerId":1264,"customerName":"Mariam Howe","phone":"(639) 461-4086","email":"velit.dui.semper@protonmail.couk","address":"Ap #931-7415 Faucibus Rd.","postalZip":"427079","country":"India"},{"customerId":1265,"customerName":"MacKenzie Alford","phone":"1-894-538-1015","email":"tincidunt.neque.vitae@aol.ca","address":"Ap #937-6343 Dictum. St.","postalZip":"95268","country":"Philippines"},{"customerId":1266,"customerName":"Graham Holloway","phone":"1-914-671-1572","email":"facilisis.eget@google.ca","address":"Ap #741-5080 Facilisi. Street","postalZip":"51478","country":"Philippines"},{"customerId":1267,"customerName":"Heidi Mays","phone":"1-734-713-2514","email":"sem@hotmail.net","address":"396-4900 Sem Rd.","postalZip":"1446-8660","country":"New Zealand"},{"customerId":1268,"customerName":"Amelia Farmer","phone":"1-317-724-8376","email":"libero.donec@yahoo.edu","address":"Ap #662-8397 Lorem Street","postalZip":"Y6P 7N7","country":"Russian Federation"},{"customerId":1269,"customerName":"Holly Hernandez","phone":"1-565-529-5693","email":"placerat.orci.lacus@aol.org","address":"7601 Vel Ave","postalZip":"4786","country":"Turkey"},{"customerId":1270,"customerName":"Philip Hurley","phone":"1-605-754-4983","email":"nibh.sit@google.org","address":"Ap #757-1677 Vivamus Ave","postalZip":"40188","country":"Russian Federation"},{"customerId":1271,"customerName":"Veronica Maddox","phone":"1-342-207-4242","email":"ac.metus.vitae@icloud.ca","address":"Ap #301-4476 Orci, Street","postalZip":"236475","country":"Indonesia"},{"customerId":1272,"customerName":"Nolan Wallace","phone":"1-625-178-4338","email":"donec@hotmail.ca","address":"838-1885 Non, Av.","postalZip":"11705","country":"Austria"},{"customerId":1273,"customerName":"Grace Ford","phone":"(771) 717-4359","email":"ornare@aol.couk","address":"1650 Sed Ave","postalZip":"853817","country":"Philippines"},{"customerId":1274,"customerName":"Imelda Bird","phone":"1-256-394-3476","email":"in.hendrerit.consectetuer@hotmail.com","address":"Ap #207-873 Faucibus Ave","postalZip":"58544","country":"Costa Rica"},{"customerId":1275,"customerName":"Amos Barnett","phone":"(217) 753-0167","email":"vestibulum.massa.rutrum@outlook.org","address":"Ap #504-7391 Id Road","postalZip":"428658","country":"Brazil"},{"customerId":1276,"customerName":"Vance Davidson","phone":"(632) 848-0851","email":"tortor@google.com","address":"8164 Libero. Av.","postalZip":"59-452","country":"China"},{"customerId":1277,"customerName":"George Valdez","phone":"1-267-365-8404","email":"quisque@icloud.couk","address":"580 Sed Avenue","postalZip":"9231","country":"Colombia"},{"customerId":1278,"customerName":"Rama Dejesus","phone":"(994) 521-1473","email":"duis.cursus@yahoo.couk","address":"395-357 Tellus Av.","postalZip":"3577","country":"United Kingdom"},{"customerId":1279,"customerName":"Tyler Ferguson","phone":"1-737-618-0663","email":"arcu@hotmail.edu","address":"P.O. Box 486, 7908 Tempor Av.","postalZip":"1354","country":"Pakistan"},{"customerId":1280,"customerName":"Fallon Ryan","phone":"(673) 362-7218","email":"quis.arcu@hotmail.edu","address":"916-7982 Egestas, Rd.","postalZip":"73151","country":"Poland"},{"customerId":1281,"customerName":"Rhiannon Riddle","phone":"(379) 427-8051","email":"mi.lacinia@icloud.org","address":"1538 Ut Avenue","postalZip":"96418","country":"Chile"},{"customerId":1282,"customerName":"Mannix Stokes","phone":"1-952-667-7440","email":"tempus@icloud.couk","address":"Ap #465-924 Placerat Rd.","postalZip":"8941","country":"Netherlands"},{"customerId":1283,"customerName":"Kirsten Beard","phone":"(386) 552-8516","email":"ipsum@hotmail.com","address":"Ap #314-2610 Donec Rd.","postalZip":"865232","country":"Netherlands"},{"customerId":1284,"customerName":"Colton Greer","phone":"(544) 639-1708","email":"eros.proin@icloud.net","address":"Ap #905-1422 Non Road","postalZip":"528183","country":"Costa Rica"},{"customerId":1285,"customerName":"Beck Rasmussen","phone":"(701) 185-3456","email":"sagittis@protonmail.edu","address":"6434 Amet Road","postalZip":"27272","country":"Brazil"},{"customerId":1286,"customerName":"Driscoll Walter","phone":"(315) 868-2551","email":"natoque.penatibus@yahoo.net","address":"6840 Ac Avenue","postalZip":"39757","country":"Colombia"},{"customerId":1287,"customerName":"Guinevere Bolton","phone":"1-560-309-8068","email":"mauris.vel.turpis@aol.org","address":"9282 Fringilla Street","postalZip":"635531","country":"Sweden"},{"customerId":1288,"customerName":"Talon Barr","phone":"(281) 571-6497","email":"tellus.phasellus@protonmail.edu","address":"8955 Tincidunt Rd.","postalZip":"A8M 4Z5","country":"Pakistan"},{"customerId":1289,"customerName":"Fatima Mccoy","phone":"(685) 483-3596","email":"mus.proin@yahoo.org","address":"Ap #684-6010 Etiam Ave","postalZip":"25617","country":"Netherlands"},{"customerId":1290,"customerName":"Ivana Mays","phone":"1-858-558-1483","email":"ultricies.adipiscing.enim@protonmail.ca","address":"5110 Ut Street","postalZip":"B2W 3L8","country":"Belgium"},{"customerId":1291,"customerName":"Kenneth Burnett","phone":"1-873-670-1824","email":"lectus.pede.et@icloud.edu","address":"Ap #350-2238 Orci. Road","postalZip":"289227","country":"Netherlands"},{"customerId":1292,"customerName":"Raymond Daniel","phone":"1-543-681-3471","email":"odio.a@yahoo.com","address":"266-9313 Urna St.","postalZip":"49309","country":"Italy"},{"customerId":1293,"customerName":"Lael Delacruz","phone":"(542) 282-5126","email":"adipiscing@outlook.net","address":"742-7498 Dis Avenue","postalZip":"68087","country":"Costa Rica"},{"customerId":1294,"customerName":"Stephen Navarro","phone":"(964) 652-1134","email":"quis.arcu@yahoo.edu","address":"P.O. Box 777, 6051 Ipsum Ave","postalZip":"3769","country":"Poland"},{"customerId":1295,"customerName":"Keith Sykes","phone":"(240) 371-6114","email":"sodales.nisi@google.couk","address":"P.O. Box 712, 4196 Sed Road","postalZip":"3124","country":"Italy"},{"customerId":1296,"customerName":"Hop Wheeler","phone":"(882) 852-2134","email":"tellus.id@aol.couk","address":"1148 Quisque St.","postalZip":"07388","country":"Vietnam"},{"customerId":1297,"customerName":"Austin Browning","phone":"1-564-808-1387","email":"velit.sed@protonmail.org","address":"Ap #508-3125 Sollicitudin Rd.","postalZip":"153452","country":"Russian Federation"},{"customerId":1298,"customerName":"Ulric Harrington","phone":"(404) 767-7164","email":"lectus@yahoo.edu","address":"727-6859 Metus. Road","postalZip":"10-672","country":"Norway"},{"customerId":1299,"customerName":"Hanae Hyde","phone":"1-578-859-4133","email":"non.justo.proin@protonmail.net","address":"P.O. Box 780, 4090 Dapibus Av.","postalZip":"61255","country":"Ireland"},{"customerId":1300,"customerName":"Baker Morse","phone":"(826) 500-9636","email":"amet.dapibus@yahoo.couk","address":"570-7315 Bibendum Rd.","postalZip":"36605","country":"India"},{"customerId":1301,"customerName":"Evangeline Leon","phone":"1-658-285-7538","email":"ac.turpis@yahoo.com","address":"Ap #632-3608 Ac St.","postalZip":"25893-07660","country":"Norway"},{"customerId":1302,"customerName":"Noble Donaldson","phone":"(672) 816-8714","email":"quis@icloud.net","address":"4300 Iaculis, Ave","postalZip":"02707","country":"Colombia"},{"customerId":1303,"customerName":"Kalia Colon","phone":"(427) 123-2426","email":"vel.pede.blandit@hotmail.couk","address":"P.O. Box 870, 3590 Eleifend. St.","postalZip":"206846","country":"Indonesia"},{"customerId":1304,"customerName":"Linus Hess","phone":"1-619-136-5385","email":"nunc.sed@outlook.ca","address":"Ap #880-3705 Eu, Street","postalZip":"L3X 5S1","country":"Spain"},{"customerId":1305,"customerName":"Colt Stout","phone":"1-543-909-7130","email":"suspendisse.sed.dolor@yahoo.ca","address":"P.O. Box 653, 6054 Massa Rd.","postalZip":"T2T 3W6","country":"Netherlands"},{"customerId":1306,"customerName":"Ronan Taylor","phone":"1-753-561-8886","email":"dolor@protonmail.edu","address":"Ap #207-9022 Ac St.","postalZip":"268624","country":"Philippines"},{"customerId":1307,"customerName":"Rahim Roberson","phone":"1-278-767-3521","email":"nunc.quisque@google.net","address":"720-6909 Non, Rd.","postalZip":"5815","country":"South Korea"},{"customerId":1308,"customerName":"Hayden Crane","phone":"(335) 968-3323","email":"porta.elit.a@aol.com","address":"Ap #920-4101 Quis St.","postalZip":"425565","country":"Spain"},{"customerId":1309,"customerName":"Halla Hooper","phone":"(259) 162-0866","email":"ac.mattis@aol.com","address":"P.O. Box 253, 4701 Fusce Rd.","postalZip":"58871-613","country":"Ukraine"},{"customerId":1310,"customerName":"Mohammad Morse","phone":"(516) 866-3151","email":"semper.et@outlook.org","address":"Ap #774-5318 Mauris Ave","postalZip":"63371","country":"Indonesia"},{"customerId":1311,"customerName":"Yeo Summers","phone":"(677) 386-8129","email":"sed.tortor@outlook.com","address":"P.O. Box 172, 7153 Mauris. Ave","postalZip":"10808","country":"United Kingdom"},{"customerId":1312,"customerName":"Abdul Bartlett","phone":"(368) 654-6656","email":"malesuada@outlook.com","address":"P.O. Box 353, 3630 Orci, Street","postalZip":"4786","country":"Chile"},{"customerId":1313,"customerName":"Alvin Kirk","phone":"1-561-308-0898","email":"mauris@protonmail.ca","address":"253-692 Ipsum Street","postalZip":"I6B 7XE","country":"Vietnam"},{"customerId":1314,"customerName":"Cora Jimenez","phone":"1-748-974-5722","email":"aliquet.diam.sed@yahoo.com","address":"670-5496 Sed Street","postalZip":"43176","country":"Mexico"},{"customerId":1315,"customerName":"Sybill Osborn","phone":"1-447-771-6596","email":"ultricies@google.ca","address":"659-6176 Mauris Road","postalZip":"589008","country":"United States"},{"customerId":1316,"customerName":"Dominique Sandoval","phone":"1-787-906-6357","email":"tellus.imperdiet@outlook.ca","address":"440-5486 Eu Road","postalZip":"9191","country":"Brazil"},{"customerId":1317,"customerName":"Kyra Gross","phone":"1-380-721-5074","email":"quis.accumsan.convallis@google.net","address":"762-318 Vestibulum St.","postalZip":"88-859","country":"Sweden"},{"customerId":1318,"customerName":"Joelle Buckner","phone":"(881) 445-5503","email":"malesuada.vel.venenatis@yahoo.com","address":"P.O. Box 523, 2613 Dui, Road","postalZip":"909421","country":"Australia"},{"customerId":1319,"customerName":"Kyle Santiago","phone":"(829) 759-2866","email":"at.velit@yahoo.couk","address":"902-9693 Elit, St.","postalZip":"96721-726","country":"China"},{"customerId":1320,"customerName":"Colorado Cook","phone":"1-413-651-3683","email":"at.fringilla.purus@yahoo.ca","address":"Ap #819-1809 In Street","postalZip":"1808","country":"Italy"},{"customerId":1321,"customerName":"Lev Robinson","phone":"1-196-234-2414","email":"sed.congue.elit@icloud.net","address":"Ap #223-9304 At Avenue","postalZip":"V0Z 7E1","country":"Sweden"},{"customerId":1322,"customerName":"Linus Lloyd","phone":"1-944-270-7136","email":"diam@outlook.edu","address":"Ap #767-5684 Lobortis. Avenue","postalZip":"S5G 2L0","country":"Indonesia"},{"customerId":1323,"customerName":"Chaim Kinney","phone":"1-555-209-8729","email":"ac@google.org","address":"Ap #299-238 Lobortis Rd.","postalZip":"18474","country":"Poland"},{"customerId":1324,"customerName":"Keane Meadows","phone":"(356) 754-9635","email":"vitae.sodales@hotmail.ca","address":"Ap #698-3225 Donec Ave","postalZip":"28357-282","country":"Australia"},{"customerId":1325,"customerName":"Amaya Carroll","phone":"1-285-137-8225","email":"ac.metus@protonmail.edu","address":"204-6242 Nunc St.","postalZip":"66321-333","country":"Belgium"},{"customerId":1326,"customerName":"Hayfa Yang","phone":"1-518-607-9630","email":"augue@aol.ca","address":"P.O. Box 777, 611 Dui, St.","postalZip":"88577","country":"Australia"},{"customerId":1327,"customerName":"Jenette Rivera","phone":"1-117-899-8340","email":"porta@hotmail.couk","address":"6330 Erat Road","postalZip":"1156","country":"Spain"},{"customerId":1328,"customerName":"Oren Faulkner","phone":"(626) 935-7176","email":"pretium.et@google.edu","address":"976-459 Orci, Road","postalZip":"2248","country":"Turkey"},{"customerId":1329,"customerName":"Jakeem Hopkins","phone":"1-821-356-4816","email":"quisque.fringilla.euismod@yahoo.com","address":"Ap #163-6401 Orci. Street","postalZip":"17747","country":"Canada"},{"customerId":1330,"customerName":"Dana Walker","phone":"(613) 682-2416","email":"mauris@google.couk","address":"231-3124 Ultrices Avenue","postalZip":"584075","country":"South Korea"},{"customerId":1331,"customerName":"Griffith Hardin","phone":"(601) 585-9447","email":"varius.et@google.net","address":"Ap #363-9006 Aliquam Ave","postalZip":"8465-8387","country":"Pakistan"},{"customerId":1332,"customerName":"Axel Horn","phone":"(354) 604-8388","email":"libero.dui@hotmail.net","address":"Ap #684-3222 Purus Street","postalZip":"50615","country":"Canada"},{"customerId":1333,"customerName":"Raya Ochoa","phone":"(547) 494-1328","email":"donec.fringilla@yahoo.org","address":"Ap #383-3711 Aliquam Rd.","postalZip":"566332","country":"United States"},{"customerId":1334,"customerName":"Berk Best","phone":"1-783-723-4745","email":"suspendisse.aliquet@google.net","address":"218-782 Proin Av.","postalZip":"30214","country":"Pakistan"},{"customerId":1335,"customerName":"Roanna Rodriquez","phone":"1-351-606-1374","email":"maecenas.iaculis.aliquet@yahoo.couk","address":"Ap #435-2602 Nunc Street","postalZip":"56724","country":"Netherlands"},{"customerId":1336,"customerName":"Simon Navarro","phone":"(776) 407-3328","email":"condimentum.donec@hotmail.edu","address":"500-2422 Lacinia Road","postalZip":"65-796","country":"Australia"},{"customerId":1337,"customerName":"Jaime Sullivan","phone":"(444) 875-8366","email":"odio@yahoo.couk","address":"P.O. Box 248, 6669 Sem Ave","postalZip":"253020","country":"Australia"},{"customerId":1338,"customerName":"Boris Fowler","phone":"(276) 788-0236","email":"duis.gravida@outlook.org","address":"738-2917 Nibh Avenue","postalZip":"11808","country":"New Zealand"},{"customerId":1339,"customerName":"Xenos Newman","phone":"(866) 561-7975","email":"feugiat.metus@hotmail.couk","address":"7339 Morbi Ave","postalZip":"64462","country":"Austria"},{"customerId":1340,"customerName":"Hayley Russell","phone":"(150) 601-3338","email":"vel.pede@yahoo.com","address":"6306 Placerat, Street","postalZip":"3627","country":"Russian Federation"},{"customerId":1341,"customerName":"Bernard Frederick","phone":"(670) 424-2679","email":"at.velit.cras@aol.ca","address":"P.O. Box 388, 8445 Condimentum. Ave","postalZip":"487516","country":"Italy"},{"customerId":1342,"customerName":"Desiree Williams","phone":"(250) 588-7416","email":"sollicitudin.a@icloud.org","address":"796-3664 Lobortis Avenue","postalZip":"87204","country":"South Korea"},{"customerId":1343,"customerName":"Clare Bowen","phone":"1-346-496-3723","email":"nullam.vitae.diam@outlook.couk","address":"479-6977 Gravida Av.","postalZip":"9716 QG","country":"Turkey"},{"customerId":1344,"customerName":"Colorado Ochoa","phone":"(231) 914-2689","email":"in.magna@hotmail.net","address":"881-2543 Morbi St.","postalZip":"647653","country":"Mexico"},{"customerId":1345,"customerName":"Idona Gates","phone":"(264) 925-3735","email":"inceptos.hymenaeos@google.ca","address":"929-2560 Accumsan Street","postalZip":"249589","country":"Vietnam"},{"customerId":1346,"customerName":"Dalton Simpson","phone":"1-568-501-2571","email":"pharetra@aol.edu","address":"631-5847 Aliquet Ave","postalZip":"44554","country":"United States"},{"customerId":1347,"customerName":"Tate Santiago","phone":"(978) 525-5134","email":"nunc.in.at@icloud.org","address":"P.O. Box 355, 283 Ridiculus Ave","postalZip":"8719","country":"Mexico"},{"customerId":1348,"customerName":"Demetrius Boyle","phone":"1-863-361-1919","email":"per.conubia@aol.couk","address":"Ap #455-1160 Nam St.","postalZip":"46594","country":"Belgium"},{"customerId":1349,"customerName":"Walter Dudley","phone":"1-662-882-1484","email":"vitae.aliquet@aol.net","address":"396-1095 Augue Street","postalZip":"86113","country":"South Africa"},{"customerId":1350,"customerName":"Buckminster Knapp","phone":"1-721-445-1634","email":"fringilla.donec@aol.com","address":"463-3365 Tellus. Street","postalZip":"3845","country":"Mexico"},{"customerId":1351,"customerName":"Claudia Monroe","phone":"(377) 474-8872","email":"libero.mauris.aliquam@protonmail.ca","address":"Ap #631-2128 Orci Avenue","postalZip":"45-114","country":"Australia"},{"customerId":1352,"customerName":"Perry Barnes","phone":"(376) 706-8457","email":"amet@google.net","address":"768-739 Integer Ave","postalZip":"543444","country":"Italy"},{"customerId":1353,"customerName":"Rylee Manning","phone":"1-145-872-5110","email":"lorem.fringilla.ornare@hotmail.org","address":"P.O. Box 743, 9906 Elit, St.","postalZip":"94671","country":"Ireland"},{"customerId":1354,"customerName":"Thane Velez","phone":"(477) 965-7329","email":"risus@yahoo.net","address":"4619 Nisl Road","postalZip":"5831","country":"Poland"},{"customerId":1355,"customerName":"Karen Padilla","phone":"(555) 480-6185","email":"fringilla.est@yahoo.edu","address":"Ap #291-7380 Non St.","postalZip":"41791","country":"China"},{"customerId":1356,"customerName":"Jeremy Haney","phone":"1-503-552-3914","email":"varius.orci@hotmail.couk","address":"Ap #982-1886 Justo St.","postalZip":"416248","country":"Germany"},{"customerId":1357,"customerName":"Illiana Henderson","phone":"(848) 154-5971","email":"ac.urna@aol.net","address":"462-1517 Convallis Street","postalZip":"19712","country":"Chile"},{"customerId":1358,"customerName":"Quon Snyder","phone":"(258) 274-6291","email":"dictum.placerat@icloud.com","address":"202-3794 Odio. Av.","postalZip":"675528","country":"China"},{"customerId":1359,"customerName":"Rogan Adkins","phone":"(834) 232-7960","email":"senectus@icloud.edu","address":"P.O. Box 446, 7362 Proin St.","postalZip":"07481","country":"Norway"},{"customerId":1360,"customerName":"Delilah Greene","phone":"1-641-330-0447","email":"sagittis.augue@google.com","address":"7027 Pellentesque. St.","postalZip":"8727-8221","country":"India"},{"customerId":1361,"customerName":"Quynn Sandoval","phone":"(955) 103-3732","email":"nec.ante.maecenas@aol.com","address":"P.O. Box 247, 5287 Pellentesque Av.","postalZip":"84-68","country":"Nigeria"},{"customerId":1362,"customerName":"Lydia Sargent","phone":"1-856-740-7823","email":"a.arcu@icloud.couk","address":"785-6677 Arcu. Rd.","postalZip":"86286","country":"India"},{"customerId":1363,"customerName":"Marshall Dawson","phone":"1-416-827-7501","email":"a.sollicitudin.orci@icloud.couk","address":"698-4234 Consectetuer Ave","postalZip":"16607","country":"Colombia"},{"customerId":1364,"customerName":"Ivan O'Neill","phone":"(455) 224-7425","email":"natoque@google.net","address":"P.O. Box 148, 1124 Ultrices Rd.","postalZip":"61073","country":"Singapore"},{"customerId":1365,"customerName":"Nash Camacho","phone":"1-997-274-3587","email":"donec@protonmail.org","address":"Ap #357-6667 Mi Ave","postalZip":"34782","country":"Russian Federation"},{"customerId":1366,"customerName":"Brynn Forbes","phone":"(975) 296-1204","email":"vitae.sodales.at@outlook.net","address":"P.O. Box 993, 945 Faucibus. Ave","postalZip":"226329","country":"Netherlands"},{"customerId":1367,"customerName":"Guinevere Cote","phone":"1-389-545-7549","email":"posuere.vulputate@icloud.net","address":"341-5041 Nunc Rd.","postalZip":"4043","country":"China"},{"customerId":1368,"customerName":"Fritz Mcdowell","phone":"(624) 556-6133","email":"nulla.at@protonmail.couk","address":"P.O. Box 267, 5900 Arcu Rd.","postalZip":"9117 YN","country":"Vietnam"},{"customerId":1369,"customerName":"Abel Rollins","phone":"1-935-533-1320","email":"integer.tincidunt.aliquam@aol.edu","address":"4591 Quis, Street","postalZip":"410943","country":"China"},{"customerId":1370,"customerName":"Shay Sexton","phone":"1-672-295-8772","email":"nulla@protonmail.ca","address":"8330 Id, Rd.","postalZip":"25994","country":"Peru"},{"customerId":1371,"customerName":"Rebekah Potts","phone":"1-753-351-3583","email":"aenean.sed@protonmail.couk","address":"743-2372 Senectus Rd.","postalZip":"26632","country":"China"},{"customerId":1372,"customerName":"Abel Callahan","phone":"1-238-897-4737","email":"ipsum.ac@protonmail.ca","address":"602-9571 Et Rd.","postalZip":"676111","country":"Ukraine"},{"customerId":1373,"customerName":"Mary Giles","phone":"(735) 725-4428","email":"libero.dui@outlook.ca","address":"Ap #165-736 Nulla Ave","postalZip":"6821","country":"Australia"},{"customerId":1374,"customerName":"Philip Oneil","phone":"(257) 629-2555","email":"aptent.taciti@google.edu","address":"157-3521 Proin Ave","postalZip":"Y0P 8C1","country":"Poland"},{"customerId":1375,"customerName":"Patrick Castro","phone":"1-640-726-6319","email":"elementum.sem@aol.edu","address":"717-1600 Mi St.","postalZip":"598875","country":"New Zealand"},{"customerId":1376,"customerName":"Hilary Whitney","phone":"1-435-463-7643","email":"semper.cursus@icloud.org","address":"967-2948 Cursus Av.","postalZip":"2152","country":"Pakistan"},{"customerId":1377,"customerName":"Remedios Chen","phone":"1-353-715-3714","email":"ac.sem@outlook.net","address":"1176 Massa. Av.","postalZip":"8947","country":"Austria"},{"customerId":1378,"customerName":"Oliver Garrison","phone":"1-888-763-3744","email":"proin@hotmail.net","address":"384-7892 Cras Av.","postalZip":"12817","country":"United States"},{"customerId":1379,"customerName":"Deborah Banks","phone":"1-689-256-5736","email":"facilisis.vitae@yahoo.ca","address":"693-2272 Nec, Road","postalZip":"436775","country":"South Africa"},{"customerId":1380,"customerName":"Gray Dickson","phone":"1-342-858-0605","email":"duis.ac@aol.edu","address":"213-1391 Eu Road","postalZip":"391188","country":"Singapore"},{"customerId":1381,"customerName":"Idola Emerson","phone":"(337) 452-8241","email":"duis.a@protonmail.org","address":"8660 Pharetra Avenue","postalZip":"8263-8908","country":"Mexico"},{"customerId":1382,"customerName":"Elijah Mcfarland","phone":"(736) 200-7353","email":"nec@google.edu","address":"4989 In Road","postalZip":"287217","country":"United States"},{"customerId":1383,"customerName":"Fuller Briggs","phone":"1-761-488-5674","email":"pellentesque.massa@aol.org","address":"Ap #414-1834 Phasellus Ave","postalZip":"68-67","country":"Nigeria"},{"customerId":1384,"customerName":"Cassandra Kline","phone":"(375) 844-8213","email":"augue.ut@aol.ca","address":"2860 Enim. Avenue","postalZip":"T7R 5HK","country":"South Africa"},{"customerId":1385,"customerName":"Dante Schwartz","phone":"1-671-992-7859","email":"mi@aol.org","address":"4007 Sed Road","postalZip":"58671-152","country":"Spain"},{"customerId":1386,"customerName":"Troy Herrera","phone":"1-848-134-1888","email":"integer.urna@google.ca","address":"Ap #894-2060 Ante, Rd.","postalZip":"71831","country":"Nigeria"},{"customerId":1387,"customerName":"Brandon Carter","phone":"(375) 550-5413","email":"blandit.nam.nulla@yahoo.org","address":"Ap #505-8566 Curabitur Street","postalZip":"2163-7106","country":"Chile"},{"customerId":1388,"customerName":"Jane Richardson","phone":"1-687-726-2155","email":"eu.tempor.erat@hotmail.couk","address":"Ap #495-9237 Convallis, St.","postalZip":"5621","country":"Turkey"},{"customerId":1389,"customerName":"Georgia Barber","phone":"(732) 462-7264","email":"cras.vehicula@protonmail.net","address":"P.O. Box 389, 622 Diam Street","postalZip":"67-457","country":"Chile"},{"customerId":1390,"customerName":"Blake Morse","phone":"(368) 540-3115","email":"proin.sed@yahoo.edu","address":"9857 Blandit St.","postalZip":"2634","country":"Netherlands"},{"customerId":1391,"customerName":"Graham King","phone":"1-231-496-2332","email":"metus.vitae.velit@yahoo.ca","address":"Ap #696-8137 In, Rd.","postalZip":"61623","country":"Spain"},{"customerId":1392,"customerName":"Kevyn Cotton","phone":"(724) 617-2252","email":"enim.sit@icloud.ca","address":"Ap #274-4472 Pellentesque Rd.","postalZip":"B1C 9Y0","country":"Norway"},{"customerId":1393,"customerName":"Matthew Powell","phone":"1-330-146-8282","email":"nonummy.ac.feugiat@outlook.ca","address":"P.O. Box 319, 810 Aliquam Av.","postalZip":"28842","country":"Italy"},{"customerId":1394,"customerName":"Hyatt Jacobs","phone":"1-764-370-3841","email":"nunc.id@icloud.com","address":"P.O. Box 130, 8495 Convallis Road","postalZip":"37288","country":"Chile"},{"customerId":1395,"customerName":"Xaviera Porter","phone":"(603) 632-9282","email":"tincidunt@google.ca","address":"P.O. Box 973, 1320 Etiam Av.","postalZip":"776726","country":"Indonesia"},{"customerId":1396,"customerName":"Byron Bender","phone":"1-800-455-2084","email":"enim@google.net","address":"3781 Dolor Avenue","postalZip":"3283","country":"Italy"},{"customerId":1397,"customerName":"Indira Harrell","phone":"(654) 738-6165","email":"convallis.est@hotmail.ca","address":"365-2891 Scelerisque Rd.","postalZip":"73422","country":"China"},{"customerId":1398,"customerName":"Brady Mcdonald","phone":"1-715-461-5072","email":"nulla@yahoo.com","address":"937-4396 Vitae, Street","postalZip":"2628","country":"Chile"},{"customerId":1399,"customerName":"Hadley Sharp","phone":"1-433-710-7754","email":"a@protonmail.edu","address":"420-4962 Mi St.","postalZip":"622548","country":"Peru"},{"customerId":1400,"customerName":"Jared Mercado","phone":"(248) 846-3824","email":"bibendum.fermentum.metus@aol.ca","address":"4990 Blandit St.","postalZip":"3463","country":"Chile"},{"customerId":1401,"customerName":"Robert Guy","phone":"1-357-829-2343","email":"ut.eros.non@protonmail.ca","address":"1961 Quam St.","postalZip":"9271","country":"Russian Federation"},{"customerId":1402,"customerName":"Breanna Mosley","phone":"1-771-929-4147","email":"donec.sollicitudin@google.net","address":"232-6807 Sit Rd.","postalZip":"82425","country":"Costa Rica"},{"customerId":1403,"customerName":"Paula Atkins","phone":"(344) 599-3220","email":"integer.vulputate@google.com","address":"752-1940 Nibh Avenue","postalZip":"5238","country":"Sweden"},{"customerId":1404,"customerName":"Brenda Salinas","phone":"(550) 302-6150","email":"tortor@outlook.com","address":"Ap #558-2552 Dapibus Rd.","postalZip":"4156","country":"South Korea"},{"customerId":1405,"customerName":"Macaulay Trujillo","phone":"1-877-845-3785","email":"est@yahoo.org","address":"337-6767 A, Street","postalZip":"6412","country":"Netherlands"},{"customerId":1406,"customerName":"Mason Cooke","phone":"(351) 681-6735","email":"leo.in@protonmail.edu","address":"Ap #918-8413 Turpis Rd.","postalZip":"Y2M 4T1","country":"United Kingdom"},{"customerId":1407,"customerName":"Karly White","phone":"1-228-311-8259","email":"ac.sem@google.net","address":"Ap #399-1965 Id, St.","postalZip":"2288","country":"Sweden"},{"customerId":1408,"customerName":"Shelly Velasquez","phone":"(177) 208-7167","email":"nunc@google.edu","address":"5845 Eu, Road","postalZip":"534955","country":"Belgium"},{"customerId":1409,"customerName":"Hayes Garrison","phone":"(249) 725-6442","email":"magnis@aol.ca","address":"Ap #454-8593 Eu Ave","postalZip":"577247","country":"Germany"},{"customerId":1410,"customerName":"Cally Graham","phone":"1-236-136-0781","email":"sed.turpis.nec@google.edu","address":"855-351 Auctor St.","postalZip":"0306 CF","country":"Belgium"},{"customerId":1411,"customerName":"Shellie Chen","phone":"1-566-412-5218","email":"tristique@icloud.net","address":"P.O. Box 973, 883 Id St.","postalZip":"62546-868","country":"Ireland"},{"customerId":1412,"customerName":"Kaitlin Newman","phone":"(146) 425-3974","email":"ultrices.posuere@icloud.edu","address":"3837 Eget Rd.","postalZip":"482654","country":"China"},{"customerId":1413,"customerName":"Karyn Webb","phone":"1-472-581-4721","email":"amet.nulla@outlook.ca","address":"P.O. Box 676, 5623 Tristique Av.","postalZip":"30612","country":"Austria"},{"customerId":1414,"customerName":"Sebastian Hendrix","phone":"1-712-549-3131","email":"dolor.sit.amet@yahoo.edu","address":"P.O. Box 294, 6115 Ut Rd.","postalZip":"8706","country":"New Zealand"},{"customerId":1415,"customerName":"Sarah Schroeder","phone":"(274) 632-7831","email":"sit.amet@outlook.ca","address":"704-2747 Adipiscing St.","postalZip":"13-63","country":"Russian Federation"},{"customerId":1416,"customerName":"Malik Head","phone":"(879) 526-5425","email":"ultricies.sem@aol.ca","address":"294-6499 Eu Street","postalZip":"5826","country":"United States"},{"customerId":1417,"customerName":"Mark Downs","phone":"1-398-312-6149","email":"auctor.velit.eget@hotmail.edu","address":"1587 Convallis Road","postalZip":"613182","country":"Netherlands"},{"customerId":1418,"customerName":"Hedley Warner","phone":"(732) 564-7748","email":"proin.sed.turpis@icloud.edu","address":"902-201 In Avenue","postalZip":"8855 WH","country":"Brazil"},{"customerId":1419,"customerName":"Lee Hendrix","phone":"(844) 751-1313","email":"odio.semper@protonmail.com","address":"Ap #441-4472 Fusce Ave","postalZip":"93282","country":"South Africa"},{"customerId":1420,"customerName":"Hadley Carney","phone":"1-743-635-8227","email":"etiam@aol.couk","address":"7589 Augue, Av.","postalZip":"51621","country":"Chile"},{"customerId":1421,"customerName":"Amanda Armstrong","phone":"(921) 533-8075","email":"senectus.et@protonmail.edu","address":"Ap #394-8637 Sit St.","postalZip":"473854","country":"Italy"},{"customerId":1422,"customerName":"Simon Boyd","phone":"1-687-372-4535","email":"aenean@yahoo.com","address":"P.O. Box 374, 2081 Hendrerit Road","postalZip":"8208","country":"Poland"},{"customerId":1423,"customerName":"Regina Guerrero","phone":"(160) 753-3871","email":"nullam.feugiat@aol.com","address":"590-4169 Tellus. Av.","postalZip":"63H 2C8","country":"Norway"},{"customerId":1424,"customerName":"Teagan Maddox","phone":"(347) 225-1895","email":"elementum.at@google.com","address":"Ap #616-2976 Elit Road","postalZip":"16051","country":"Ukraine"},{"customerId":1425,"customerName":"Clementine Meadows","phone":"(815) 346-8474","email":"proin.nisl.sem@google.couk","address":"7562 Fringilla, Ave","postalZip":"5218","country":"Pakistan"},{"customerId":1426,"customerName":"Carter Mcgee","phone":"(485) 816-9556","email":"purus.sapien@google.com","address":"Ap #604-2617 Proin Rd.","postalZip":"72-38","country":"Colombia"},{"customerId":1427,"customerName":"Ray Diaz","phone":"(570) 856-5463","email":"nonummy@yahoo.com","address":"P.O. Box 410, 9374 Dolor. Road","postalZip":"347542","country":"Turkey"},{"customerId":1428,"customerName":"Medge Smith","phone":"1-172-522-0656","email":"enim.non.nisi@google.net","address":"982-3692 Id Rd.","postalZip":"2127","country":"Sweden"},{"customerId":1429,"customerName":"Venus Durham","phone":"1-877-220-6950","email":"lorem.ipsum@aol.net","address":"524-3668 Morbi Rd.","postalZip":"81159-587","country":"Chile"},{"customerId":1430,"customerName":"Jordan Barry","phone":"(319) 823-4618","email":"purus.maecenas@hotmail.couk","address":"Ap #170-4836 Gravida. St.","postalZip":"M01 4FO","country":"Colombia"},{"customerId":1431,"customerName":"Darryl Kidd","phone":"(374) 815-7524","email":"ultricies.ornare.elit@outlook.com","address":"5756 Facilisis Av.","postalZip":"8668","country":"Vietnam"},{"customerId":1432,"customerName":"Rudyard Richmond","phone":"1-686-596-4093","email":"semper@yahoo.ca","address":"403-3191 Nunc Street","postalZip":"472111","country":"Ireland"},{"customerId":1433,"customerName":"Burton Murphy","phone":"(332) 388-1202","email":"felis.donec@google.com","address":"7095 Porttitor Street","postalZip":"85-28","country":"Nigeria"},{"customerId":1434,"customerName":"Shellie Silva","phone":"1-544-711-5586","email":"feugiat.nec@protonmail.edu","address":"495-6059 Felis Avenue","postalZip":"695718","country":"China"},{"customerId":1435,"customerName":"Boris Cummings","phone":"1-448-430-4422","email":"diam.at.pretium@yahoo.org","address":"842-1880 Euismod St.","postalZip":"354827","country":"Poland"},{"customerId":1436,"customerName":"Melyssa Sweeney","phone":"1-773-385-2255","email":"fermentum.arcu@outlook.org","address":"6543 Suspendisse Rd.","postalZip":"1143 WM","country":"Colombia"},{"customerId":1437,"customerName":"Elizabeth Adkins","phone":"1-492-238-3683","email":"luctus.curabitur.egestas@outlook.edu","address":"Ap #186-4670 Ullamcorper, Street","postalZip":"34733","country":"Austria"},{"customerId":1438,"customerName":"Regan Chase","phone":"(427) 874-0222","email":"nulla.tincidunt@google.couk","address":"P.O. Box 729, 9658 Ante. Av.","postalZip":"421677","country":"Canada"},{"customerId":1439,"customerName":"Marcia Hayden","phone":"1-517-454-6216","email":"luctus.ipsum@outlook.couk","address":"4343 Posuere St.","postalZip":"65571","country":"Italy"},{"customerId":1440,"customerName":"Nathan Woodard","phone":"(864) 221-8233","email":"sed.pede@outlook.edu","address":"Ap #721-6523 Nisl St.","postalZip":"958646","country":"Peru"},{"customerId":1441,"customerName":"Patrick Joseph","phone":"(397) 337-8161","email":"enim.etiam@protonmail.org","address":"646 Nibh. Rd.","postalZip":"541326","country":"Indonesia"},{"customerId":1442,"customerName":"Nell Terry","phone":"(319) 269-2944","email":"cursus@google.com","address":"5599 Sapien. Street","postalZip":"14758","country":"Costa Rica"},{"customerId":1443,"customerName":"Jackson Hood","phone":"1-333-858-3511","email":"vel.venenatis@google.com","address":"5730 Integer Rd.","postalZip":"R1M 5M4","country":"Italy"},{"customerId":1444,"customerName":"Bo Townsend","phone":"(982) 834-0159","email":"odio.nam@google.couk","address":"Ap #409-5038 Hendrerit. St.","postalZip":"7330","country":"Canada"},{"customerId":1445,"customerName":"Kasimir Cobb","phone":"1-226-827-6362","email":"libero.morbi@outlook.net","address":"718-687 Laoreet Rd.","postalZip":"73577","country":"Peru"},{"customerId":1446,"customerName":"Seth Clay","phone":"(373) 374-3584","email":"vulputate.posuere@yahoo.com","address":"Ap #282-5429 Odio, Street","postalZip":"543124","country":"Ireland"},{"customerId":1447,"customerName":"May Morse","phone":"(650) 978-2239","email":"enim@outlook.net","address":"216-3840 Sed Rd.","postalZip":"62784","country":"Germany"},{"customerId":1448,"customerName":"Regan Hunt","phone":"1-230-987-0487","email":"faucibus.orci@yahoo.net","address":"404-6518 Lectus Road","postalZip":"27725","country":"Mexico"},{"customerId":1449,"customerName":"Oren Weiss","phone":"1-657-169-2093","email":"interdum.enim@yahoo.com","address":"Ap #520-7390 Orci Av.","postalZip":"83828","country":"China"},{"customerId":1450,"customerName":"Xander Lyons","phone":"(251) 743-6084","email":"sed@icloud.edu","address":"298 Adipiscing. Rd.","postalZip":"557583","country":"Poland"},{"customerId":1451,"customerName":"Jerome Lawson","phone":"1-346-144-0305","email":"dolor@outlook.net","address":"Ap #494-5240 Metus Road","postalZip":"25141","country":"New Zealand"},{"customerId":1452,"customerName":"Lester Morton","phone":"(261) 480-6322","email":"nullam.nisl@google.com","address":"619-705 Posuere, Ave","postalZip":"876325","country":"China"},{"customerId":1453,"customerName":"Daphne Hutchinson","phone":"1-588-521-0089","email":"cras.eget@protonmail.edu","address":"132-2342 Imperdiet St.","postalZip":"53-281","country":"South Korea"},{"customerId":1454,"customerName":"Noel Bell","phone":"1-522-123-1613","email":"mauris.erat@aol.ca","address":"271-8137 Eget Av.","postalZip":"5577","country":"Singapore"},{"customerId":1455,"customerName":"Neil Mcgee","phone":"1-393-523-7116","email":"pretium.et.rutrum@protonmail.couk","address":"4057 Duis Avenue","postalZip":"0245","country":"Sweden"},{"customerId":1456,"customerName":"Rajah Kaufman","phone":"(623) 206-3689","email":"vel@google.edu","address":"P.O. Box 263, 2713 Vivamus Av.","postalZip":"78846","country":"New Zealand"},{"customerId":1457,"customerName":"Pamela Barron","phone":"1-282-880-3258","email":"non.lacinia@yahoo.edu","address":"Ap #339-8091 Egestas Rd.","postalZip":"268541","country":"Germany"},{"customerId":1458,"customerName":"Judith Ortega","phone":"1-430-910-7469","email":"nec.luctus@hotmail.ca","address":"P.O. Box 285, 6251 Etiam Avenue","postalZip":"8597","country":"Turkey"},{"customerId":1459,"customerName":"Quyn Cervantes","phone":"1-661-857-5314","email":"phasellus.nulla@protonmail.org","address":"4746 Lacus. Avenue","postalZip":"76388","country":"Netherlands"},{"customerId":1460,"customerName":"Rebekah Solis","phone":"(621) 685-7840","email":"neque.sed@google.com","address":"743-7503 Sed Street","postalZip":"92472","country":"Ireland"},{"customerId":1461,"customerName":"Rajah Ferguson","phone":"(519) 271-1344","email":"in.dolor.fusce@yahoo.com","address":"678-2766 Tortor. Rd.","postalZip":"25485","country":"United States"},{"customerId":1462,"customerName":"Beau Moran","phone":"(257) 616-6112","email":"ut@hotmail.org","address":"810-5322 Nam Av.","postalZip":"7042","country":"Australia"},{"customerId":1463,"customerName":"Sebastian Gutierrez","phone":"(125) 232-2042","email":"elit.pretium.et@outlook.com","address":"1581 Est. St.","postalZip":"628394","country":"Singapore"},{"customerId":1464,"customerName":"Pearl Brooks","phone":"1-962-618-4885","email":"dui@protonmail.net","address":"P.O. Box 537, 4680 Euismod Ave","postalZip":"12307","country":"Philippines"},{"customerId":1465,"customerName":"Zachery Rowe","phone":"(704) 388-7845","email":"natoque.penatibus.et@aol.ca","address":"Ap #730-411 Id, Street","postalZip":"243539","country":"Russian Federation"},{"customerId":1466,"customerName":"Constance Kirkland","phone":"1-952-518-1532","email":"dolor.sit@aol.org","address":"P.O. Box 137, 950 Eu Rd.","postalZip":"259766","country":"New Zealand"},{"customerId":1467,"customerName":"Callum Melton","phone":"1-740-226-4104","email":"quam.vel.sapien@google.com","address":"248-862 Auctor Street","postalZip":"8573","country":"Mexico"},{"customerId":1468,"customerName":"Byron Pratt","phone":"(188) 775-5788","email":"risus.duis@protonmail.edu","address":"P.O. Box 469, 8493 Neque. St.","postalZip":"83348","country":"Nigeria"},{"customerId":1469,"customerName":"Raymond Mendez","phone":"1-386-551-1685","email":"phasellus@google.net","address":"Ap #810-8261 Quisque St.","postalZip":"283756","country":"Spain"},{"customerId":1470,"customerName":"Dorothy Molina","phone":"1-924-226-0519","email":"dictum.augue@yahoo.com","address":"738-1375 Quam St.","postalZip":"04276","country":"Ireland"},{"customerId":1471,"customerName":"Judith Bryan","phone":"(232) 371-0652","email":"amet.orci.ut@yahoo.edu","address":"665-3294 Erat St.","postalZip":"317846","country":"United Kingdom"},{"customerId":1472,"customerName":"Fletcher Hayes","phone":"1-764-338-1455","email":"orci.quis.lectus@icloud.org","address":"1076 Ornare Road","postalZip":"55514","country":"France"},{"customerId":1473,"customerName":"Brittany Chandler","phone":"(744) 892-8876","email":"duis.mi@protonmail.couk","address":"Ap #561-2067 Sagittis Avenue","postalZip":"871363","country":"Turkey"},{"customerId":1474,"customerName":"Mikayla Jensen","phone":"(485) 285-1430","email":"morbi.tristique.senectus@aol.org","address":"851-6767 Volutpat Road","postalZip":"4292","country":"Nigeria"},{"customerId":1475,"customerName":"Briar King","phone":"(356) 212-7474","email":"non.arcu@google.net","address":"359-6927 Turpis. Street","postalZip":"21-874","country":"Colombia"},{"customerId":1476,"customerName":"Lacey Mercer","phone":"(885) 333-9474","email":"venenatis.a@outlook.org","address":"Ap #419-3943 Duis St.","postalZip":"539142","country":"France"},{"customerId":1477,"customerName":"Eleanor Floyd","phone":"1-177-533-7375","email":"volutpat.ornare@yahoo.com","address":"Ap #960-4112 Elementum, Rd.","postalZip":"718548","country":"Germany"},{"customerId":1478,"customerName":"Maile Mayer","phone":"1-322-315-8111","email":"tincidunt.aliquam@yahoo.com","address":"Ap #486-649 Fusce Rd.","postalZip":"56241","country":"Netherlands"},{"customerId":1479,"customerName":"Hillary Wade","phone":"1-443-311-0868","email":"arcu@google.com","address":"197-6962 Enim. Avenue","postalZip":"5513-2453","country":"Philippines"},{"customerId":1480,"customerName":"Melodie Nieves","phone":"1-988-553-3198","email":"rutrum.urna@google.couk","address":"825 Imperdiet, Rd.","postalZip":"35-49","country":"Australia"},{"customerId":1481,"customerName":"Rudyard Sherman","phone":"(888) 322-1271","email":"amet.lorem@icloud.com","address":"4138 Pede Street","postalZip":"939718","country":"United Kingdom"},{"customerId":1482,"customerName":"Demetria England","phone":"1-501-219-5570","email":"arcu.vestibulum@google.ca","address":"282-7794 Velit. Av.","postalZip":"134573","country":"Ireland"},{"customerId":1483,"customerName":"Travis Barron","phone":"(831) 197-9763","email":"sem.pellentesque.ut@google.net","address":"Ap #987-3412 Tincidunt, St.","postalZip":"40337","country":"Australia"},{"customerId":1484,"customerName":"Fuller Barnes","phone":"(854) 764-4813","email":"purus@hotmail.net","address":"9191 Congue Rd.","postalZip":"S6V 6C2","country":"Brazil"},{"customerId":1485,"customerName":"Jacqueline Riggs","phone":"(210) 411-0395","email":"sed.auctor.odio@icloud.com","address":"Ap #758-4793 Pharetra, Rd.","postalZip":"631719","country":"Australia"},{"customerId":1486,"customerName":"Cherokee Cherry","phone":"1-759-146-3635","email":"condimentum.eget@icloud.com","address":"1779 Semper St.","postalZip":"2555","country":"Colombia"},{"customerId":1487,"customerName":"Eliana Wiggins","phone":"1-340-861-3284","email":"nulla.facilisis@google.com","address":"874-4413 Nulla St.","postalZip":"18721","country":"India"},{"customerId":1488,"customerName":"Ocean Nolan","phone":"(440) 888-6142","email":"urna@google.ca","address":"7353 Magna St.","postalZip":"P6N 8IW","country":"Pakistan"},{"customerId":1489,"customerName":"Phillip Malone","phone":"1-298-214-1548","email":"donec.tempus.lorem@protonmail.net","address":"816-1177 Ac Av.","postalZip":"874549","country":"Italy"},{"customerId":1490,"customerName":"Bertha Browning","phone":"1-976-795-7866","email":"scelerisque.scelerisque.dui@icloud.org","address":"Ap #584-7985 Ultrices. St.","postalZip":"75771-071","country":"Netherlands"},{"customerId":1491,"customerName":"Kiara Keller","phone":"(532) 654-4924","email":"duis.a@aol.org","address":"P.O. Box 462, 6705 Mauris Avenue","postalZip":"16101","country":"Philippines"},{"customerId":1492,"customerName":"Roary Mcguire","phone":"1-584-974-2759","email":"tincidunt.tempus@hotmail.com","address":"351-5478 Lorem Av.","postalZip":"29739","country":"Netherlands"},{"customerId":1493,"customerName":"Gretchen Terrell","phone":"1-753-115-8564","email":"magna@protonmail.ca","address":"P.O. Box 450, 4866 Aptent St.","postalZip":"6975-9289","country":"Singapore"},{"customerId":1494,"customerName":"Wilma Lewis","phone":"1-242-889-5854","email":"adipiscing.elit@google.couk","address":"Ap #107-998 Fermentum Av.","postalZip":"78445","country":"Philippines"},{"customerId":1495,"customerName":"Malcolm Flynn","phone":"(362) 465-8764","email":"integer@yahoo.edu","address":"596-7143 Et, St.","postalZip":"79-629","country":"United Kingdom"},{"customerId":1496,"customerName":"Noah Summers","phone":"1-127-528-8858","email":"convallis@google.net","address":"Ap #573-9650 Et Street","postalZip":"763186","country":"Mexico"},{"customerId":1497,"customerName":"Athena Noel","phone":"(185) 760-5457","email":"molestie.arcu@google.couk","address":"938-1487 Nunc, Av.","postalZip":"58593","country":"Philippines"},{"customerId":1498,"customerName":"William Tyler","phone":"1-705-351-4918","email":"faucibus.lectus@aol.net","address":"559-438 Risus. Road","postalZip":"7065","country":"Vietnam"},{"customerId":1499,"customerName":"Dylan Hutchinson","phone":"(652) 906-4717","email":"sed.diam@yahoo.edu","address":"356-3693 Blandit Road","postalZip":"77279","country":"United States"},{"customerId":1500,"customerName":"Flynn Hartman","phone":"1-468-568-4494","email":"turpis.vitae.purus@google.net","address":"675-5870 Sapien. St.","postalZip":"791118","country":"Austria"},{"customerId":1501,"customerName":"McKenzie Mcneil","phone":"(166) 390-7282","email":"praesent.luctus.curabitur@outlook.com","address":"Ap #116-7259 Interdum. Avenue","postalZip":"2110","country":"Ireland"},{"customerId":1502,"customerName":"Tarik Fields","phone":"1-866-750-2706","email":"libero.proin@outlook.org","address":"7574 Donec Rd.","postalZip":"80177","country":"Nigeria"},{"customerId":1503,"customerName":"Whilemina Reilly","phone":"1-501-858-3298","email":"dictum.phasellus@yahoo.net","address":"Ap #120-762 Rhoncus. Rd.","postalZip":"B7S 5A2","country":"China"},{"customerId":1504,"customerName":"Aaron Lewis","phone":"1-526-722-6692","email":"nunc@icloud.edu","address":"419-2134 Vitae St.","postalZip":"37464","country":"Ukraine"},{"customerId":1505,"customerName":"Basil Sloan","phone":"(328) 668-5437","email":"nec@protonmail.edu","address":"Ap #565-1866 Mi Rd.","postalZip":"21507","country":"United States"},{"customerId":1506,"customerName":"Ezra Banks","phone":"1-233-743-6012","email":"vulputate.posuere.vulputate@google.edu","address":"840-4158 Nibh. Road","postalZip":"63478","country":"Mexico"},{"customerId":1507,"customerName":"Ian Wyatt","phone":"(467) 713-5531","email":"orci@outlook.ca","address":"Ap #686-9816 Vitae Av.","postalZip":"93364","country":"Austria"},{"customerId":1508,"customerName":"Ahmed James","phone":"1-707-235-8866","email":"egestas@hotmail.org","address":"Ap #960-1187 Massa. Ave","postalZip":"UB4 7RK","country":"Mexico"},{"customerId":1509,"customerName":"Cailin Smith","phone":"1-885-601-4724","email":"purus.in.molestie@google.com","address":"928-392 Ligula. Ave","postalZip":"24831","country":"New Zealand"},{"customerId":1510,"customerName":"Kylee Gallegos","phone":"1-701-158-4685","email":"porta.elit.a@outlook.edu","address":"571-6772 Erat Road","postalZip":"50447-730","country":"Germany"},{"customerId":1511,"customerName":"Aimee Myers","phone":"(868) 615-7841","email":"aliquet.nec@protonmail.net","address":"P.O. Box 543, 5797 Eu Avenue","postalZip":"37494","country":"Canada"},{"customerId":1512,"customerName":"Abbot Spencer","phone":"(771) 675-6803","email":"blandit.enim@protonmail.edu","address":"Ap #645-8349 Ad Ave","postalZip":"12153","country":"Germany"},{"customerId":1513,"customerName":"Nell Wilcox","phone":"(466) 387-5621","email":"eu.arcu.morbi@protonmail.couk","address":"P.O. Box 295, 2886 Ante. St.","postalZip":"8567-6327","country":"Colombia"},{"customerId":1514,"customerName":"Maggy Hood","phone":"1-856-525-6187","email":"sed.eget@icloud.com","address":"P.O. Box 732, 6922 Odio. St.","postalZip":"515861","country":"Singapore"},{"customerId":1515,"customerName":"Macon Mccall","phone":"1-884-618-4634","email":"cubilia.curae@protonmail.ca","address":"8746 Vel Street","postalZip":"8911","country":"United States"},{"customerId":1516,"customerName":"Ezekiel Cooley","phone":"1-302-114-6634","email":"amet.metus@google.com","address":"880-2620 Egestas. Street","postalZip":"9912 DN","country":"New Zealand"},{"customerId":1517,"customerName":"Russell Hendrix","phone":"(328) 841-5878","email":"condimentum.eget.volutpat@outlook.ca","address":"Ap #520-4463 Metus Avenue","postalZip":"24768","country":"Austria"},{"customerId":1518,"customerName":"Tad Norman","phone":"(539) 650-8887","email":"eu.augue@yahoo.net","address":"Ap #655-4472 Vitae Rd.","postalZip":"74831","country":"Mexico"},{"customerId":1519,"customerName":"Adena Baxter","phone":"1-412-781-7545","email":"ultrices.duis@icloud.org","address":"245 Cras Road","postalZip":"5765","country":"South Africa"},{"customerId":1520,"customerName":"Tate Dawson","phone":"(841) 344-1704","email":"vestibulum.neque@outlook.net","address":"6714 Hendrerit Rd.","postalZip":"72656","country":"Mexico"},{"customerId":1521,"customerName":"Dara George","phone":"1-346-386-2181","email":"sed.et@hotmail.couk","address":"586-3321 Elit St.","postalZip":"14847","country":"Sweden"},{"customerId":1522,"customerName":"Jessica Bell","phone":"(740) 633-3725","email":"vestibulum@outlook.net","address":"8717 Proin Street","postalZip":"14761","country":"Nigeria"},{"customerId":1523,"customerName":"Steel Dale","phone":"1-586-946-4061","email":"imperdiet.dictum@protonmail.net","address":"3549 Vestibulum Ave","postalZip":"306701","country":"Singapore"},{"customerId":1524,"customerName":"Grace Thornton","phone":"1-404-815-9933","email":"semper.rutrum@google.org","address":"562-2784 Molestie Street","postalZip":"432990","country":"Russian Federation"},{"customerId":1525,"customerName":"Christian Copeland","phone":"1-569-813-8954","email":"risus.quisque@icloud.couk","address":"7909 Dictum Road","postalZip":"78383-26021","country":"Pakistan"},{"customerId":1526,"customerName":"Nissim Jackson","phone":"(646) 231-6467","email":"in.molestie@hotmail.ca","address":"990-3298 Orci Av.","postalZip":"15158","country":"Nigeria"},{"customerId":1527,"customerName":"Anthony Spencer","phone":"1-207-684-3725","email":"a.tortor@google.edu","address":"P.O. Box 692, 9331 Tincidunt Road","postalZip":"426698","country":"Turkey"},{"customerId":1528,"customerName":"Yoshio Herman","phone":"(557) 625-9833","email":"sapien.imperdiet.ornare@outlook.ca","address":"256-8143 Aliquam, St.","postalZip":"51045","country":"United States"},{"customerId":1529,"customerName":"Karleigh William","phone":"1-876-823-6379","email":"a.facilisis.non@google.couk","address":"9877 Mattis. Av.","postalZip":"86464","country":"Sweden"},{"customerId":1530,"customerName":"Jeremy Lloyd","phone":"(460) 415-3476","email":"scelerisque.neque.nullam@google.ca","address":"P.O. Box 338, 8128 Donec Avenue","postalZip":"61407-521","country":"Germany"},{"customerId":1531,"customerName":"Ivy English","phone":"1-179-798-6357","email":"dictum@aol.ca","address":"583 Dui, Rd.","postalZip":"213345","country":"Turkey"},{"customerId":1532,"customerName":"Jenette Bentley","phone":"1-782-772-5541","email":"convallis@outlook.edu","address":"P.O. Box 123, 4816 Tristique St.","postalZip":"8861","country":"Singapore"},{"customerId":1533,"customerName":"Mary Miranda","phone":"1-759-387-2924","email":"lacus.aliquam@icloud.ca","address":"1032 Massa. Road","postalZip":"338261","country":"Ireland"},{"customerId":1534,"customerName":"Neil Meyers","phone":"(784) 575-4741","email":"quis@yahoo.com","address":"299-1192 At, St.","postalZip":"564168","country":"Pakistan"},{"customerId":1535,"customerName":"Burke Guthrie","phone":"1-737-670-8343","email":"massa.mauris.vestibulum@icloud.org","address":"3879 Justo Road","postalZip":"61176","country":"Peru"},{"customerId":1536,"customerName":"Uriel Cervantes","phone":"1-648-388-3587","email":"at.velit.cras@yahoo.net","address":"7752 Et, Road","postalZip":"PG5A 1OK","country":"Canada"},{"customerId":1537,"customerName":"Alexander Ryan","phone":"1-807-745-3807","email":"dictum.ultricies@google.edu","address":"125-2358 Consectetuer Avenue","postalZip":"56-15","country":"South Korea"},{"customerId":1538,"customerName":"Mechelle Gilbert","phone":"1-362-242-5351","email":"vestibulum.lorem@outlook.com","address":"835-6325 Sapien. Road","postalZip":"785957","country":"Sweden"},{"customerId":1539,"customerName":"Serina Ratliff","phone":"1-733-412-4228","email":"libero.dui@yahoo.couk","address":"Ap #179-2329 Duis Avenue","postalZip":"795272","country":"Russian Federation"},{"customerId":1540,"customerName":"Baker Sloan","phone":"(753) 257-3255","email":"tortor.dictum.eu@protonmail.ca","address":"486-2340 Fringilla Av.","postalZip":"2801","country":"India"},{"customerId":1541,"customerName":"Zena Rowe","phone":"(575) 288-5544","email":"quam.a@outlook.couk","address":"161-2481 Nec Rd.","postalZip":"02070","country":"Ireland"},{"customerId":1542,"customerName":"Nadine Duke","phone":"(835) 884-7769","email":"maecenas.malesuada@protonmail.net","address":"5794 Vel St.","postalZip":"50105","country":"France"},{"customerId":1543,"customerName":"Sara Mcdonald","phone":"(581) 214-4133","email":"nullam@outlook.edu","address":"170-1390 Viverra. Rd.","postalZip":"248080","country":"Ireland"},{"customerId":1544,"customerName":"Quinlan Garner","phone":"(238) 571-0284","email":"lectus.ante@yahoo.com","address":"Ap #292-3354 Eu St.","postalZip":"7152","country":"Singapore"},{"customerId":1545,"customerName":"Cade Garza","phone":"1-724-688-3790","email":"congue.in@outlook.org","address":"Ap #112-7956 Donec Road","postalZip":"53-59","country":"Mexico"},{"customerId":1546,"customerName":"Leonard Nicholson","phone":"1-970-237-7180","email":"vitae.posuere@outlook.org","address":"Ap #744-3445 Tempor Rd.","postalZip":"2672","country":"Sweden"},{"customerId":1547,"customerName":"Julian Rodriguez","phone":"(974) 443-3175","email":"quisque.ac.libero@outlook.net","address":"3467 Hymenaeos. Av.","postalZip":"8453","country":"Costa Rica"},{"customerId":1548,"customerName":"Carolyn Mcfadden","phone":"1-825-506-0384","email":"orci.luctus@icloud.net","address":"323-6285 Risus. Road","postalZip":"7046","country":"Brazil"},{"customerId":1549,"customerName":"Tate Morin","phone":"1-635-725-4085","email":"montes.nascetur.ridiculus@protonmail.org","address":"Ap #688-4955 Arcu. St.","postalZip":"30881","country":"New Zealand"},{"customerId":1550,"customerName":"Xander Bullock","phone":"1-974-842-8466","email":"metus.in@outlook.net","address":"509-6735 Non St.","postalZip":"393524","country":"South Africa"},{"customerId":1551,"customerName":"Chester Lyons","phone":"1-438-891-7757","email":"consectetuer.adipiscing@protonmail.org","address":"Ap #513-1993 Quisque Street","postalZip":"45140-18471","country":"Sweden"},{"customerId":1552,"customerName":"Odessa Becker","phone":"(456) 252-3811","email":"sodales@hotmail.ca","address":"Ap #674-147 Augue Ave","postalZip":"21528-58414","country":"New Zealand"},{"customerId":1553,"customerName":"Tara Best","phone":"1-838-562-6847","email":"cum.sociis@outlook.com","address":"Ap #319-8597 Velit. Ave","postalZip":"12603","country":"Belgium"},{"customerId":1554,"customerName":"Lael Gross","phone":"1-461-738-3675","email":"varius.nam@yahoo.net","address":"515-995 Rhoncus. Avenue","postalZip":"21237","country":"Russian Federation"},{"customerId":1555,"customerName":"Kelly Savage","phone":"1-665-770-0615","email":"erat@google.net","address":"Ap #775-3829 Et, Avenue","postalZip":"671683","country":"Pakistan"},{"customerId":1556,"customerName":"Theodore Mcneil","phone":"1-817-208-4768","email":"consequat.enim@aol.ca","address":"649-3431 Nunc St.","postalZip":"33426","country":"Costa Rica"},{"customerId":1557,"customerName":"Hilary Guthrie","phone":"(441) 586-5208","email":"in.consequat@icloud.ca","address":"662-355 Viverra. Avenue","postalZip":"202273","country":"France"},{"customerId":1558,"customerName":"Carissa Perkins","phone":"1-227-673-1245","email":"habitant@aol.edu","address":"947-3502 Auctor Rd.","postalZip":"157261","country":"Italy"},{"customerId":1559,"customerName":"Claudia Foreman","phone":"(618) 390-6326","email":"nascetur@aol.org","address":"Ap #474-9359 Tellus. Av.","postalZip":"33525452","country":"Philippines"},{"customerId":1560,"customerName":"Shana Valdez","phone":"(204) 242-7458","email":"diam.proin@google.edu","address":"959-8629 Mus. Ave","postalZip":"245686","country":"France"},{"customerId":1561,"customerName":"Nadine Kim","phone":"(566) 178-6838","email":"phasellus.in@outlook.com","address":"Ap #880-6632 At, Road","postalZip":"604233","country":"South Korea"},{"customerId":1562,"customerName":"Tamekah Calderon","phone":"(589) 642-1591","email":"lectus.convallis@hotmail.edu","address":"3995 Sit Ave","postalZip":"8486","country":"India"},{"customerId":1563,"customerName":"Leah Battle","phone":"1-265-436-2635","email":"odio.phasellus@hotmail.couk","address":"Ap #694-436 Cras Rd.","postalZip":"311774","country":"Philippines"},{"customerId":1564,"customerName":"Vance Battle","phone":"1-815-769-4626","email":"condimentum.donec@icloud.com","address":"386-9686 Quisque Rd.","postalZip":"3812","country":"Norway"},{"customerId":1565,"customerName":"Fallon Mcdowell","phone":"(244) 856-6414","email":"arcu.iaculis.enim@hotmail.couk","address":"P.O. Box 120, 2304 Id, Road","postalZip":"48533","country":"Australia"},{"customerId":1566,"customerName":"Guinevere James","phone":"1-859-864-6361","email":"nonummy.ut@hotmail.com","address":"Ap #216-8629 Neque Rd.","postalZip":"34658","country":"Nigeria"},{"customerId":1567,"customerName":"Kylynn Villarreal","phone":"1-748-281-4551","email":"conubia.nostra.per@outlook.org","address":"500-8908 In Street","postalZip":"903978","country":"Russian Federation"},{"customerId":1568,"customerName":"James Baxter","phone":"1-861-691-8354","email":"vel.sapien.imperdiet@outlook.net","address":"Ap #188-5927 Sodales Road","postalZip":"666693","country":"Nigeria"},{"customerId":1569,"customerName":"Dominic Randolph","phone":"1-846-244-6548","email":"libero.donec@hotmail.org","address":"Ap #962-5268 Neque. Rd.","postalZip":"48-25","country":"Colombia"},{"customerId":1570,"customerName":"Jael Boone","phone":"(675) 840-5703","email":"cursus.diam@google.edu","address":"5719 Et, Street","postalZip":"S2N 5B5","country":"Sweden"},{"customerId":1571,"customerName":"Axel Moses","phone":"1-572-176-6541","email":"lobortis.augue.scelerisque@aol.net","address":"Ap #866-9703 Aliquet St.","postalZip":"892948","country":"Colombia"},{"customerId":1572,"customerName":"Kirby Olson","phone":"1-318-371-3883","email":"in.magna@yahoo.com","address":"Ap #297-7935 Ipsum Avenue","postalZip":"F8B 6AE","country":"France"},{"customerId":1573,"customerName":"Griffith Wright","phone":"1-775-697-9174","email":"molestie@protonmail.couk","address":"Ap #882-9342 Amet Rd.","postalZip":"2158","country":"Australia"},{"customerId":1574,"customerName":"Jemima Beck","phone":"(467) 488-2618","email":"montes.nascetur@aol.couk","address":"P.O. Box 664, 7037 Amet St.","postalZip":"UV75 0QY","country":"India"},{"customerId":1575,"customerName":"Tallulah Branch","phone":"(880) 338-1627","email":"tristique.senectus@icloud.net","address":"2481 Urna Av.","postalZip":"30515","country":"Australia"},{"customerId":1576,"customerName":"Dara Herman","phone":"(760) 541-2943","email":"lectus.justo.eu@google.ca","address":"3211 Luctus Rd.","postalZip":"10-363","country":"Australia"},{"customerId":1577,"customerName":"Reece Carter","phone":"(265) 319-3355","email":"quam@hotmail.couk","address":"P.O. Box 767, 682 Sem, Road","postalZip":"54867","country":"Mexico"},{"customerId":1578,"customerName":"Xyla Butler","phone":"1-384-877-3155","email":"cum.sociis.natoque@aol.net","address":"Ap #186-6630 Tempus St.","postalZip":"3698","country":"Vietnam"},{"customerId":1579,"customerName":"Libby Madden","phone":"(479) 936-4346","email":"enim@hotmail.ca","address":"Ap #383-3743 Accumsan Avenue","postalZip":"4784","country":"Chile"},{"customerId":1580,"customerName":"Keaton Gonzales","phone":"1-630-158-6984","email":"odio.auctor@aol.edu","address":"7406 Arcu. Street","postalZip":"338469","country":"China"},{"customerId":1581,"customerName":"Guinevere Dixon","phone":"(763) 788-7542","email":"nunc.lectus.pede@aol.edu","address":"643-1844 Lorem. Ave","postalZip":"40213","country":"Colombia"},{"customerId":1582,"customerName":"Priscilla Pena","phone":"1-607-730-5138","email":"consequat.purus@protonmail.edu","address":"P.O. Box 563, 824 Aliquet Street","postalZip":"9853","country":"Australia"},{"customerId":1583,"customerName":"Timon Hopper","phone":"1-790-808-7406","email":"dictum.mi.ac@outlook.net","address":"Ap #341-8394 Luctus Street","postalZip":"11563","country":"Sweden"},{"customerId":1584,"customerName":"Carl Castaneda","phone":"1-926-562-5316","email":"elit.a@outlook.couk","address":"832-5155 Nascetur Ave","postalZip":"56205","country":"Peru"},{"customerId":1585,"customerName":"Xaviera Kelley","phone":"(723) 911-7523","email":"cum.sociis@icloud.org","address":"Ap #427-903 Euismod Av.","postalZip":"820757","country":"Netherlands"},{"customerId":1586,"customerName":"Unity Henson","phone":"1-953-684-5154","email":"a.purus@protonmail.org","address":"Ap #695-2807 Senectus Rd.","postalZip":"9382","country":"Italy"},{"customerId":1587,"customerName":"Gage Holden","phone":"1-355-247-5242","email":"odio.sagittis@google.couk","address":"457-1090 Enim Rd.","postalZip":"475296","country":"Brazil"},{"customerId":1588,"customerName":"Nita Adkins","phone":"1-584-691-5154","email":"amet@google.com","address":"5126 Nunc. Av.","postalZip":"WU31 2QK","country":"Australia"},{"customerId":1589,"customerName":"Keegan Lamb","phone":"1-716-343-3456","email":"pulvinar@yahoo.net","address":"Ap #372-4204 At Road","postalZip":"87-67","country":"Philippines"},{"customerId":1590,"customerName":"Quinn Sweet","phone":"1-239-328-7187","email":"adipiscing.elit@yahoo.net","address":"476-7064 Libero. Ave","postalZip":"7228","country":"Philippines"},{"customerId":1591,"customerName":"Ezra Greene","phone":"1-841-595-9177","email":"feugiat.non@aol.net","address":"Ap #718-444 Eros St.","postalZip":"43955","country":"Russian Federation"},{"customerId":1592,"customerName":"Frances Flowers","phone":"1-146-387-1926","email":"accumsan@hotmail.ca","address":"645-5000 Aliquam Street","postalZip":"852576","country":"Poland"},{"customerId":1593,"customerName":"Trevor Dejesus","phone":"(884) 636-8153","email":"ultrices.posuere.cubilia@icloud.edu","address":"Ap #276-122 Donec Street","postalZip":"541234","country":"Vietnam"},{"customerId":1594,"customerName":"Neil Cummings","phone":"1-612-507-2021","email":"ligula.tortor.dictum@google.ca","address":"Ap #612-9353 Sagittis. Street","postalZip":"337068","country":"Singapore"},{"customerId":1595,"customerName":"Lillith Gay","phone":"(274) 572-2548","email":"imperdiet@yahoo.edu","address":"Ap #622-2006 Cursus Ave","postalZip":"30811","country":"Ukraine"},{"customerId":1596,"customerName":"Illiana Vincent","phone":"(826) 460-8876","email":"maecenas.libero@aol.org","address":"P.O. Box 217, 4003 Ut, Rd.","postalZip":"T2M 4S4","country":"New Zealand"},{"customerId":1597,"customerName":"Ezra Finch","phone":"1-454-647-1191","email":"iaculis.odio@google.org","address":"288-2063 Auctor, Ave","postalZip":"5297","country":"Sweden"},{"customerId":1598,"customerName":"Chadwick Carney","phone":"(850) 217-8180","email":"nascetur.ridiculus.mus@icloud.couk","address":"Ap #246-2593 Eu Ave","postalZip":"4458","country":"United Kingdom"},{"customerId":1599,"customerName":"Ira Molina","phone":"(431) 332-4783","email":"feugiat@yahoo.ca","address":"Ap #310-1089 Semper Avenue","postalZip":"30765","country":"Sweden"},{"customerId":1600,"customerName":"Maya Chang","phone":"1-792-445-6513","email":"velit.aliquam@yahoo.net","address":"Ap #376-990 Risus. Street","postalZip":"36147","country":"Philippines"},{"customerId":1601,"customerName":"Ferris Mcpherson","phone":"(281) 367-9438","email":"elit.elit@protonmail.edu","address":"P.O. Box 186, 4085 Senectus Rd.","postalZip":"57188","country":"Italy"},{"customerId":1602,"customerName":"Rebekah Mason","phone":"1-563-616-6157","email":"sagittis@hotmail.org","address":"P.O. Box 662, 8738 Nullam St.","postalZip":"3617 FY","country":"Sweden"},{"customerId":1603,"customerName":"Ahmed Booker","phone":"1-825-659-3780","email":"dui.nec@hotmail.ca","address":"4536 Adipiscing Avenue","postalZip":"17455","country":"Pakistan"},{"customerId":1604,"customerName":"Azalia Huber","phone":"(825) 379-6869","email":"sed.libero.proin@icloud.net","address":"558-7276 Eleifend, St.","postalZip":"965025","country":"Brazil"},{"customerId":1605,"customerName":"Ella Preston","phone":"(831) 264-7575","email":"nibh.quisque.nonummy@yahoo.couk","address":"566-8199 Mus. Rd.","postalZip":"3439","country":"Ukraine"},{"customerId":1606,"customerName":"Blythe Pittman","phone":"(834) 671-7126","email":"mauris.blandit@aol.org","address":"125-4326 Purus St.","postalZip":"4317","country":"Ukraine"},{"customerId":1607,"customerName":"Yoshio Chapman","phone":"(898) 986-1273","email":"sit.amet@protonmail.edu","address":"Ap #155-2288 Libero Av.","postalZip":"44743","country":"Philippines"},{"customerId":1608,"customerName":"Anika Little","phone":"1-594-637-8201","email":"donec@outlook.couk","address":"Ap #294-872 Mauris Ave","postalZip":"06379","country":"Poland"},{"customerId":1609,"customerName":"Macon Workman","phone":"(289) 594-1157","email":"dis.parturient.montes@google.edu","address":"936-3514 Vitae, Ave","postalZip":"0252","country":"Canada"},{"customerId":1610,"customerName":"Garrison Durham","phone":"(258) 870-0620","email":"libero.integer@icloud.net","address":"P.O. Box 876, 1097 Magnis St.","postalZip":"30815","country":"Colombia"},{"customerId":1611,"customerName":"Veda Rios","phone":"(466) 365-7576","email":"mollis.integer@hotmail.org","address":"Ap #592-8065 Lacus. Street","postalZip":"835424","country":"Brazil"},{"customerId":1612,"customerName":"Whilemina Dominguez","phone":"(284) 662-2143","email":"sit.amet@icloud.couk","address":"938-7019 Sociis St.","postalZip":"485445","country":"China"},{"customerId":1613,"customerName":"Brett Morris","phone":"1-196-128-3152","email":"mi.ac@protonmail.edu","address":"545-3988 Mattis. Avenue","postalZip":"36438","country":"Spain"},{"customerId":1614,"customerName":"Elliott Gray","phone":"1-552-222-8342","email":"fermentum.metus@google.org","address":"284-9443 Justo Road","postalZip":"77-479","country":"Australia"},{"customerId":1615,"customerName":"Graham Norton","phone":"(867) 546-3531","email":"cursus.et@icloud.edu","address":"1955 Lorem, Av.","postalZip":"74772-058","country":"China"},{"customerId":1616,"customerName":"Palmer White","phone":"(855) 828-3747","email":"in.scelerisque@yahoo.edu","address":"Ap #694-6826 Tincidunt. Ave","postalZip":"16885","country":"China"},{"customerId":1617,"customerName":"Erasmus Camacho","phone":"1-948-196-9143","email":"vitae.nibh@aol.ca","address":"Ap #363-1053 Class Avenue","postalZip":"38169","country":"Mexico"},{"customerId":1618,"customerName":"Imogene Guy","phone":"1-276-653-6350","email":"metus.vitae.velit@outlook.ca","address":"5267 Dictum St.","postalZip":"041885","country":"Philippines"},{"customerId":1619,"customerName":"Aaron Bennett","phone":"(833) 375-4642","email":"et.lacinia@google.couk","address":"9677 Eleifend St.","postalZip":"831378","country":"Netherlands"},{"customerId":1620,"customerName":"Arden Patel","phone":"(622) 136-5410","email":"duis.a@hotmail.org","address":"202-1668 Gravida. Avenue","postalZip":"19038","country":"Colombia"},{"customerId":1621,"customerName":"Nissim Gray","phone":"1-405-952-2632","email":"aliquam@google.org","address":"Ap #919-8162 Ipsum Rd.","postalZip":"8488-8333","country":"Netherlands"},{"customerId":1622,"customerName":"Joshua Travis","phone":"(737) 261-3075","email":"mauris@google.org","address":"P.O. Box 475, 3136 Vitae Av.","postalZip":"818843","country":"Brazil"},{"customerId":1623,"customerName":"Benedict Sullivan","phone":"(458) 408-9656","email":"velit.justo@icloud.couk","address":"P.O. Box 632, 5450 Dui Road","postalZip":"6156 QH","country":"Costa Rica"},{"customerId":1624,"customerName":"Rudyard Battle","phone":"(665) 849-7813","email":"nullam.feugiat@icloud.net","address":"317-6615 Turpis Av.","postalZip":"7505","country":"Colombia"},{"customerId":1625,"customerName":"Clio Maddox","phone":"1-428-714-9741","email":"cras.vehicula.aliquet@outlook.com","address":"Ap #335-8353 Ultricies St.","postalZip":"1185 JV","country":"Russian Federation"},{"customerId":1626,"customerName":"Peter Gallagher","phone":"1-614-870-0551","email":"nunc.mauris@outlook.ca","address":"459-6842 Aenean St.","postalZip":"74645-22584","country":"New Zealand"},{"customerId":1627,"customerName":"Chester Reed","phone":"(840) 373-0625","email":"at@yahoo.com","address":"521-9750 Luctus Ave","postalZip":"53878","country":"France"},{"customerId":1628,"customerName":"Basia O'Neill","phone":"(782) 198-3175","email":"odio.phasellus@google.couk","address":"773-7288 Phasellus Rd.","postalZip":"490253","country":"Chile"},{"customerId":1629,"customerName":"Jack Benson","phone":"(281) 256-6334","email":"vulputate.lacus@yahoo.com","address":"194 Sed Road","postalZip":"8222","country":"Turkey"},{"customerId":1630,"customerName":"Shoshana Maddox","phone":"(568) 652-9811","email":"massa.non.ante@icloud.ca","address":"Ap #342-1108 Vel, St.","postalZip":"28638","country":"Sweden"},{"customerId":1631,"customerName":"Wing Atkinson","phone":"(467) 822-4681","email":"cras.convallis@hotmail.org","address":"Ap #120-3919 Hymenaeos. Road","postalZip":"7757","country":"South Korea"},{"customerId":1632,"customerName":"Callum Hobbs","phone":"(372) 578-6405","email":"nisi.cum.sociis@yahoo.couk","address":"9163 Lectus Avenue","postalZip":"445227","country":"Singapore"},{"customerId":1633,"customerName":"Lucian Tate","phone":"(862) 273-4625","email":"rutrum.magna@yahoo.edu","address":"Ap #525-9688 Suspendisse Ave","postalZip":"50111","country":"United Kingdom"},{"customerId":1634,"customerName":"Upton Holloway","phone":"(946) 658-1201","email":"in.aliquet@outlook.org","address":"759-5589 Dictum Road","postalZip":"3983","country":"United States"},{"customerId":1635,"customerName":"Dylan Wong","phone":"1-727-363-2861","email":"eros@icloud.ca","address":"7860 Ac Road","postalZip":"M3N 5W3","country":"China"},{"customerId":1636,"customerName":"Tara Aguilar","phone":"(765) 709-4857","email":"in.consectetuer@icloud.ca","address":"139-9509 Dolor Av.","postalZip":"64-615","country":"South Africa"},{"customerId":1637,"customerName":"Rafael Olson","phone":"(226) 352-1331","email":"et@protonmail.ca","address":"8503 Varius Road","postalZip":"66052","country":"Norway"},{"customerId":1638,"customerName":"Bernard Walton","phone":"(281) 540-7265","email":"rutrum.lorem.ac@aol.couk","address":"Ap #567-7048 Sem St.","postalZip":"645666","country":"Norway"},{"customerId":1639,"customerName":"Katelyn Pena","phone":"1-548-345-8795","email":"ligula.nullam.enim@yahoo.ca","address":"P.O. Box 887, 2166 Mus. Ave","postalZip":"128582","country":"France"},{"customerId":1640,"customerName":"Elmo Hewitt","phone":"(298) 925-8748","email":"a.auctor@icloud.com","address":"P.O. Box 251, 5241 Eget Street","postalZip":"471522","country":"Ukraine"},{"customerId":1641,"customerName":"Natalie Robertson","phone":"(678) 825-2562","email":"vitae@outlook.edu","address":"Ap #879-4782 Vehicula Street","postalZip":"38740","country":"France"},{"customerId":1642,"customerName":"Dawn Merritt","phone":"1-265-210-8913","email":"magnis.dis.parturient@hotmail.ca","address":"445-8990 Non, Rd.","postalZip":"18-48","country":"Philippines"},{"customerId":1643,"customerName":"Brenda Levy","phone":"(701) 974-6316","email":"et.ultrices@outlook.com","address":"3530 Scelerisque Ave","postalZip":"9006-6437","country":"Sweden"},{"customerId":1644,"customerName":"Nasim Moran","phone":"(567) 458-4753","email":"non.hendrerit@hotmail.edu","address":"Ap #581-143 Quisque Road","postalZip":"6935","country":"Brazil"},{"customerId":1645,"customerName":"Jessamine Castro","phone":"1-396-829-8782","email":"felis.ullamcorper@aol.edu","address":"P.O. Box 313, 3068 Morbi Road","postalZip":"7386","country":"Vietnam"},{"customerId":1646,"customerName":"Melvin Schwartz","phone":"(513) 964-3682","email":"hendrerit@protonmail.ca","address":"Ap #357-5828 Fermentum Ave","postalZip":"79164","country":"Spain"},{"customerId":1647,"customerName":"Emerald Edwards","phone":"1-376-557-4732","email":"purus@icloud.couk","address":"Ap #895-3768 Facilisis, St.","postalZip":"23882","country":"Colombia"},{"customerId":1648,"customerName":"Octavia Singleton","phone":"(579) 846-1365","email":"a.facilisis@icloud.edu","address":"Ap #706-6281 Sed Av.","postalZip":"8703","country":"China"},{"customerId":1649,"customerName":"Gretchen Scott","phone":"(241) 921-9732","email":"vivamus.non.lorem@aol.ca","address":"P.O. Box 729, 7299 Nulla. St.","postalZip":"6466","country":"United States"},{"customerId":1650,"customerName":"Dylan Jacobs","phone":"(642) 372-6730","email":"aliquam.erat@icloud.net","address":"337-7653 Sem. Street","postalZip":"398270","country":"Vietnam"},{"customerId":1651,"customerName":"Zorita Kirk","phone":"1-503-741-2357","email":"hendrerit.donec.porttitor@aol.couk","address":"641-7996 Gravida Road","postalZip":"62368","country":"Belgium"},{"customerId":1652,"customerName":"Marshall Lancaster","phone":"1-283-486-3777","email":"at@hotmail.org","address":"5317 Euismod Ave","postalZip":"19042","country":"Australia"},{"customerId":1653,"customerName":"Mohammad Ford","phone":"(959) 306-2558","email":"augue.malesuada@icloud.org","address":"Ap #911-585 Per Ave","postalZip":"231830","country":"Sweden"},{"customerId":1654,"customerName":"Ebony Kidd","phone":"1-893-313-7544","email":"orci@yahoo.org","address":"Ap #751-6262 Mollis Av.","postalZip":"559633","country":"Ireland"},{"customerId":1655,"customerName":"Dylan Garrett","phone":"1-684-466-1701","email":"at.arcu.vestibulum@yahoo.couk","address":"Ap #664-9498 Praesent Av.","postalZip":"7930","country":"Norway"},{"customerId":1656,"customerName":"Prescott Robinson","phone":"(887) 633-3623","email":"laoreet.posuere@protonmail.net","address":"190-4174 Ut, St.","postalZip":"6234","country":"Belgium"},{"customerId":1657,"customerName":"Seth Sharpe","phone":"1-853-372-5157","email":"erat.neque@icloud.com","address":"Ap #819-8855 Sem Av.","postalZip":"981156","country":"Belgium"},{"customerId":1658,"customerName":"Amena Sloan","phone":"(648) 164-6150","email":"quisque.fringilla@google.couk","address":"P.O. Box 599, 3942 Eget St.","postalZip":"33906","country":"New Zealand"},{"customerId":1659,"customerName":"Magee Wagner","phone":"(852) 438-3264","email":"curabitur.egestas.nunc@google.couk","address":"766-9757 Fusce Rd.","postalZip":"142020","country":"Costa Rica"},{"customerId":1660,"customerName":"Nash Goodman","phone":"1-406-853-4116","email":"et.euismod@aol.edu","address":"P.O. Box 408, 6575 Eros. Rd.","postalZip":"4756-7136","country":"Pakistan"},{"customerId":1661,"customerName":"September Ferrell","phone":"1-211-240-2216","email":"cubilia.curae@google.net","address":"732-8003 Mi. Ave","postalZip":"51124","country":"Sweden"},{"customerId":1662,"customerName":"Brett Blackwell","phone":"(803) 682-4371","email":"nonummy.ultricies@outlook.edu","address":"980-5214 Nulla. St.","postalZip":"443986","country":"Russian Federation"},{"customerId":1663,"customerName":"Lilah Cash","phone":"1-732-344-5483","email":"aenean.euismod.mauris@yahoo.net","address":"356-252 Tincidunt Ave","postalZip":"731535","country":"Pakistan"},{"customerId":1664,"customerName":"Brett Paul","phone":"1-650-481-3482","email":"aliquam.enim@yahoo.ca","address":"Ap #286-4140 Vivamus St.","postalZip":"636562","country":"Peru"},{"customerId":1665,"customerName":"Shelby Sanchez","phone":"1-516-412-2638","email":"ligula.nullam@outlook.com","address":"P.O. Box 348, 4141 Magna. Street","postalZip":"605328","country":"Sweden"},{"customerId":1666,"customerName":"Castor Bishop","phone":"(944) 121-4301","email":"ultricies@aol.ca","address":"Ap #743-6671 Phasellus St.","postalZip":"621783","country":"Mexico"},{"customerId":1667,"customerName":"Chase Wyatt","phone":"1-613-173-6522","email":"sed.orci.lobortis@outlook.org","address":"Ap #881-5816 Dolor Road","postalZip":"52594","country":"Netherlands"},{"customerId":1668,"customerName":"Tucker Alford","phone":"(423) 531-4822","email":"senectus.et.netus@hotmail.net","address":"481-2575 Primis Ave","postalZip":"888295","country":"Spain"},{"customerId":1669,"customerName":"Cruz Wells","phone":"1-507-806-1934","email":"quis.pede.praesent@icloud.com","address":"930-4088 Aliquet Av.","postalZip":"44255","country":"Turkey"},{"customerId":1670,"customerName":"Yardley Buchanan","phone":"1-783-863-9251","email":"sit@yahoo.edu","address":"Ap #978-8991 Nunc St.","postalZip":"8132 QE","country":"United Kingdom"},{"customerId":1671,"customerName":"Mariam Buckley","phone":"1-198-385-7483","email":"nibh@protonmail.ca","address":"575 Vestibulum Ave","postalZip":"4775","country":"Ukraine"},{"customerId":1672,"customerName":"Bevis Hewitt","phone":"(770) 456-1452","email":"curabitur@hotmail.com","address":"Ap #556-7092 A, St.","postalZip":"28766","country":"Philippines"},{"customerId":1673,"customerName":"Tanya Richardson","phone":"(847) 763-3342","email":"convallis@protonmail.couk","address":"2511 Orci, Av.","postalZip":"NL3H 5DU","country":"Mexico"},{"customerId":1674,"customerName":"Barry Woodward","phone":"(637) 296-0268","email":"a@yahoo.net","address":"Ap #290-5074 Pellentesque St.","postalZip":"526268","country":"United Kingdom"},{"customerId":1675,"customerName":"Daniel Velasquez","phone":"1-333-781-2793","email":"et.magnis@outlook.edu","address":"Ap #732-5193 Risus. Rd.","postalZip":"154364","country":"Mexico"},{"customerId":1676,"customerName":"Darius Foley","phone":"(887) 758-2389","email":"ornare.placerat.orci@aol.org","address":"Ap #690-1754 Netus St.","postalZip":"5988-9356","country":"Ireland"},{"customerId":1677,"customerName":"Xenos Nielsen","phone":"1-365-875-5822","email":"libero.integer@aol.couk","address":"Ap #339-784 Fusce Rd.","postalZip":"7483","country":"Spain"},{"customerId":1678,"customerName":"Idona Zamora","phone":"(635) 323-6142","email":"nec.tellus@google.ca","address":"Ap #140-642 Lectus Street","postalZip":"2197","country":"Mexico"},{"customerId":1679,"customerName":"Ciara O'brien","phone":"1-168-874-5243","email":"dolor.sit.amet@google.couk","address":"843-2358 Parturient Street","postalZip":"80009","country":"Colombia"},{"customerId":1680,"customerName":"Shelley Wall","phone":"(225) 633-7548","email":"libero.morbi.accumsan@protonmail.edu","address":"Ap #381-488 Quis Rd.","postalZip":"4026","country":"Peru"},{"customerId":1681,"customerName":"Stacey Perry","phone":"1-535-321-4212","email":"sed.pede@icloud.edu","address":"Ap #564-794 Vitae, Av.","postalZip":"7876 UD","country":"Mexico"},{"customerId":1682,"customerName":"Colleen Pickett","phone":"(742) 741-5565","email":"in.sodales.elit@hotmail.ca","address":"Ap #637-1333 Mauris Av.","postalZip":"645842","country":"Colombia"},{"customerId":1683,"customerName":"Sydnee Lowe","phone":"(320) 244-4030","email":"etiam.laoreet.libero@yahoo.com","address":"4435 Senectus Ave","postalZip":"30902","country":"Vietnam"},{"customerId":1684,"customerName":"Aiko Patton","phone":"(215) 551-6732","email":"molestie.sodales.mauris@protonmail.org","address":"920-4686 Tellus Avenue","postalZip":"67-27","country":"Poland"},{"customerId":1685,"customerName":"Thane Martinez","phone":"(514) 378-4784","email":"libero.proin@google.org","address":"813-1161 Curae Road","postalZip":"21113","country":"Italy"},{"customerId":1686,"customerName":"Kimberly Dillon","phone":"1-878-431-4544","email":"pellentesque.sed@hotmail.com","address":"Ap #118-4240 Montes, Road","postalZip":"37717","country":"Poland"},{"customerId":1687,"customerName":"Belle Newman","phone":"(855) 547-4333","email":"mauris@outlook.ca","address":"189-3660 Nam Street","postalZip":"4386","country":"Sweden"},{"customerId":1688,"customerName":"Lareina Gilmore","phone":"1-278-922-8676","email":"vitae.orci@icloud.com","address":"625-2261 Convallis St.","postalZip":"3214-4318","country":"Russian Federation"},{"customerId":1689,"customerName":"Rahim Dejesus","phone":"(672) 377-3160","email":"pede.cum@icloud.com","address":"326-3392 Dolor Rd.","postalZip":"501067","country":"Colombia"},{"customerId":1690,"customerName":"Dale Houston","phone":"(658) 121-5125","email":"ipsum@outlook.edu","address":"Ap #162-1267 Erat Av.","postalZip":"27711","country":"United Kingdom"},{"customerId":1691,"customerName":"Kaseem Delaney","phone":"(643) 691-8186","email":"fermentum.fermentum@google.com","address":"Ap #418-6382 Vitae Rd.","postalZip":"44766","country":"Norway"},{"customerId":1692,"customerName":"Avye Hardin","phone":"1-273-860-5670","email":"eget.ipsum@hotmail.org","address":"477-4210 Mi Street","postalZip":"8862","country":"Norway"},{"customerId":1693,"customerName":"Susan Baldwin","phone":"(964) 364-8434","email":"dignissim@aol.couk","address":"202-7842 In Road","postalZip":"218375","country":"Australia"},{"customerId":1694,"customerName":"Lilah West","phone":"1-796-169-5322","email":"fringilla.cursus@icloud.net","address":"Ap #310-580 Enim, Road","postalZip":"245344","country":"Spain"},{"customerId":1695,"customerName":"Coby Mckenzie","phone":"(213) 845-8650","email":"orci.tincidunt@protonmail.com","address":"806-7767 Quis Road","postalZip":"4177","country":"Norway"},{"customerId":1696,"customerName":"Christine Jennings","phone":"(715) 537-2464","email":"in.scelerisque@google.ca","address":"124-5918 Cubilia Rd.","postalZip":"1361","country":"Vietnam"},{"customerId":1697,"customerName":"Lewis Grimes","phone":"(572) 464-6213","email":"ullamcorper.velit.in@icloud.net","address":"229-7576 Ligula Rd.","postalZip":"613522","country":"Germany"},{"customerId":1698,"customerName":"Emily Collier","phone":"(278) 870-4749","email":"suspendisse.commodo@icloud.com","address":"4977 Eu Ave","postalZip":"1385 OM","country":"Belgium"},{"customerId":1699,"customerName":"Nevada Hebert","phone":"(843) 650-1745","email":"pellentesque.ut@outlook.couk","address":"P.O. Box 531, 4654 Non, St.","postalZip":"82187","country":"Norway"},{"customerId":1700,"customerName":"Lamar Hunter","phone":"(737) 457-2372","email":"morbi@outlook.couk","address":"P.O. Box 210, 9393 Porttitor Rd.","postalZip":"34348-85852","country":"Canada"},{"customerId":1701,"customerName":"Clio Sutton","phone":"(522) 825-4448","email":"fringilla.euismod@google.ca","address":"777-1845 Sollicitudin St.","postalZip":"163246","country":"Pakistan"},{"customerId":1702,"customerName":"MacKensie Bennett","phone":"1-739-635-7427","email":"id@icloud.org","address":"Ap #584-7811 Amet St.","postalZip":"574645","country":"Canada"},{"customerId":1703,"customerName":"Harding Mosley","phone":"(873) 224-4335","email":"pretium.neque.morbi@yahoo.com","address":"3540 Est, Ave","postalZip":"8237","country":"Ukraine"},{"customerId":1704,"customerName":"Sylvester Suarez","phone":"(325) 788-6486","email":"sed.orci.lobortis@outlook.com","address":"234-9600 Hendrerit. Road","postalZip":"15426","country":"Australia"},{"customerId":1705,"customerName":"Amy Gillespie","phone":"(152) 523-4975","email":"egestas@outlook.com","address":"Ap #158-2997 Dignissim St.","postalZip":"97-167","country":"Germany"},{"customerId":1706,"customerName":"Hayden Moon","phone":"(935) 260-7756","email":"nisi.mauris.nulla@hotmail.net","address":"427-1201 Auctor St.","postalZip":"66Z 2W8","country":"Colombia"},{"customerId":1707,"customerName":"Sara Anderson","phone":"(718) 748-8122","email":"iaculis@google.com","address":"Ap #677-4355 Vulputate St.","postalZip":"8283","country":"Peru"},{"customerId":1708,"customerName":"Stacy Meyers","phone":"(328) 335-6716","email":"elementum@protonmail.org","address":"Ap #449-8065 Amet St.","postalZip":"20T 5A4","country":"Philippines"},{"customerId":1709,"customerName":"Cedric Roberts","phone":"1-341-646-8248","email":"morbi@yahoo.edu","address":"P.O. Box 415, 8188 Dignissim Road","postalZip":"84-65","country":"Australia"},{"customerId":1710,"customerName":"Amity Roberson","phone":"(628) 627-8750","email":"arcu.sed@aol.com","address":"Ap #338-3979 Commodo Av.","postalZip":"228578","country":"Australia"},{"customerId":1711,"customerName":"Adele Newman","phone":"(203) 571-8100","email":"sagittis.felis.donec@protonmail.org","address":"P.O. Box 671, 5754 Sed Rd.","postalZip":"341169","country":"Indonesia"},{"customerId":1712,"customerName":"Caleb Osborn","phone":"(935) 615-2648","email":"placerat@google.edu","address":"P.O. Box 492, 5843 Ipsum. Av.","postalZip":"56826","country":"Peru"},{"customerId":1713,"customerName":"Xyla Waters","phone":"(818) 779-4231","email":"aenean.eget@aol.net","address":"6226 Leo Av.","postalZip":"41327","country":"Sweden"},{"customerId":1714,"customerName":"Samson Chan","phone":"(439) 813-0536","email":"posuere.at@icloud.com","address":"Ap #287-2311 Erat, Ave","postalZip":"9992","country":"Chile"},{"customerId":1715,"customerName":"Kevyn Horn","phone":"1-874-485-4475","email":"velit@yahoo.couk","address":"197-545 Eu Avenue","postalZip":"ST5 3VT","country":"United States"},{"customerId":1716,"customerName":"Evangeline Finch","phone":"(582) 173-5533","email":"integer.urna@icloud.com","address":"Ap #804-798 Mi. Avenue","postalZip":"48308","country":"China"},{"customerId":1717,"customerName":"Damian Pace","phone":"1-773-447-4366","email":"lorem@aol.couk","address":"223-4156 Id Ave","postalZip":"5612","country":"Pakistan"},{"customerId":1718,"customerName":"Jenna Mcneil","phone":"1-844-688-2542","email":"quis.diam@icloud.edu","address":"Ap #681-370 Malesuada Rd.","postalZip":"362646","country":"Indonesia"},{"customerId":1719,"customerName":"Raya Hickman","phone":"(586) 301-1642","email":"a.enim@google.edu","address":"847-8413 Donec Av.","postalZip":"7422","country":"Brazil"},{"customerId":1720,"customerName":"Rana Willis","phone":"1-861-551-8589","email":"aliquam.arcu@protonmail.org","address":"P.O. Box 762, 7096 Dolor. Rd.","postalZip":"74285","country":"Austria"},{"customerId":1721,"customerName":"Lani Britt","phone":"(367) 875-1722","email":"facilisis.non@hotmail.com","address":"P.O. Box 981, 4572 Dolor St.","postalZip":"418266","country":"Costa Rica"},{"customerId":1722,"customerName":"Duncan Fowler","phone":"(412) 556-7453","email":"egestas.a@outlook.ca","address":"Ap #767-3723 Nec Av.","postalZip":"7357","country":"Colombia"},{"customerId":1723,"customerName":"Linus Carey","phone":"1-391-844-2845","email":"vitae@hotmail.edu","address":"7570 Nulla St.","postalZip":"2973","country":"South Africa"},{"customerId":1724,"customerName":"Brianna Brooks","phone":"(405) 452-2352","email":"varius.ultrices@icloud.couk","address":"385 Eget, Avenue","postalZip":"56726-876","country":"Australia"},{"customerId":1725,"customerName":"Tanya Riggs","phone":"(138) 673-5782","email":"sociis.natoque@icloud.ca","address":"Ap #344-675 Lacus, Rd.","postalZip":"XV3 1SI","country":"South Africa"},{"customerId":1726,"customerName":"Sopoline Macdonald","phone":"1-271-591-6086","email":"penatibus.et@aol.com","address":"4243 Dui, St.","postalZip":"2866","country":"Turkey"},{"customerId":1727,"customerName":"Sybil Dillard","phone":"1-911-143-8841","email":"accumsan.neque@yahoo.net","address":"Ap #160-4400 Sed St.","postalZip":"306819","country":"Spain"},{"customerId":1728,"customerName":"Raphael Dean","phone":"(385) 414-3368","email":"tellus.aenean@aol.ca","address":"737-4581 Ligula Ave","postalZip":"R84 5VW","country":"Chile"},{"customerId":1729,"customerName":"Aline Blanchard","phone":"1-266-647-2786","email":"vel.arcu@aol.net","address":"Ap #975-5147 Odio. Street","postalZip":"43122","country":"Austria"},{"customerId":1730,"customerName":"Calvin Watkins","phone":"(533) 578-8483","email":"donec@hotmail.edu","address":"2175 Tempus St.","postalZip":"264537","country":"Costa Rica"},{"customerId":1731,"customerName":"Mallory Foley","phone":"1-560-215-0146","email":"nisi.nibh.lacinia@outlook.com","address":"8619 Libero. St.","postalZip":"547483","country":"Mexico"},{"customerId":1732,"customerName":"Lillith Hubbard","phone":"(806) 617-7872","email":"luctus.vulputate@yahoo.com","address":"Ap #794-6524 Enim, Av.","postalZip":"23-739","country":"United States"},{"customerId":1733,"customerName":"Kellie Ramirez","phone":"(323) 866-9423","email":"parturient.montes.nascetur@hotmail.org","address":"P.O. Box 800, 9339 A, Street","postalZip":"9730","country":"Norway"},{"customerId":1734,"customerName":"Alfonso Hampton","phone":"1-751-293-7671","email":"cras.interdum.nunc@aol.couk","address":"839-1907 Inceptos Av.","postalZip":"533273","country":"Russian Federation"},{"customerId":1735,"customerName":"Shad Vance","phone":"1-877-577-7578","email":"dictum.augue@icloud.org","address":"Ap #934-5519 Diam Avenue","postalZip":"37265","country":"Sweden"},{"customerId":1736,"customerName":"Davis Gill","phone":"(372) 548-8655","email":"commodo.hendrerit.donec@icloud.ca","address":"334-998 Ac Ave","postalZip":"85486-525","country":"Peru"},{"customerId":1737,"customerName":"Honorato Hester","phone":"(277) 235-2260","email":"cras@outlook.net","address":"Ap #315-322 At Av.","postalZip":"75-45","country":"Australia"},{"customerId":1738,"customerName":"Melodie Watkins","phone":"(695) 611-5373","email":"donec.elementum.lorem@hotmail.edu","address":"5158 Eu St.","postalZip":"43978","country":"India"},{"customerId":1739,"customerName":"Noel Carlson","phone":"1-717-155-2656","email":"blandit@google.edu","address":"190-3256 Risus. Street","postalZip":"24649","country":"New Zealand"},{"customerId":1740,"customerName":"Chester Ballard","phone":"(235) 746-0634","email":"lorem.ac@google.com","address":"4124 Laoreet Avenue","postalZip":"97-134","country":"Indonesia"},{"customerId":1741,"customerName":"Daniel Knapp","phone":"1-323-285-1218","email":"a.dui.cras@hotmail.org","address":"P.O. Box 641, 1963 Tristique Road","postalZip":"7125","country":"Germany"},{"customerId":1742,"customerName":"Dara Battle","phone":"1-558-514-2465","email":"commodo.at.libero@yahoo.org","address":"P.O. Box 497, 386 Morbi Street","postalZip":"277351","country":"Indonesia"},{"customerId":1743,"customerName":"Henry Sharpe","phone":"(521) 283-1806","email":"nunc.nulla@aol.couk","address":"8274 Etiam St.","postalZip":"86510","country":"Pakistan"},{"customerId":1744,"customerName":"Ethan Chandler","phone":"(557) 838-2445","email":"purus.sapien@icloud.ca","address":"P.O. Box 511, 4478 Quis Avenue","postalZip":"336594","country":"Italy"},{"customerId":1745,"customerName":"Ezekiel Collier","phone":"1-622-387-0656","email":"phasellus.dapibus.quam@google.net","address":"734-2366 Eget Street","postalZip":"74715-329","country":"Canada"},{"customerId":1746,"customerName":"Nigel Rowland","phone":"(163) 488-1288","email":"eleifend@protonmail.ca","address":"5461 Malesuada Street","postalZip":"719436","country":"China"},{"customerId":1747,"customerName":"Roary Byers","phone":"1-419-463-5765","email":"dolor@hotmail.org","address":"1244 Sit Street","postalZip":"57778","country":"Chile"},{"customerId":1748,"customerName":"Nasim Hickman","phone":"(347) 956-8632","email":"nam.interdum@icloud.edu","address":"181-9755 Cum Ave","postalZip":"122776","country":"Russian Federation"},{"customerId":1749,"customerName":"Maya Shelton","phone":"1-912-563-1276","email":"vulputate.risus@protonmail.edu","address":"Ap #169-6106 Lorem Street","postalZip":"338952","country":"Indonesia"},{"customerId":1750,"customerName":"Ahmed May","phone":"1-484-672-8434","email":"vel.venenatis@google.couk","address":"847-6348 Dui Av.","postalZip":"67857","country":"Belgium"},{"customerId":1751,"customerName":"Jena Watts","phone":"1-628-737-1989","email":"cursus.diam@protonmail.net","address":"120-2380 Ut, Rd.","postalZip":"36031223","country":"Costa Rica"},{"customerId":1752,"customerName":"Sylvester Sherman","phone":"(413) 839-4337","email":"laoreet@outlook.edu","address":"Ap #514-6542 Mattis. Road","postalZip":"7771","country":"Indonesia"},{"customerId":1753,"customerName":"Ruth Booker","phone":"1-468-486-1678","email":"quisque.libero@yahoo.ca","address":"P.O. Box 665, 1469 Turpis. Rd.","postalZip":"37595","country":"United Kingdom"},{"customerId":1754,"customerName":"Raja Mayer","phone":"(304) 302-3799","email":"risus.donec.egestas@outlook.net","address":"P.O. Box 878, 5902 Metus. Av.","postalZip":"13003","country":"Brazil"},{"customerId":1755,"customerName":"Theodore Bryan","phone":"(115) 851-7252","email":"dignissim.maecenas@protonmail.edu","address":"P.O. Box 270, 7392 Eu, St.","postalZip":"83-848","country":"Netherlands"},{"customerId":1756,"customerName":"Jayme Becker","phone":"(918) 537-1685","email":"rhoncus.id.mollis@hotmail.com","address":"342-4576 Nulla St.","postalZip":"6380","country":"Philippines"},{"customerId":1757,"customerName":"Denton Day","phone":"1-624-955-6135","email":"amet.consectetuer.adipiscing@hotmail.com","address":"Ap #766-904 Nunc St.","postalZip":"806901","country":"Austria"},{"customerId":1758,"customerName":"Clinton Lewis","phone":"(297) 239-0718","email":"orci.lacus@icloud.edu","address":"Ap #432-1003 Ac Rd.","postalZip":"267623","country":"Indonesia"},{"customerId":1759,"customerName":"Brody Saunders","phone":"1-433-337-4683","email":"ut.sagittis@aol.couk","address":"P.O. Box 739, 6128 Dignissim Rd.","postalZip":"23673","country":"Chile"},{"customerId":1760,"customerName":"Harriet Howell","phone":"1-540-430-7152","email":"aliquet@google.com","address":"5252 Maecenas Avenue","postalZip":"528483","country":"Philippines"},{"customerId":1761,"customerName":"Todd Fisher","phone":"(667) 877-9308","email":"dictum.phasellus@icloud.com","address":"Ap #301-3983 Montes, St.","postalZip":"651870","country":"New Zealand"},{"customerId":1762,"customerName":"Giselle Moon","phone":"(424) 655-1381","email":"et.magnis.dis@hotmail.edu","address":"638-7918 Luctus Rd.","postalZip":"613656","country":"Mexico"},{"customerId":1763,"customerName":"Caryn Adkins","phone":"(733) 891-3838","email":"accumsan.laoreet@protonmail.com","address":"162-7076 Morbi Street","postalZip":"34282","country":"Austria"},{"customerId":1764,"customerName":"Sydney Haynes","phone":"1-355-161-5018","email":"penatibus@google.ca","address":"485-7517 Fusce St.","postalZip":"605943","country":"Ireland"},{"customerId":1765,"customerName":"Tatyana Dalton","phone":"(814) 373-1703","email":"libero@yahoo.com","address":"685-2282 Dolor. St.","postalZip":"47046","country":"Poland"},{"customerId":1766,"customerName":"Elvis Jacobs","phone":"1-264-716-1507","email":"nisi@icloud.com","address":"P.O. Box 161, 6636 Vestibulum Avenue","postalZip":"94547","country":"France"},{"customerId":1767,"customerName":"Cally Barber","phone":"1-632-478-8265","email":"class.aptent@outlook.edu","address":"427-4554 Suspendisse Rd.","postalZip":"81183","country":"Indonesia"},{"customerId":1768,"customerName":"Harrison David","phone":"1-773-694-6658","email":"tellus.id.nunc@icloud.couk","address":"Ap #270-9912 Nibh. Road","postalZip":"7588","country":"Peru"},{"customerId":1769,"customerName":"Georgia Shepherd","phone":"(847) 315-8517","email":"ullamcorper.viverra.maecenas@hotmail.com","address":"368-2564 Ac Road","postalZip":"BG4 7PS","country":"Austria"},{"customerId":1770,"customerName":"Buffy Sanders","phone":"(712) 741-6568","email":"nam.ac.nulla@aol.net","address":"P.O. Box 415, 6925 Vitae, Avenue","postalZip":"04251","country":"Belgium"},{"customerId":1771,"customerName":"Brenda Payne","phone":"1-816-969-4577","email":"penatibus@aol.edu","address":"Ap #922-1366 Et, Avenue","postalZip":"58281-68196","country":"South Korea"},{"customerId":1772,"customerName":"Wylie Morton","phone":"(245) 427-8237","email":"aliquam.vulputate@outlook.couk","address":"861-9336 Magna. St.","postalZip":"45948","country":"Austria"},{"customerId":1773,"customerName":"Noah Powers","phone":"(173) 562-2488","email":"vitae@protonmail.net","address":"465-8904 Vivamus Av.","postalZip":"5824","country":"Ukraine"},{"customerId":1774,"customerName":"Ava Harmon","phone":"(221) 295-1966","email":"cum@aol.net","address":"505-5922 Curae St.","postalZip":"R3M 3R3","country":"Colombia"},{"customerId":1775,"customerName":"Jesse Brock","phone":"1-596-872-5628","email":"integer.sem.elit@yahoo.net","address":"1958 Amet, St.","postalZip":"04649","country":"Norway"},{"customerId":1776,"customerName":"Melinda O'brien","phone":"(468) 555-8182","email":"suscipit.nonummy@aol.edu","address":"509-5138 Ante Ave","postalZip":"5557","country":"Austria"},{"customerId":1777,"customerName":"Charles Skinner","phone":"1-156-831-7663","email":"et.magnis@outlook.org","address":"744-9893 Vel St.","postalZip":"6230","country":"South Africa"},{"customerId":1778,"customerName":"Jeremy Bailey","phone":"(414) 432-2193","email":"lectus.pede@protonmail.ca","address":"258-1229 Nec St.","postalZip":"5549","country":"Canada"},{"customerId":1779,"customerName":"Hannah Richard","phone":"1-551-851-4881","email":"enim.nisl@hotmail.com","address":"Ap #951-9530 Magna, Avenue","postalZip":"53-475","country":"Australia"},{"customerId":1780,"customerName":"Michael Long","phone":"(133) 817-2544","email":"vitae.orci@aol.couk","address":"241-1013 At, Rd.","postalZip":"427153","country":"Austria"},{"customerId":1781,"customerName":"Ulysses Gutierrez","phone":"(411) 761-4166","email":"faucibus.morbi.vehicula@hotmail.ca","address":"Ap #943-3504 Enim, St.","postalZip":"263511","country":"South Korea"},{"customerId":1782,"customerName":"Harrison Francis","phone":"1-643-914-3553","email":"metus@hotmail.org","address":"Ap #201-3925 Libero Road","postalZip":"454198","country":"Vietnam"},{"customerId":1783,"customerName":"Neil Williamson","phone":"(748) 412-4278","email":"quam.vel@google.ca","address":"575 Sed Rd.","postalZip":"98-14","country":"South Korea"},{"customerId":1784,"customerName":"Price Fernandez","phone":"(549) 322-5658","email":"tincidunt.nibh@google.edu","address":"522-1392 Non Road","postalZip":"5371","country":"Pakistan"},{"customerId":1785,"customerName":"Clark Conner","phone":"1-869-767-9227","email":"ante.blandit.viverra@protonmail.edu","address":"3083 Ullamcorper, Street","postalZip":"955573","country":"Singapore"},{"customerId":1786,"customerName":"Jason Callahan","phone":"(116) 867-7430","email":"quis.lectus.nullam@icloud.net","address":"864-1456 Quisque Ave","postalZip":"4963","country":"Vietnam"},{"customerId":1787,"customerName":"Alyssa Mathis","phone":"1-802-719-9555","email":"neque@icloud.ca","address":"177-5985 Malesuada Av.","postalZip":"39-58","country":"United States"},{"customerId":1788,"customerName":"Elijah Jones","phone":"(524) 683-1743","email":"ut.sagittis.lobortis@hotmail.com","address":"207-9847 Pede, Avenue","postalZip":"53213","country":"Poland"},{"customerId":1789,"customerName":"Georgia Nash","phone":"(969) 557-6952","email":"turpis.nec@outlook.com","address":"P.O. Box 944, 6476 Interdum. St.","postalZip":"8925","country":"Ukraine"},{"customerId":1790,"customerName":"Dara Riley","phone":"(526) 520-1646","email":"phasellus.in@icloud.org","address":"P.O. Box 441, 426 Eu Rd.","postalZip":"B7A 8T3","country":"Philippines"},{"customerId":1791,"customerName":"Belle Warner","phone":"1-415-566-7517","email":"blandit.at.nisi@outlook.net","address":"549-8717 Dui Rd.","postalZip":"758163","country":"Austria"},{"customerId":1792,"customerName":"Coby Merritt","phone":"1-618-671-8465","email":"ipsum@yahoo.couk","address":"Ap #785-8280 Mauris Rd.","postalZip":"644746","country":"Ukraine"},{"customerId":1793,"customerName":"Mannix Haynes","phone":"1-554-897-5620","email":"et@protonmail.edu","address":"P.O. Box 131, 6568 A St.","postalZip":"165169","country":"France"},{"customerId":1794,"customerName":"Blossom Kemp","phone":"1-854-674-8451","email":"adipiscing.mauris@icloud.net","address":"P.O. Box 128, 9829 Nulla. Avenue","postalZip":"216419","country":"Costa Rica"},{"customerId":1795,"customerName":"Ferris Greene","phone":"(532) 724-8962","email":"convallis.ligula@icloud.edu","address":"814-9823 Est. Street","postalZip":"445322","country":"Indonesia"},{"customerId":1796,"customerName":"Anika Petersen","phone":"1-263-356-6285","email":"adipiscing.enim@protonmail.net","address":"Ap #757-2085 In Road","postalZip":"58602-945","country":"Pakistan"},{"customerId":1797,"customerName":"Thane Lewis","phone":"(621) 351-7054","email":"porttitor.vulputate@google.ca","address":"P.O. Box 128, 7773 Eu, St.","postalZip":"43346-654","country":"Pakistan"},{"customerId":1798,"customerName":"Harriet Buckner","phone":"(341) 946-9522","email":"facilisis@hotmail.edu","address":"Ap #811-1435 Cursus Rd.","postalZip":"33541","country":"Philippines"},{"customerId":1799,"customerName":"Ishmael Haley","phone":"(172) 970-7286","email":"nec.quam.curabitur@protonmail.ca","address":"606-6505 Nulla Ave","postalZip":"27874","country":"Turkey"},{"customerId":1800,"customerName":"Hayes Heath","phone":"(294) 863-1797","email":"dapibus.ligula.aliquam@google.org","address":"802-7664 Sit Street","postalZip":"5841","country":"Ireland"},{"customerId":1801,"customerName":"Ivor Yang","phone":"1-489-721-6641","email":"sed@icloud.com","address":"Ap #511-8042 Turpis. Av.","postalZip":"30414","country":"Belgium"},{"customerId":1802,"customerName":"Zachary Fuller","phone":"(569) 501-6280","email":"curabitur.vel@outlook.edu","address":"Ap #479-149 Mi Road","postalZip":"45138-56581","country":"China"},{"customerId":1803,"customerName":"Boris Carr","phone":"(246) 426-8635","email":"nunc.mauris@hotmail.edu","address":"5988 Augue Rd.","postalZip":"71483","country":"Norway"},{"customerId":1804,"customerName":"Jillian Hester","phone":"1-842-170-8880","email":"libero.donec.consectetuer@yahoo.ca","address":"Ap #473-5694 Donec Street","postalZip":"13735","country":"Indonesia"},{"customerId":1805,"customerName":"Molly Curtis","phone":"1-463-287-9365","email":"donec.non.justo@protonmail.net","address":"Ap #100-5411 Integer Street","postalZip":"62107","country":"Brazil"},{"customerId":1806,"customerName":"August Glenn","phone":"(786) 700-3867","email":"auctor.non.feugiat@hotmail.org","address":"Ap #102-6496 Tincidunt Rd.","postalZip":"71173","country":"Turkey"},{"customerId":1807,"customerName":"Guinevere Watkins","phone":"1-744-686-4053","email":"suspendisse.aliquet@outlook.com","address":"346-3526 Aliquam Road","postalZip":"78-885","country":"Austria"},{"customerId":1808,"customerName":"Fletcher Snyder","phone":"(782) 222-2403","email":"aliquam.rutrum@yahoo.couk","address":"299-6142 Mauris, St.","postalZip":"15543","country":"Colombia"},{"customerId":1809,"customerName":"Emi Hendricks","phone":"1-365-569-6802","email":"maecenas.iaculis.aliquet@google.org","address":"Ap #468-2981 Molestie Rd.","postalZip":"139735","country":"Netherlands"},{"customerId":1810,"customerName":"Griffith Koch","phone":"1-677-712-7032","email":"diam@icloud.edu","address":"848-5850 Ante Street","postalZip":"273287","country":"Indonesia"},{"customerId":1811,"customerName":"Oleg Benson","phone":"1-438-842-5605","email":"enim.sit@outlook.edu","address":"966-7757 Cras Av.","postalZip":"932172","country":"Mexico"},{"customerId":1812,"customerName":"Brian Tanner","phone":"1-522-315-2414","email":"nec@icloud.ca","address":"Ap #784-640 Nunc, Rd.","postalZip":"9305","country":"Spain"},{"customerId":1813,"customerName":"Macaulay Emerson","phone":"1-256-558-1718","email":"dolor.sit.amet@protonmail.net","address":"602-1910 Egestas St.","postalZip":"5143","country":"Sweden"},{"customerId":1814,"customerName":"Donovan Farrell","phone":"1-262-998-8322","email":"a@outlook.com","address":"3197 Auctor Ave","postalZip":"660874","country":"Germany"},{"customerId":1815,"customerName":"Jack Mcgowan","phone":"1-844-617-1574","email":"ipsum.cursus@icloud.couk","address":"7325 Sagittis Rd.","postalZip":"844446","country":"Italy"},{"customerId":1816,"customerName":"Carly Sweet","phone":"(809) 648-3876","email":"amet.diam.eu@outlook.org","address":"Ap #622-1658 Mauris Rd.","postalZip":"80270-737","country":"Netherlands"},{"customerId":1817,"customerName":"Jemima Foley","phone":"1-852-247-2287","email":"semper.nam@yahoo.com","address":"Ap #770-6836 Vitae, Rd.","postalZip":"S71 2ME","country":"Italy"},{"customerId":1818,"customerName":"Cameron Norton","phone":"(239) 640-5270","email":"libero.lacus.varius@google.net","address":"970 Cursus. Rd.","postalZip":"3864","country":"Singapore"},{"customerId":1819,"customerName":"Cameron Moran","phone":"1-335-431-4146","email":"adipiscing@protonmail.org","address":"Ap #699-2557 Non Av.","postalZip":"82601","country":"Philippines"},{"customerId":1820,"customerName":"Harper Chang","phone":"(657) 168-5387","email":"phasellus@aol.ca","address":"P.O. Box 583, 4501 Netus Avenue","postalZip":"52-85","country":"South Korea"},{"customerId":1821,"customerName":"Wayne Ward","phone":"(103) 545-3443","email":"accumsan.neque@icloud.ca","address":"472-2686 Morbi Rd.","postalZip":"67283-89433","country":"Indonesia"},{"customerId":1822,"customerName":"Melanie Lopez","phone":"(400) 623-2558","email":"nibh.quisque.nonummy@yahoo.net","address":"Ap #911-261 Bibendum St.","postalZip":"49474","country":"Austria"},{"customerId":1823,"customerName":"Emi Maddox","phone":"1-416-492-6492","email":"enim.mi.tempor@google.ca","address":"692-6228 Vitae, Rd.","postalZip":"842514","country":"Brazil"},{"customerId":1824,"customerName":"Anjolie Lara","phone":"(864) 413-3315","email":"praesent.interdum.ligula@google.org","address":"595-325 Suspendisse Road","postalZip":"4426 UI","country":"Ukraine"},{"customerId":1825,"customerName":"Quail Norris","phone":"1-257-603-7737","email":"dolor.tempus@protonmail.couk","address":"213-8882 Lorem Street","postalZip":"22038","country":"Russian Federation"},{"customerId":1826,"customerName":"Marah Fletcher","phone":"(326) 705-0128","email":"faucibus.lectus@hotmail.org","address":"764-8019 Pede Road","postalZip":"58238","country":"Norway"},{"customerId":1827,"customerName":"Melinda Grant","phone":"(370) 534-5882","email":"est@yahoo.com","address":"184-2603 Tellus, Avenue","postalZip":"5477","country":"Chile"},{"customerId":1828,"customerName":"Cleo Tate","phone":"1-618-442-5272","email":"lectus.a@aol.couk","address":"2491 Et, Rd.","postalZip":"50106","country":"Indonesia"},{"customerId":1829,"customerName":"Keefe Carlson","phone":"(912) 721-8764","email":"dolor.nonummy@aol.edu","address":"298-2756 Ornare Av.","postalZip":"13995","country":"Pakistan"},{"customerId":1830,"customerName":"Chandler Underwood","phone":"1-412-911-1417","email":"cursus.et.eros@outlook.com","address":"867-8864 Sollicitudin Street","postalZip":"8764","country":"Singapore"},{"customerId":1831,"customerName":"Gavin House","phone":"1-545-851-8989","email":"diam.eu@aol.org","address":"Ap #139-5780 Amet Ave","postalZip":"03150","country":"Ukraine"},{"customerId":1832,"customerName":"Alan Shelton","phone":"1-556-476-3653","email":"ante@google.org","address":"105-8354 Proin Street","postalZip":"5148 LO","country":"Germany"},{"customerId":1833,"customerName":"Wylie Trujillo","phone":"(437) 892-2136","email":"ante@hotmail.edu","address":"Ap #350-8470 Posuere, Rd.","postalZip":"622673","country":"Canada"},{"customerId":1834,"customerName":"Oliver Nguyen","phone":"1-929-736-1834","email":"orci.lobortis@google.org","address":"P.O. Box 882, 5936 Vitae Ave","postalZip":"H2L 6E1","country":"New Zealand"},{"customerId":1835,"customerName":"Isabelle Velasquez","phone":"(453) 153-4523","email":"eget@aol.org","address":"Ap #244-7627 Augue Rd.","postalZip":"783117","country":"Ukraine"},{"customerId":1836,"customerName":"Regina Weiss","phone":"1-586-355-1362","email":"a.enim@hotmail.couk","address":"596-7708 Ipsum. St.","postalZip":"89226-240","country":"South Africa"},{"customerId":1837,"customerName":"Rae Shaffer","phone":"1-559-617-2783","email":"sagittis.nullam@icloud.org","address":"564-8586 Lobortis Av.","postalZip":"3484","country":"Philippines"},{"customerId":1838,"customerName":"Cairo Mays","phone":"1-761-394-8886","email":"donec.egestas.aliquam@icloud.ca","address":"824-9965 Pellentesque Av.","postalZip":"38-26","country":"Singapore"},{"customerId":1839,"customerName":"Nigel Rodriguez","phone":"(465) 414-1401","email":"sem.ut@outlook.couk","address":"9904 Lorem, St.","postalZip":"80569","country":"Germany"},{"customerId":1840,"customerName":"Allen Edwards","phone":"(485) 774-2467","email":"pellentesque@protonmail.com","address":"864-7078 Dolor. Rd.","postalZip":"689563","country":"Australia"},{"customerId":1841,"customerName":"Reuben Rios","phone":"1-673-192-7641","email":"ridiculus.mus@yahoo.ca","address":"701-8932 Vulputate Rd.","postalZip":"11405","country":"Chile"},{"customerId":1842,"customerName":"Astra Lawson","phone":"1-688-844-0044","email":"nec@google.org","address":"P.O. Box 790, 9203 Ligula. Street","postalZip":"67381","country":"United Kingdom"},{"customerId":1843,"customerName":"Stewart Doyle","phone":"(685) 545-4664","email":"vel@yahoo.org","address":"316-9869 Lectus, Road","postalZip":"464974","country":"Nigeria"},{"customerId":1844,"customerName":"Jessica King","phone":"1-702-407-6351","email":"in.lobortis.tellus@aol.ca","address":"Ap #641-2258 Quam, Rd.","postalZip":"81366","country":"Ireland"},{"customerId":1845,"customerName":"Jesse Conrad","phone":"1-495-767-7781","email":"augue.ut@google.couk","address":"Ap #240-3069 Mauris Street","postalZip":"2863","country":"Poland"},{"customerId":1846,"customerName":"Tiger Levy","phone":"(393) 157-3425","email":"ultricies@protonmail.org","address":"578-5644 Nec Road","postalZip":"11809","country":"Netherlands"},{"customerId":1847,"customerName":"Clare Davenport","phone":"1-467-256-4453","email":"cum.sociis@outlook.edu","address":"438-6184 Cras Street","postalZip":"77763-03658","country":"Peru"},{"customerId":1848,"customerName":"Austin Cortez","phone":"1-451-457-6747","email":"blandit@hotmail.edu","address":"495-8379 Est, Ave","postalZip":"25769","country":"New Zealand"},{"customerId":1849,"customerName":"Amir Blanchard","phone":"1-524-281-3189","email":"pharetra.sed@protonmail.ca","address":"Ap #257-7017 Lorem Avenue","postalZip":"957693","country":"Ireland"},{"customerId":1850,"customerName":"Peter Mcclure","phone":"(657) 563-2573","email":"erat.volutpat@protonmail.edu","address":"P.O. Box 689, 4758 Phasellus Road","postalZip":"28319","country":"Indonesia"},{"customerId":1851,"customerName":"Marah Mcpherson","phone":"(345) 412-8313","email":"augue.id@yahoo.net","address":"311-597 Enim, Road","postalZip":"44941","country":"South Africa"},{"customerId":1852,"customerName":"Erasmus Kramer","phone":"1-982-775-5286","email":"ultrices@hotmail.net","address":"1645 Nascetur Ave","postalZip":"1135","country":"Philippines"},{"customerId":1853,"customerName":"Omar Joyce","phone":"(322) 926-2331","email":"consectetuer.adipiscing@aol.couk","address":"Ap #177-7427 Pharetra Av.","postalZip":"4282","country":"United Kingdom"},{"customerId":1854,"customerName":"August Cervantes","phone":"(530) 972-2722","email":"dignissim.magna@hotmail.com","address":"Ap #959-9935 Dui. Street","postalZip":"13723","country":"South Korea"},{"customerId":1855,"customerName":"Stella Foster","phone":"1-437-227-4156","email":"vitae@yahoo.edu","address":"4300 Elit. Ave","postalZip":"82-667","country":"Spain"},{"customerId":1856,"customerName":"Gloria Baxter","phone":"(719) 881-1924","email":"velit.eget.laoreet@icloud.edu","address":"Ap #811-2759 Senectus Av.","postalZip":"93364","country":"Philippines"},{"customerId":1857,"customerName":"Kuame Wagner","phone":"(865) 181-7591","email":"egestas@aol.edu","address":"981-652 Vel, Rd.","postalZip":"548823","country":"Brazil"},{"customerId":1858,"customerName":"Hakeem Manning","phone":"1-307-542-8165","email":"amet@outlook.edu","address":"P.O. Box 929, 9971 Odio Rd.","postalZip":"684633","country":"Belgium"},{"customerId":1859,"customerName":"Stella Griffith","phone":"1-751-899-6737","email":"fusce.mollis@aol.ca","address":"Ap #551-438 In, Rd.","postalZip":"8843","country":"Ireland"},{"customerId":1860,"customerName":"Ivory Spence","phone":"(547) 148-2471","email":"enim@protonmail.couk","address":"625-8735 Sapien, St.","postalZip":"51111","country":"Italy"},{"customerId":1861,"customerName":"Francis Myers","phone":"1-772-272-5804","email":"aliquam.enim@protonmail.couk","address":"P.O. Box 939, 6243 Id, Ave","postalZip":"67357-78060","country":"Austria"},{"customerId":1862,"customerName":"Alexander Brady","phone":"1-729-342-0668","email":"sociis.natoque@yahoo.ca","address":"322-4405 Quis, St.","postalZip":"645196","country":"Russian Federation"},{"customerId":1863,"customerName":"Carlos Molina","phone":"1-276-809-9145","email":"diam.luctus@hotmail.ca","address":"787-6465 Dolor Rd.","postalZip":"719618","country":"Peru"},{"customerId":1864,"customerName":"Allen Jones","phone":"1-301-303-1943","email":"elit.elit@protonmail.couk","address":"Ap #603-2462 In St.","postalZip":"34225","country":"Russian Federation"},{"customerId":1865,"customerName":"Adena Rodgers","phone":"(556) 234-5054","email":"aliquet.libero@icloud.ca","address":"581-7426 Erat. Ave","postalZip":"866795","country":"France"},{"customerId":1866,"customerName":"Kieran Fowler","phone":"1-466-346-1457","email":"enim@protonmail.net","address":"956-4438 Id, St.","postalZip":"2770","country":"Germany"},{"customerId":1867,"customerName":"Arthur Sims","phone":"1-526-733-2899","email":"sem.consequat@yahoo.org","address":"P.O. Box 257, 5793 Urna. Street","postalZip":"72860","country":"Germany"},{"customerId":1868,"customerName":"Kenneth Walker","phone":"(414) 375-4371","email":"tincidunt.orci@hotmail.ca","address":"9592 Curabitur Rd.","postalZip":"35787","country":"Sweden"},{"customerId":1869,"customerName":"Ryder Powell","phone":"1-624-490-8582","email":"etiam@outlook.edu","address":"P.O. Box 161, 4903 Condimentum Rd.","postalZip":"8215","country":"Sweden"},{"customerId":1870,"customerName":"Genevieve Haynes","phone":"(965) 865-1548","email":"aliquam.eros.turpis@hotmail.edu","address":"862-5038 Non, St.","postalZip":"40504","country":"South Africa"},{"customerId":1871,"customerName":"Flynn Carver","phone":"(146) 235-7187","email":"eget.magna.suspendisse@icloud.edu","address":"Ap #702-5604 Eros. Road","postalZip":"36742-72244","country":"Singapore"},{"customerId":1872,"customerName":"Nicholas Horn","phone":"(263) 162-8732","email":"in.condimentum.donec@hotmail.ca","address":"739-4887 Diam Avenue","postalZip":"36594","country":"Brazil"},{"customerId":1873,"customerName":"Elton Barrera","phone":"1-297-797-6663","email":"ipsum.cursus.vestibulum@hotmail.edu","address":"109-8487 Ut Street","postalZip":"62554","country":"Ukraine"},{"customerId":1874,"customerName":"Garrett Mitchell","phone":"1-809-782-4524","email":"iaculis.odio.nam@protonmail.net","address":"Ap #154-5465 Facilisis St.","postalZip":"5643","country":"Belgium"},{"customerId":1875,"customerName":"Willa Wooten","phone":"1-734-268-2036","email":"est@yahoo.edu","address":"290-6395 Sed Ave","postalZip":"40707","country":"Pakistan"},{"customerId":1876,"customerName":"Octavius Mclean","phone":"1-465-326-6802","email":"blandit.enim.consequat@icloud.ca","address":"Ap #327-7237 Sed St.","postalZip":"S2Y 4B3","country":"United Kingdom"},{"customerId":1877,"customerName":"Deacon Cole","phone":"1-378-653-0840","email":"aliquam.eros@aol.edu","address":"2005 Ipsum Street","postalZip":"6386-8474","country":"France"},{"customerId":1878,"customerName":"Neville Noel","phone":"(811) 751-2258","email":"pulvinar.arcu.et@google.org","address":"P.O. Box 533, 9794 Donec Avenue","postalZip":"1712","country":"Ireland"},{"customerId":1879,"customerName":"Drake Alford","phone":"(541) 288-4877","email":"vulputate@icloud.com","address":"Ap #325-3628 Posuere St.","postalZip":"13447","country":"Italy"},{"customerId":1880,"customerName":"Melodie Bell","phone":"1-226-713-4345","email":"nisl.arcu@aol.edu","address":"6366 Eget Avenue","postalZip":"56836","country":"Peru"},{"customerId":1881,"customerName":"Brittany Townsend","phone":"(642) 416-3802","email":"scelerisque@google.net","address":"P.O. Box 166, 8614 Tincidunt. Ave","postalZip":"33118","country":"Nigeria"},{"customerId":1882,"customerName":"Brynn Hopkins","phone":"(629) 129-1863","email":"ipsum.nunc.id@protonmail.edu","address":"4848 Porta Avenue","postalZip":"236166","country":"United States"},{"customerId":1883,"customerName":"Justina Sharpe","phone":"(772) 338-7876","email":"duis.cursus.diam@aol.net","address":"Ap #673-6972 Sed Avenue","postalZip":"857193","country":"Italy"},{"customerId":1884,"customerName":"Lani Daniels","phone":"(611) 166-0409","email":"mauris@yahoo.com","address":"Ap #953-7019 Nam Road","postalZip":"2385","country":"Colombia"},{"customerId":1885,"customerName":"Matthew Wynn","phone":"(783) 513-6115","email":"egestas.nunc@aol.couk","address":"602-1593 Etiam Av.","postalZip":"785833","country":"Netherlands"},{"customerId":1886,"customerName":"Abraham Cook","phone":"1-265-617-2884","email":"sit.amet@icloud.com","address":"3257 Cursus St.","postalZip":"3753","country":"Canada"},{"customerId":1887,"customerName":"Iliana Hendrix","phone":"1-284-146-8871","email":"curabitur@icloud.org","address":"P.O. Box 395, 3399 Sociis Rd.","postalZip":"7333","country":"Brazil"},{"customerId":1888,"customerName":"William Odom","phone":"1-690-135-9943","email":"facilisis.magna.tellus@aol.com","address":"Ap #802-3901 Tincidunt St.","postalZip":"3211","country":"Vietnam"},{"customerId":1889,"customerName":"Dominic Dodson","phone":"1-606-466-3392","email":"lobortis.quis.pede@google.net","address":"P.O. Box 458, 5161 Ligula Road","postalZip":"15721","country":"Sweden"},{"customerId":1890,"customerName":"Abbot Mercer","phone":"1-156-112-8805","email":"non.lorem@yahoo.couk","address":"P.O. Box 483, 7081 Parturient Avenue","postalZip":"284439","country":"Canada"},{"customerId":1891,"customerName":"Kylynn Jacobson","phone":"(678) 435-0864","email":"orci.adipiscing@google.com","address":"Ap #165-9838 Donec Street","postalZip":"78448","country":"South Korea"},{"customerId":1892,"customerName":"Emery Fisher","phone":"(123) 890-4325","email":"nisl@outlook.net","address":"327-1458 Pede Av.","postalZip":"724060","country":"Chile"},{"customerId":1893,"customerName":"Aquila Morales","phone":"1-662-209-8121","email":"amet.massa@aol.net","address":"5212 Nam Rd.","postalZip":"34052","country":"France"},{"customerId":1894,"customerName":"Steel Alvarez","phone":"1-772-611-8442","email":"in@outlook.couk","address":"8797 Quisque St.","postalZip":"345474","country":"South Korea"},{"customerId":1895,"customerName":"Ciaran Hickman","phone":"1-636-894-1656","email":"mi.tempor.lorem@google.edu","address":"634 Purus Street","postalZip":"5413","country":"Poland"},{"customerId":1896,"customerName":"Cheyenne Pickett","phone":"1-421-154-6217","email":"faucibus.ut@aol.couk","address":"Ap #750-8413 Sit Avenue","postalZip":"89317","country":"New Zealand"},{"customerId":1897,"customerName":"Stacey Frost","phone":"1-205-688-5415","email":"phasellus.dapibus.quam@icloud.net","address":"2731 Convallis Rd.","postalZip":"54N 8K3","country":"Indonesia"},{"customerId":1898,"customerName":"Chanda Short","phone":"1-246-625-1117","email":"vulputate.mauris.sagittis@protonmail.org","address":"Ap #651-7627 Convallis Ave","postalZip":"600991","country":"Ukraine"},{"customerId":1899,"customerName":"Hayden Nicholson","phone":"(252) 843-7630","email":"nisi.cum@yahoo.org","address":"P.O. Box 538, 654 Quam, Ave","postalZip":"345713","country":"Costa Rica"},{"customerId":1900,"customerName":"Ingrid Lamb","phone":"1-215-787-8326","email":"lorem.ut.aliquam@aol.org","address":"Ap #694-6769 Est, Avenue","postalZip":"249507","country":"United States"},{"customerId":1901,"customerName":"Hillary Rutledge","phone":"(685) 647-1350","email":"sodales.elit@hotmail.couk","address":"Ap #929-8555 In St.","postalZip":"64695","country":"Turkey"},{"customerId":1902,"customerName":"McKenzie Woods","phone":"(481) 275-8422","email":"egestas.hendrerit.neque@google.couk","address":"Ap #744-6078 Integer Rd.","postalZip":"248827","country":"Ireland"},{"customerId":1903,"customerName":"Britanni Hurley","phone":"1-359-677-1812","email":"dictum@protonmail.edu","address":"783-1472 Molestie Rd.","postalZip":"B1C 6S0","country":"South Korea"},{"customerId":1904,"customerName":"Brynne Hendrix","phone":"(425) 432-1859","email":"scelerisque.lorem@hotmail.ca","address":"812-3306 Cursus St.","postalZip":"98852-87194","country":"Philippines"},{"customerId":1905,"customerName":"Alan Wise","phone":"(695) 334-4756","email":"lorem.vitae@hotmail.org","address":"3894 Nunc, Street","postalZip":"15443","country":"Turkey"},{"customerId":1906,"customerName":"Baker Stuart","phone":"1-645-318-1323","email":"lobortis@aol.com","address":"P.O. Box 115, 3968 Auctor. Avenue","postalZip":"683633","country":"Chile"},{"customerId":1907,"customerName":"Jack Knowles","phone":"(865) 646-0104","email":"ligula.nullam.enim@outlook.ca","address":"P.O. Box 503, 1481 Nonummy Avenue","postalZip":"6038 FX","country":"Sweden"},{"customerId":1908,"customerName":"Ferdinand Phelps","phone":"(882) 377-4211","email":"interdum.nunc@outlook.edu","address":"Ap #673-6139 Libero St.","postalZip":"84115","country":"Italy"},{"customerId":1909,"customerName":"September Phillips","phone":"1-820-498-4893","email":"sem@icloud.couk","address":"Ap #580-178 Metus. St.","postalZip":"87564","country":"Austria"},{"customerId":1910,"customerName":"Kimberly Figueroa","phone":"(625) 380-4152","email":"massa.mauris@yahoo.ca","address":"Ap #947-7054 Felis Avenue","postalZip":"333803","country":"Norway"},{"customerId":1911,"customerName":"Adara Eaton","phone":"1-331-418-6738","email":"lectus.ante@aol.com","address":"P.O. Box 323, 621 Mauris Rd.","postalZip":"466335","country":"South Korea"},{"customerId":1912,"customerName":"Ivor Benton","phone":"1-254-872-3154","email":"sem.vitae@aol.net","address":"755-1841 Interdum. Street","postalZip":"35623","country":"Germany"},{"customerId":1913,"customerName":"Priscilla Haley","phone":"(367) 358-2304","email":"in.magna@hotmail.net","address":"Ap #594-2415 Adipiscing Rd.","postalZip":"4447","country":"Nigeria"},{"customerId":1914,"customerName":"Wyoming Talley","phone":"(570) 793-8155","email":"in.faucibus@icloud.net","address":"7385 Cursus. Ave","postalZip":"18723-511","country":"Peru"},{"customerId":1915,"customerName":"Theodore Whitley","phone":"(584) 671-6377","email":"tellus.eu@yahoo.net","address":"Ap #687-2211 Quam Ave","postalZip":"2236","country":"Australia"},{"customerId":1916,"customerName":"Adam Ross","phone":"1-923-536-2401","email":"tempor.diam@aol.ca","address":"Ap #445-6340 Malesuada. Av.","postalZip":"561431","country":"France"},{"customerId":1917,"customerName":"Sophia Pugh","phone":"(834) 291-7660","email":"nunc.interdum@outlook.org","address":"Ap #657-3714 Arcu Street","postalZip":"1352","country":"Mexico"},{"customerId":1918,"customerName":"Desirae Gates","phone":"(437) 628-8912","email":"malesuada.fringilla.est@protonmail.net","address":"Ap #445-8866 Sit St.","postalZip":"192504","country":"Norway"},{"customerId":1919,"customerName":"Tad Fisher","phone":"1-112-372-7529","email":"et.magnis@protonmail.com","address":"3946 Vulputate, St.","postalZip":"57-026","country":"India"},{"customerId":1920,"customerName":"Colette Duke","phone":"1-802-387-2346","email":"eget.nisi@google.couk","address":"P.O. Box 611, 2783 Augue St.","postalZip":"86585","country":"South Korea"},{"customerId":1921,"customerName":"Yolanda Mosley","phone":"(462) 737-9037","email":"urna@protonmail.couk","address":"1350 Non Avenue","postalZip":"07-758","country":"Ukraine"},{"customerId":1922,"customerName":"Cathleen Best","phone":"(863) 686-4677","email":"a.enim@outlook.org","address":"Ap #545-7936 Lectus Rd.","postalZip":"32609","country":"New Zealand"},{"customerId":1923,"customerName":"Galena Mueller","phone":"(257) 331-8978","email":"sit@hotmail.org","address":"8386 Adipiscing St.","postalZip":"7096-3056","country":"Turkey"},{"customerId":1924,"customerName":"Zane Fuentes","phone":"1-191-322-5677","email":"amet@outlook.org","address":"Ap #419-7784 Semper Rd.","postalZip":"67247","country":"United States"},{"customerId":1925,"customerName":"Lee Romero","phone":"(675) 103-3374","email":"dolor.quisque@icloud.com","address":"Ap #613-9414 Nec Av.","postalZip":"375359","country":"Belgium"},{"customerId":1926,"customerName":"Bree Christensen","phone":"1-228-192-4787","email":"sed.sem.egestas@hotmail.org","address":"Ap #455-3187 Nisi Rd.","postalZip":"42817","country":"Canada"},{"customerId":1927,"customerName":"Phelan Hammond","phone":"1-329-234-5222","email":"ut.sagittis@icloud.couk","address":"P.O. Box 814, 581 Mauris St.","postalZip":"28452","country":"Nigeria"},{"customerId":1928,"customerName":"Noel O'Neill","phone":"1-434-358-5842","email":"mauris.sit@outlook.ca","address":"6391 Vitae Road","postalZip":"F2 5NZ","country":"Singapore"},{"customerId":1929,"customerName":"Quinn Ballard","phone":"(351) 846-1611","email":"ut.sem.nulla@outlook.ca","address":"377-3132 Et, Avenue","postalZip":"6516","country":"France"},{"customerId":1930,"customerName":"Jane French","phone":"(588) 297-5859","email":"mauris@outlook.org","address":"9514 Nulla Road","postalZip":"87-17","country":"Belgium"},{"customerId":1931,"customerName":"Samson Pate","phone":"1-256-274-5718","email":"eleifend.egestas@yahoo.com","address":"335-2976 Non, Avenue","postalZip":"302914","country":"China"},{"customerId":1932,"customerName":"Lee Bates","phone":"1-522-851-7746","email":"mi.enim.condimentum@icloud.com","address":"Ap #705-7521 Rutrum Rd.","postalZip":"88-378","country":"Russian Federation"},{"customerId":1933,"customerName":"Galena Burke","phone":"1-660-152-5750","email":"turpis.non.enim@icloud.edu","address":"Ap #514-8587 Mi Street","postalZip":"392162","country":"India"},{"customerId":1934,"customerName":"Zelda Sharpe","phone":"1-944-292-7168","email":"erat.neque@google.couk","address":"P.O. Box 978, 647 Arcu. Rd.","postalZip":"4439","country":"Germany"},{"customerId":1935,"customerName":"Alec Wolfe","phone":"(755) 259-5304","email":"ac.mattis.velit@yahoo.org","address":"318-1151 Fusce Avenue","postalZip":"984295","country":"United States"},{"customerId":1936,"customerName":"Lewis Montoya","phone":"1-425-513-1726","email":"orci@icloud.net","address":"P.O. Box 924, 3652 Nam Av.","postalZip":"98182-41395","country":"New Zealand"},{"customerId":1937,"customerName":"Yael Mercado","phone":"(633) 702-6704","email":"iaculis.lacus.pede@google.edu","address":"Ap #752-3027 In Rd.","postalZip":"131797","country":"Indonesia"},{"customerId":1938,"customerName":"Damian Cummings","phone":"1-535-648-2572","email":"suspendisse.ac.metus@aol.com","address":"759-956 Mollis. Street","postalZip":"0158","country":"Vietnam"},{"customerId":1939,"customerName":"Dustin Chaney","phone":"(503) 886-0665","email":"eget@yahoo.couk","address":"3178 Ligula. Rd.","postalZip":"58118-164","country":"Costa Rica"},{"customerId":1940,"customerName":"Shelly Bryan","phone":"(311) 726-0887","email":"eros.turpis.non@protonmail.net","address":"P.O. Box 604, 6770 Dui, Ave","postalZip":"387948","country":"New Zealand"},{"customerId":1941,"customerName":"Charlotte Meadows","phone":"(639) 893-2124","email":"donec.felis@hotmail.ca","address":"P.O. Box 858, 8575 Ipsum Avenue","postalZip":"13225","country":"Peru"},{"customerId":1942,"customerName":"Kenyon Camacho","phone":"1-861-321-8402","email":"varius.nam@yahoo.ca","address":"122-1077 Turpis Road","postalZip":"342261","country":"Singapore"},{"customerId":1943,"customerName":"Leah Singleton","phone":"(462) 129-3256","email":"auctor.velit.aliquam@protonmail.com","address":"8729 Congue. Avenue","postalZip":"12026","country":"Germany"},{"customerId":1944,"customerName":"Jerry Skinner","phone":"(938) 358-7523","email":"ullamcorper.nisl@outlook.ca","address":"Ap #749-5734 Orci Street","postalZip":"2128","country":"Vietnam"},{"customerId":1945,"customerName":"Thaddeus Rosario","phone":"1-548-788-8153","email":"orci@google.couk","address":"906-1436 Orci Avenue","postalZip":"50517","country":"Netherlands"},{"customerId":1946,"customerName":"Abdul Love","phone":"(445) 835-6892","email":"a.tortor.nunc@outlook.ca","address":"Ap #203-3317 Eu Av.","postalZip":"45-541","country":"Belgium"},{"customerId":1947,"customerName":"Karly Knox","phone":"1-582-259-6876","email":"turpis.non@google.net","address":"488-4553 Odio. Street","postalZip":"121636","country":"Mexico"},{"customerId":1948,"customerName":"Maggie Maldonado","phone":"(750) 440-4269","email":"est.arcu.ac@protonmail.couk","address":"P.O. Box 871, 4738 Amet Rd.","postalZip":"911828","country":"Netherlands"},{"customerId":1949,"customerName":"Andrew Carroll","phone":"1-651-717-7573","email":"sapien.gravida@aol.couk","address":"Ap #313-7897 Non, Street","postalZip":"36-82","country":"Vietnam"},{"customerId":1950,"customerName":"Lana Reese","phone":"1-461-611-6288","email":"mus.proin@aol.net","address":"5898 Et Avenue","postalZip":"21157","country":"France"},{"customerId":1951,"customerName":"Althea Delgado","phone":"1-245-556-7878","email":"interdum.curabitur@google.ca","address":"490-8010 Porttitor Rd.","postalZip":"9839","country":"Australia"},{"customerId":1952,"customerName":"Forrest Dunlap","phone":"(902) 334-7146","email":"praesent.interdum@yahoo.edu","address":"Ap #168-8759 Tristique Rd.","postalZip":"41-162","country":"Norway"},{"customerId":1953,"customerName":"Dora Schneider","phone":"(815) 642-8375","email":"libero@icloud.net","address":"279-7895 Fermentum St.","postalZip":"17558-56886","country":"United Kingdom"},{"customerId":1954,"customerName":"Gary Gaines","phone":"(603) 584-0047","email":"maecenas.mi@hotmail.com","address":"227-5991 Lacus. Rd.","postalZip":"874838","country":"China"},{"customerId":1955,"customerName":"Darryl Brennan","phone":"1-952-835-5827","email":"mi@hotmail.couk","address":"546-9418 Ad Av.","postalZip":"11371-28674","country":"New Zealand"},{"customerId":1956,"customerName":"Autumn Murphy","phone":"(944) 534-8183","email":"fermentum@outlook.edu","address":"P.O. Box 789, 1377 Et, Ave","postalZip":"12420","country":"Norway"},{"customerId":1957,"customerName":"Donna Castaneda","phone":"1-964-677-2689","email":"semper.tellus@icloud.com","address":"4979 Vitae Rd.","postalZip":"D2 6MG","country":"Nigeria"},{"customerId":1958,"customerName":"Kirby Kelley","phone":"(814) 225-8824","email":"mauris.erat@yahoo.edu","address":"568-4879 Quisque Av.","postalZip":"648468","country":"Russian Federation"},{"customerId":1959,"customerName":"Elmo Reilly","phone":"(774) 232-2605","email":"velit.cras@aol.couk","address":"2451 Porttitor St.","postalZip":"00-320","country":"United Kingdom"},{"customerId":1960,"customerName":"Gage Johnston","phone":"1-167-686-3155","email":"enim@google.edu","address":"Ap #467-7607 Mi Av.","postalZip":"32-55","country":"Ireland"},{"customerId":1961,"customerName":"Malik Fischer","phone":"(883) 301-7931","email":"neque.nullam.nisl@aol.com","address":"Ap #327-7425 Netus Road","postalZip":"66-810","country":"Chile"},{"customerId":1962,"customerName":"Shelley Wilson","phone":"(703) 672-0707","email":"turpis@icloud.com","address":"Ap #954-200 Ante Av.","postalZip":"86126","country":"India"},{"customerId":1963,"customerName":"Raymond Price","phone":"1-563-164-6654","email":"ante@outlook.edu","address":"221-9731 In Ave","postalZip":"634553","country":"India"},{"customerId":1964,"customerName":"Alden Fox","phone":"(726) 375-4844","email":"ullamcorper.magna@yahoo.ca","address":"6171 Malesuada Avenue","postalZip":"8184","country":"United States"},{"customerId":1965,"customerName":"Jerry Kelly","phone":"1-583-775-0164","email":"odio.auctor@google.ca","address":"4912 Porttitor Rd.","postalZip":"99317","country":"Ireland"},{"customerId":1966,"customerName":"Maisie Dunn","phone":"(392) 679-8155","email":"phasellus@yahoo.ca","address":"Ap #968-9517 Ante Road","postalZip":"542782","country":"Germany"},{"customerId":1967,"customerName":"Whoopi Terrell","phone":"(761) 112-3129","email":"dignissim.magna@google.couk","address":"Ap #552-4560 Cubilia St.","postalZip":"54695","country":"Vietnam"},{"customerId":1968,"customerName":"Todd Chen","phone":"(323) 673-3823","email":"phasellus.dapibus@protonmail.net","address":"P.O. Box 502, 1048 Elementum St.","postalZip":"GW1M 9IR","country":"Colombia"},{"customerId":1969,"customerName":"Lane Hickman","phone":"(378) 534-1640","email":"enim.commodo.hendrerit@hotmail.net","address":"138-830 Lectus Ave","postalZip":"B6W 4S6","country":"China"},{"customerId":1970,"customerName":"Raphael Hines","phone":"(321) 313-4834","email":"commodo.auctor.velit@hotmail.couk","address":"Ap #846-4814 Adipiscing Avenue","postalZip":"834625","country":"Australia"},{"customerId":1971,"customerName":"Selma Villarreal","phone":"1-422-129-7546","email":"euismod.enim@outlook.org","address":"P.O. Box 150, 6190 Mi Road","postalZip":"58791","country":"Mexico"},{"customerId":1972,"customerName":"Maile Hatfield","phone":"(154) 593-6400","email":"venenatis.lacus@google.net","address":"4394 Pede Ave","postalZip":"77338","country":"South Africa"},{"customerId":1973,"customerName":"Dane Conner","phone":"(338) 310-6671","email":"amet.dapibus.id@icloud.net","address":"983-7551 Sem Rd.","postalZip":"9526-8662","country":"Italy"},{"customerId":1974,"customerName":"Dylan Petty","phone":"1-201-571-4956","email":"ac.risus@google.ca","address":"Ap #310-9255 Ligula. Rd.","postalZip":"81M 1V1","country":"Ukraine"},{"customerId":1975,"customerName":"Fay Howard","phone":"(660) 402-4432","email":"sociis.natoque@outlook.com","address":"573-5343 Tellus Av.","postalZip":"11219","country":"Indonesia"},{"customerId":1976,"customerName":"Hedda Gross","phone":"(265) 412-7640","email":"arcu.aliquam@yahoo.com","address":"Ap #726-2764 Posuere St.","postalZip":"23871","country":"South Africa"},{"customerId":1977,"customerName":"Devin Burton","phone":"1-353-432-8572","email":"adipiscing.fringilla.porttitor@icloud.ca","address":"835-1832 Risus. Av.","postalZip":"47-48","country":"Nigeria"},{"customerId":1978,"customerName":"Amber Hubbard","phone":"(251) 369-7381","email":"vel@protonmail.com","address":"5651 Congue Av.","postalZip":"60761","country":"Russian Federation"},{"customerId":1979,"customerName":"Stella Warren","phone":"(730) 217-0434","email":"ipsum.dolor@yahoo.edu","address":"955-8876 Ultrices Road","postalZip":"40018","country":"South Korea"},{"customerId":1980,"customerName":"Miranda Vaughn","phone":"(286) 745-9212","email":"magna.phasellus@outlook.com","address":"Ap #795-7294 Eu Rd.","postalZip":"7394","country":"Chile"},{"customerId":1981,"customerName":"Ahmed Mckinney","phone":"(721) 976-8173","email":"proin.vel@protonmail.com","address":"6101 Orci Road","postalZip":"8564","country":"France"},{"customerId":1982,"customerName":"Felix Mcbride","phone":"1-593-527-3256","email":"aenean.eget@protonmail.edu","address":"4437 A, St.","postalZip":"78541","country":"Mexico"},{"customerId":1983,"customerName":"Vladimir Velazquez","phone":"(372) 460-7710","email":"parturient@icloud.net","address":"Ap #427-1787 Pede Av.","postalZip":"72584","country":"Ireland"},{"customerId":1984,"customerName":"Oprah England","phone":"(825) 604-3254","email":"velit.eu@hotmail.ca","address":"Ap #467-2113 Dapibus St.","postalZip":"812316","country":"Colombia"},{"customerId":1985,"customerName":"Chelsea Richard","phone":"1-233-830-6941","email":"sagittis.semper.nam@yahoo.edu","address":"Ap #120-9600 Orci. Av.","postalZip":"12226","country":"Chile"},{"customerId":1986,"customerName":"Berk Juarez","phone":"1-555-912-8835","email":"pellentesque.massa.lobortis@google.couk","address":"390-4503 Gravida St.","postalZip":"95-58","country":"Poland"},{"customerId":1987,"customerName":"Channing Mcclure","phone":"1-972-275-5207","email":"aenean@google.ca","address":"Ap #482-622 Bibendum Road","postalZip":"11856","country":"United Kingdom"},{"customerId":1988,"customerName":"Gabriel Riddle","phone":"(446) 623-3822","email":"in.mi@google.ca","address":"P.O. Box 126, 1812 Sit Ave","postalZip":"632277","country":"Austria"},{"customerId":1989,"customerName":"Laurel Montoya","phone":"1-631-215-2305","email":"dictum.eu@google.org","address":"7628 Orci Ave","postalZip":"5987","country":"United Kingdom"},{"customerId":1990,"customerName":"Stewart Vasquez","phone":"(372) 925-1206","email":"hendrerit.a.arcu@protonmail.com","address":"960-4259 Elit Ave","postalZip":"12777-34242","country":"Indonesia"},{"customerId":1991,"customerName":"Brody Bowen","phone":"1-631-977-2126","email":"gravida.sagittis@icloud.ca","address":"478 Ante. St.","postalZip":"37508","country":"China"},{"customerId":1992,"customerName":"Boris Short","phone":"1-644-724-7864","email":"pellentesque.a.facilisis@hotmail.net","address":"992-7563 Sem Street","postalZip":"5303","country":"United States"},{"customerId":1993,"customerName":"Deanna Russo","phone":"(276) 819-4043","email":"adipiscing.elit@yahoo.com","address":"P.O. Box 666, 6846 Nibh. St.","postalZip":"57881","country":"Singapore"},{"customerId":1994,"customerName":"Ahmed Ford","phone":"1-751-871-4244","email":"lobortis.augue.scelerisque@google.ca","address":"Ap #182-7880 Donec Rd.","postalZip":"5778","country":"Costa Rica"},{"customerId":1995,"customerName":"Stella Rowland","phone":"(635) 976-8426","email":"nunc@icloud.org","address":"Ap #791-7934 Semper, Rd.","postalZip":"4730 OG","country":"United States"},{"customerId":1996,"customerName":"Chiquita Weiss","phone":"1-420-691-0429","email":"dolor.fusce@yahoo.org","address":"P.O. Box 603, 623 Semper, Rd.","postalZip":"2987","country":"Norway"},{"customerId":1997,"customerName":"Hop Potter","phone":"1-862-589-7849","email":"neque.nullam@outlook.org","address":"369-8543 Erat Ave","postalZip":"Q5G 8JW","country":"Turkey"},{"customerId":1998,"customerName":"Yvette Fletcher","phone":"1-493-824-6861","email":"nec.quam@aol.org","address":"719-1513 Mus. Ave","postalZip":"188335","country":"Vietnam"},{"customerId":1999,"customerName":"Raya Chaney","phone":"1-343-252-4186","email":"ipsum.nunc.id@aol.org","address":"152-7411 Facilisis Ave","postalZip":"24-030","country":"Turkey"},{"customerId":2000,"customerName":"Oleg Morton","phone":"1-271-724-9512","email":"feugiat.nec@aol.couk","address":"6910 Ut Avenue","postalZip":"04325","country":"Poland"}] \ No newline at end of file diff --git a/BlazorBootstrap.Demo.Hosted/Client/wwwroot/sitemap.xml b/BlazorBootstrap.Demo.Hosted/Client/wwwroot/sitemap.xml deleted file mode 100644 index 483f45f4c..000000000 --- a/BlazorBootstrap.Demo.Hosted/Client/wwwroot/sitemap.xml +++ /dev/null @@ -1,118 +0,0 @@ - - - - https://demos.blazorbootstrap.com - daily - 0.9 - - - https://demos.blazorbootstrap.com/getting-started - weekly - 0.5 - - - https://demos.blazorbootstrap.com/alerts - weekly - 0.5 - - - https://demos.blazorbootstrap.com/autocomplete - weekly - 0.5 - - - https://demos.blazorbootstrap.com/breadcrumb - weekly - 0.5 - - - https://demos.blazorbootstrap.com/buttons - weekly - 0.5 - - - https://demos.blazorbootstrap.com/callout - weekly - 0.5 - - - https://demos.blazorbootstrap.com/charts - weekly - 0.5 - - - https://demos.blazorbootstrap.com/confirm-dialog - weekly - 0.5 - - - https://demos.blazorbootstrap.com/form/currency-input - weekly - 0.5 - - - https://demos.blazorbootstrap.com/grid - weekly - 0.5 - - - https://demos.blazorbootstrap.com/icons - weekly - 0.5 - - - https://demos.blazorbootstrap.com/modals - weekly - 0.5 - - - https://demos.blazorbootstrap.com/form/number-input - weekly - 0.5 - - - https://demos.blazorbootstrap.com/offcanvas - weekly - 0.5 - - - https://demos.blazorbootstrap.com/pagination - weekly - 0.5 - - - https://demos.blazorbootstrap.com/placeholders - weekly - 0.5 - - - https://demos.blazorbootstrap.com/preload - weekly - 0.5 - - - https://demos.blazorbootstrap.com/progress - weekly - 0.5 - - - https://demos.blazorbootstrap.com/form/switch - weekly - 0.5 - - - https://demos.blazorbootstrap.com/tabs - weekly - 0.5 - - - https://demos.blazorbootstrap.com/toasts - weekly - 0.5 - - - https://demos.blazorbootstrap.com/tooltips - weekly - 0.5 - - \ No newline at end of file diff --git a/BlazorBootstrap.Demo.Hosted/Server/BlazorBootstrap.Demo.Hosted.Server.csproj b/BlazorBootstrap.Demo.Hosted/Server/BlazorBootstrap.Demo.Hosted.Server.csproj deleted file mode 100644 index f377d8fcd..000000000 --- a/BlazorBootstrap.Demo.Hosted/Server/BlazorBootstrap.Demo.Hosted.Server.csproj +++ /dev/null @@ -1,18 +0,0 @@ - - - - net9.0 - enable - enable - - - - - - - - - - - - diff --git a/BlazorBootstrap.Demo.Hosted/Server/Controllers/WeatherForecastController.cs b/BlazorBootstrap.Demo.Hosted/Server/Controllers/WeatherForecastController.cs deleted file mode 100644 index 0a771f214..000000000 --- a/BlazorBootstrap.Demo.Hosted/Server/Controllers/WeatherForecastController.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Microsoft.AspNetCore.Mvc; - -namespace BlazorBootstrap.Demo.Hosted.Server.Controllers; - -[ApiController] -[Route("[controller]")] -public class WeatherForecastController : ControllerBase -{ - [HttpGet] - public string Get() => "Hello!"; -} \ No newline at end of file diff --git a/BlazorBootstrap.Demo.Hosted/Server/Pages/Error.cshtml b/BlazorBootstrap.Demo.Hosted/Server/Pages/Error.cshtml deleted file mode 100644 index 037d19f24..000000000 --- a/BlazorBootstrap.Demo.Hosted/Server/Pages/Error.cshtml +++ /dev/null @@ -1,42 +0,0 @@ -@page -@model BlazorBootstrap.Demo.Hosted.Server.Pages.ErrorModel - - - - - - - - Error - - - - - -
-
-

Error.

-

An error occurred while processing your request.

- - @if (Model.ShowRequestId) - { -

- Request ID: @Model.RequestId -

- } - -

Development Mode

-

- Swapping to the Development environment displays detailed information about the error that occurred. -

-

- The Development environment shouldn't be enabled for deployed applications. - It can result in displaying sensitive information from exceptions to end users. - For local debugging, enable the Development environment by setting the ASPNETCORE_ENVIRONMENT environment variable to Development - and restarting the app. -

-
-
- - - diff --git a/BlazorBootstrap.Demo.Hosted/Server/Pages/Error.cshtml.cs b/BlazorBootstrap.Demo.Hosted/Server/Pages/Error.cshtml.cs deleted file mode 100644 index 645de155a..000000000 --- a/BlazorBootstrap.Demo.Hosted/Server/Pages/Error.cshtml.cs +++ /dev/null @@ -1,26 +0,0 @@ -using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.Mvc.RazorPages; -using System.Diagnostics; - -namespace BlazorBootstrap.Demo.Hosted.Server.Pages; - -[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)] -[IgnoreAntiforgeryToken] -public class ErrorModel : PageModel -{ - public string? RequestId { get; set; } - - public bool ShowRequestId => !string.IsNullOrEmpty(RequestId); - - private readonly ILogger _logger; - - public ErrorModel(ILogger logger) - { - _logger = logger; - } - - public void OnGet() - { - RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier; - } -} \ No newline at end of file diff --git a/BlazorBootstrap.Demo.Hosted/Server/Pages/_Host.cshtml b/BlazorBootstrap.Demo.Hosted/Server/Pages/_Host.cshtml deleted file mode 100644 index 0ae52e044..000000000 --- a/BlazorBootstrap.Demo.Hosted/Server/Pages/_Host.cshtml +++ /dev/null @@ -1,66 +0,0 @@ -@page "/" -@using BlazorBootstrap.Demo.Hosted.Client -@using Microsoft.AspNetCore.Components.Web -@namespace BlazorBootstrap.Demo.Hosted.Server.Pages -@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers - - - - - - - Demos & Examples | An Enterprise-class Blazor Bootstrap Component library built on the Blazor and Bootstrap CSS frameworks | Blazor Bootstrap - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/BlazorBootstrap.Demo.Hosted/Server/Program.cs b/BlazorBootstrap.Demo.Hosted/Server/Program.cs deleted file mode 100644 index bbe083394..000000000 --- a/BlazorBootstrap.Demo.Hosted/Server/Program.cs +++ /dev/null @@ -1,36 +0,0 @@ -var builder = WebApplication.CreateBuilder(args); -{ - // DI - builder.Services.AddHttpClient(); - builder.Services.AddBlazorBootstrap(); - builder.Services.AddDemoServices(); - - builder.Services.AddControllersWithViews(); - builder.Services.AddRazorPages(); -} - -var app = builder.Build(); -{ - if (app.Environment.IsDevelopment()) - { - app.UseWebAssemblyDebugging(); - } - else - { - app.UseExceptionHandler("/Error"); - app.UseHsts(); - } - - app.UseHttpsRedirection(); - - app.UseBlazorFrameworkFiles(); - app.UseStaticFiles(); - - app.UseRouting(); - - app.MapRazorPages(); - app.MapControllers(); - app.MapFallbackToPage("/_Host"); - - app.Run(); -} diff --git a/BlazorBootstrap.Demo.Hosted/Server/Properties/launchSettings.json b/BlazorBootstrap.Demo.Hosted/Server/Properties/launchSettings.json deleted file mode 100644 index 626120395..000000000 --- a/BlazorBootstrap.Demo.Hosted/Server/Properties/launchSettings.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "iisSettings": { - "windowsAuthentication": false, - "anonymousAuthentication": true, - "iisExpress": { - "applicationUrl": "http://localhost:7232", - "sslPort": 44372 - } - }, - "profiles": { - "BlazorBootstrap.Demo.Server": { - "commandName": "Project", - "dotnetRunMessages": true, - "launchBrowser": true, - "inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}", - "applicationUrl": "https://localhost:5021;http://localhost:5020", - "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development" - } - }, - "IIS Express": { - "commandName": "IISExpress", - "launchBrowser": true, - "inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}", - "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development" - } - } - } - } diff --git a/BlazorBootstrap.Demo.Hosted/Server/Using.cs b/BlazorBootstrap.Demo.Hosted/Server/Using.cs deleted file mode 100644 index 7c1cdc2e8..000000000 --- a/BlazorBootstrap.Demo.Hosted/Server/Using.cs +++ /dev/null @@ -1 +0,0 @@ -global using BlazorBootstrap.Demo.RCL; diff --git a/BlazorBootstrap.Demo.Hosted/Server/appsettings.Development.json b/BlazorBootstrap.Demo.Hosted/Server/appsettings.Development.json deleted file mode 100644 index 0c208ae91..000000000 --- a/BlazorBootstrap.Demo.Hosted/Server/appsettings.Development.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "Logging": { - "LogLevel": { - "Default": "Information", - "Microsoft.AspNetCore": "Warning" - } - } -} diff --git a/BlazorBootstrap.Demo.Hosted/Server/appsettings.json b/BlazorBootstrap.Demo.Hosted/Server/appsettings.json deleted file mode 100644 index 10f68b8c8..000000000 --- a/BlazorBootstrap.Demo.Hosted/Server/appsettings.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "Logging": { - "LogLevel": { - "Default": "Information", - "Microsoft.AspNetCore": "Warning" - } - }, - "AllowedHosts": "*" -} diff --git a/BlazorBootstrap.Demo.RCL/BlazorBootstrap.Demo.RCL.csproj b/BlazorBootstrap.Demo.RCL/BlazorBootstrap.Demo.RCL.csproj index 3a3a921dc..fee67b139 100644 --- a/BlazorBootstrap.Demo.RCL/BlazorBootstrap.Demo.RCL.csproj +++ b/BlazorBootstrap.Demo.RCL/BlazorBootstrap.Demo.RCL.csproj @@ -1,7 +1,7 @@  - net9.0 + net10.0 enable enable @@ -11,8 +11,9 @@ - - + + + diff --git a/BlazorBootstrap.Demo.RCL/Components/Layout/BlogMainLayout.razor b/BlazorBootstrap.Demo.RCL/Components/Layout/BlogMainLayout.razor new file mode 100644 index 000000000..63d63cb8f --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Layout/BlogMainLayout.razor @@ -0,0 +1,2 @@ +@namespace BlazorBootstrap.Demo.RCL +@inherits MainLayoutBase diff --git a/BlazorBootstrap.Demo.RCL/Components/Layout/BlogMainLayout.razor.cs b/BlazorBootstrap.Demo.RCL/Components/Layout/BlogMainLayout.razor.cs new file mode 100644 index 000000000..3cfc147ff --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Layout/BlogMainLayout.razor.cs @@ -0,0 +1,5 @@ +namespace BlazorBootstrap.Demo.RCL; + +public partial class BlogMainLayout : MainLayoutBase +{ +} diff --git a/BlazorBootstrap.Demo.RCL/Components/Layout/DemosMainLayout.razor b/BlazorBootstrap.Demo.RCL/Components/Layout/DemosMainLayout.razor new file mode 100644 index 000000000..160bec2c0 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Layout/DemosMainLayout.razor @@ -0,0 +1,97 @@ +@namespace BlazorBootstrap.Demo.RCL +@inherits MainLayoutBase + + + + + + + + + + + @Body + + + + + If you like Blazor Bootstrap, give it a star on GitHub! + + + + + + +
+
+ + Blazor Bootstrap + Blazor Bootstrap + +
    +
  • Designed and built with all the love in the world by the Blazor Bootstrap team with the help of our contributors.
  • +
  • Code licensed Apache License 2.0.
  • +
  • Currently @Version.
  • + @if (!string.IsNullOrWhiteSpace(DotNetVersion)) + { +
  • Powered by @DotNetVersion
  • + } +
+
+
+
Links
+ +
+ +
+
Community
+ +
+ +
+
+
+ + diff --git a/BlazorBootstrap.Demo.RCL/Components/Layout/DemosMainLayout.razor.cs b/BlazorBootstrap.Demo.RCL/Components/Layout/DemosMainLayout.razor.cs new file mode 100644 index 000000000..2121bed2b --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Layout/DemosMainLayout.razor.cs @@ -0,0 +1,119 @@ +namespace BlazorBootstrap.Demo.RCL; + +public partial class DemosMainLayout : MainLayoutBase +{ + internal override IEnumerable GetNavItems() + { + navItems ??= new List + { + new (){ Id = "1", Text = "Getting Started", Href = DemoRouteConstants.Demos_URL_GettingStarted, IconName = IconName.HouseDoorFill }, + + new (){ Id = "2", Text = "Layout", IconName = IconName.LayoutTextWindowReverse, IconColor = IconColor.Success }, + new (){ Id = "201", Text = "Blazor Server", Href = DemoRouteConstants.Demos_URL_Layout_Blazor_Server, IconName = IconName.Server, ParentId = "2" }, + new (){ Id = "200", Text = "Blazor WebAssembly", Href = DemoRouteConstants.Demos_URL_Layout_BlazorWebAssembly, IconName = IconName.BrowserEdge, ParentId = "2" }, + + new (){ Id = "3", Text = "Content", IconName = IconName.BodyText, IconColor = IconColor.Primary }, + new (){ Id = "300", Text = "Icons", Href = DemoRouteConstants.Demos_URL_Icons, IconName = IconName.PersonSquare, ParentId = "3" }, + new (){ Id = "301", Text = "Images", Href = DemoRouteConstants.Demos_URL_Images, IconName = IconName.Image, ParentId = "3" }, + + new (){ Id = "4", Text = "Forms", IconName = IconName.InputCursorText, IconColor = IconColor.Success }, + new (){ Id = "400", Text = "Auto Complete", Href = DemoRouteConstants.Demos_URL_AutoComplete, IconName = IconName.InputCursorText, ParentId = "4" }, + new (){ Id = "401", Text = "Checkbox Input", Href = DemoRouteConstants.Demos_URL_CheckboxInput, IconName = IconName.CheckSquareFill, ParentId = "4" }, + new (){ Id = "402", Text = "Currency Input", Href = DemoRouteConstants.Demos_URL_CurrencyInput, IconName = IconName.CurrencyDollar, ParentId = "4" }, + new (){ Id = "403", Text = "Date Input", Href = DemoRouteConstants.Demos_URL_DateInput, IconName = IconName.CalendarDate, ParentId = "4" }, + new (){ Id = "415", Text = "Drag and Drop File Input", Href = DemoRouteConstants.Demos_URL_DragAndDropFileInput, IconName = IconName.FileEarmarkArrowUp, ParentId = "4" }, + new (){ Id = "404", Text = "Enum Input", Href = DemoRouteConstants.Demos_URL_EnumInput, IconName = IconName.MenuButtonWideFill, ParentId = "4" }, + new (){ Id = "414", Text = "File Input", Href = DemoRouteConstants.Demos_URL_FileInput, IconName = IconName.FileEarmarkArrowUp, ParentId = "4" }, + new (){ Id = "405", Text = "Number Input", Href = DemoRouteConstants.Demos_URL_NumberInput, IconName = IconName.InputCursor, ParentId = "4" }, + new (){ Id = "406", Text = "OTP Input", Href = DemoRouteConstants.Demos_URL_OTPInput, IconName = IconName.Asterisk, ParentId = "4" }, + new (){ Id = "407", Text = "Password Input", Href = DemoRouteConstants.Demos_URL_PasswordInput, IconName = IconName.EyeSlashFill, ParentId = "4" }, + new (){ Id = "408", Text = "Radio Input", Href = DemoRouteConstants.Demos_URL_RadioInput, IconName = IconName.RecordCircle, ParentId = "4" }, + new (){ Id = "409", Text = "Range Input", Href = DemoRouteConstants.Demos_URL_RangeInput, IconName = IconName.Sliders, ParentId = "4" }, + //new (){ Id = "404", Text = "Select Input", Href = DemoRouteConstants.Demos_URL_SelectInput, IconName = IconName.MenuButtonWideFill, ParentId = "4" }, + new (){ Id = "416", Text = "RichTextEditor", Href = DemoRouteConstants.Demos_URL_RichTextEditor, IconName = IconName.Type, ParentId = "4" }, + new (){ Id = "410", Text = "Switch", Href = DemoRouteConstants.Demos_URL_Switch, IconName = IconName.ToggleOn, ParentId = "4" }, + new (){ Id = "412", Text = "Text Area Input", Href = DemoRouteConstants.Demos_URL_TextAreaInput, IconName = IconName.InputCursorText, ParentId = "4" }, + new (){ Id = "411", Text = "Text Input", Href = DemoRouteConstants.Demos_URL_TextInput, IconName = IconName.InputCursorText, ParentId = "4" }, + new (){ Id = "413", Text = "Time Input", Href = DemoRouteConstants.Demos_URL_TimeInput, IconName = IconName.ClockFill, ParentId = "4" }, + + new (){ Id = "5", Text = "Components", IconName = IconName.GearFill, IconColor = IconColor.Danger }, + new (){ Id = "500", Text = "Accordion", Href = DemoRouteConstants.Demos_URL_Accordion, IconName = IconName.ChevronBarExpand, ParentId = "5" }, + new (){ Id = "501", Text = "Alerts", Href = DemoRouteConstants.Demos_URL_Alerts, IconName = IconName.CheckCircleFill, ParentId = "5" }, + new (){ Id = "502", Text = "Badge", Href = DemoRouteConstants.Demos_URL_Badge, IconName = IconName.AppIndicator, ParentId = "5" }, + new (){ Id = "503", Text = "Breadcrumb", Href = DemoRouteConstants.Demos_URL_Breadcrumb, IconName = IconName.SegmentedNav, ParentId = "5" }, + new (){ Id = "504", Text = "Buttons", Href = DemoRouteConstants.Demos_URL_Buttons, IconName = IconName.ToggleOn, ParentId = "5" }, + new (){ Id = "505", Text = "Callout", Href = DemoRouteConstants.Demos_URL_Callout, IconName = IconName.StickyFill, ParentId = "5" }, + new (){ Id = "506", Text = "Card", Href = DemoRouteConstants.Demos_URL_Card, IconName = IconName.CardHeading, ParentId = "5" }, + new (){ Id = "507", Text = "Carousel", Href = DemoRouteConstants.Demos_URL_Carousel, IconName = IconName.CollectionPlayFill, ParentId = "5" }, + new (){ Id = "508", Text = "Charts", Href = DemoRouteConstants.Demos_URL_Charts, IconName = IconName.BarChartLineFill, ParentId = "5", Match = NavLinkMatch.All }, + new (){ Id = "509", Text = "Collapse", Href = DemoRouteConstants.Demos_URL_Collapse, IconName = IconName.ArrowsCollapse, ParentId = "5" }, + new (){ Id = "510", Text = "Confirm Dialog", Href = DemoRouteConstants.Demos_URL_ConfirmDialog, IconName = IconName.QuestionDiamondFill, ParentId = "5" }, + new (){ Id = "511", Text = "Dropdown", Href = DemoRouteConstants.Demos_URL_Dropdown, IconName = IconName.MenuButtonWideFill, ParentId = "5" }, + new (){ Id = "512", Text = "Google Map", Href = DemoRouteConstants.Demos_URL_GoogleMap, IconName = IconName.Map, ParentId = "5" }, + + #region Grid + + new (){ Id = "513", Text = "Grid", IconName = IconName.Grid, ParentId = "5" }, + new (){ Id = "51301", Text = "Overview", Href = DemoRouteConstants.Demos_URL_Grid_Overview, IconName = IconName.Grid, ParentId = "513" }, // first item - do not change + new (){ Id = "51302", Text = "Alignment", Href = DemoRouteConstants.Demos_URL_Grid_Alignment, IconName = IconName.Justify, ParentId = "513" }, + new (){ Id = "51303", Text = "Custom CSS Class", Href = DemoRouteConstants.Demos_URL_Grid_CustomCSSClass, IconName = IconName.FileTypeCss, ParentId = "513" }, + new (){ Id = "51304", Text = "Data Binding", Href = DemoRouteConstants.Demos_URL_Grid_DataBinding, IconName = IconName.GridFill, ParentId = "513" }, + new (){ Id = "51306", Text = "Detail View", Href = DemoRouteConstants.Demos_URL_Grid_DetailView, IconName = IconName.ListNested, ParentId = "513" }, + new (){ Id = "51307", Text = "Events", Href = DemoRouteConstants.Demos_URL_Grid_Events, IconName = IconName.LightningChargeFill, ParentId = "513" }, + new (){ Id = "51317", Text = "Filters", Href = DemoRouteConstants.Demos_URL_Grid_Filters, IconName = IconName.FunnelFill, ParentId = "513" }, + new (){ Id = "51308", Text = "Fixed Header", Href = DemoRouteConstants.Demos_URL_Grid_FixedHeader, IconName = IconName.Table, ParentId = "513" }, + new (){ Id = "51309", Text = "Freeze Columns", Href = DemoRouteConstants.Demos_URL_Grid_FreezeColumns, IconName = IconName.LayoutThreeColumns, ParentId = "513" }, + new (){ Id = "51310", Text = "Grid Settings", Href = DemoRouteConstants.Demos_URL_Grid_Settings, IconName = IconName.GearFill, ParentId = "513" }, + new (){ Id = "51311", Text = "Nested Grid", Href = DemoRouteConstants.Demos_URL_Grid_NestedGrid, IconName = IconName.Pip, ParentId = "513" }, + new (){ Id = "51312", Text = "Paging", Href = DemoRouteConstants.Demos_URL_Grid_Paging, IconName = IconName.ChevronBarRight, ParentId = "513" }, + new (){ Id = "51313", Text = "Selection", Href = DemoRouteConstants.Demos_URL_Grid_Selection, IconName = IconName.CheckSquareFill, ParentId = "513" }, + new (){ Id = "51314", Text = "Sorting", Href = DemoRouteConstants.Demos_URL_Grid_Sorting, IconName = IconName.ArrowDownUp, ParentId = "513" }, + new (){ Id = "51315", Text = "Summary", Href = DemoRouteConstants.Demos_URL_Grid_Summary, IconName = IconName.Calculator, ParentId = "513" }, + new (){ Id = "51316", Text = "Translations", Href = DemoRouteConstants.Demos_URL_Grid_Translations, IconName = IconName.Translate, ParentId = "513" }, + new (){ Id = "51399", Text = "Other", Href = DemoRouteConstants.Demos_URL_Grid_OtherExamples, IconName = IconName.PlusSquareFill, ParentId = "513" }, // last item - do not change + + #endregion Grid + + new (){ Id = "514", Text = "Markdown", Href = DemoRouteConstants.Demos_URL_Markdown, IconName = IconName.MarkdownFill, ParentId = "5" }, + new (){ Id = "5145", Text = "Modals", Href = DemoRouteConstants.Demos_URL_Modal, IconName = IconName.WindowStack, ParentId = "5" }, + new (){ Id = "515", Text = "Offcanvas", Href = DemoRouteConstants.Demos_URL_Offcanvas, IconName = IconName.LayoutSidebarReverse, ParentId = "5" }, + new (){ Id = "516", Text = "Pagination", Href = DemoRouteConstants.Demos_URL_Pagination, IconName = IconName.ThreeDots, ParentId = "5" }, + new (){ Id = "517", Text = "PDF Viewer", Href = DemoRouteConstants.Demos_URL_PDFViewer, IconName = IconName.FilePdfFill, ParentId = "5" }, + new (){ Id = "518", Text = "Placeholders", Href = DemoRouteConstants.Demos_URL_Placeholders, IconName = IconName.ColumnsGap, ParentId = "5" }, + new (){ Id = "519", Text = "Preload", Href = DemoRouteConstants.Demos_URL_Preload, IconName = IconName.ArrowClockwise, ParentId = "5" }, + new (){ Id = "520", Text = "Progress", Href = DemoRouteConstants.Demos_URL_Progress, IconName = IconName.UsbC, ParentId = "5" }, + new (){ Id = "521", Text = "Ribbon", Href = DemoRouteConstants.Demos_URL_Ribbon, IconName = IconName.WindowStack, ParentId = "5" }, + new (){ Id = "522", Text = "Script Loader", Href = DemoRouteConstants.Demos_URL_ScriptLoader, IconName = IconName.CodeSlash, ParentId = "5" }, + new (){ Id = "523", Text = "Sidebar", Href = DemoRouteConstants.Demos_URL_Sidebar, IconName = IconName.LayoutSidebar, ParentId = "5" }, + new (){ Id = "524", Text = "Sidebar 2", Href = DemoRouteConstants.Demos_URL_Sidebar2, IconName = IconName.ListNested, ParentId = "5" }, + new (){ Id = "525", Text = "Sortable List", Href = DemoRouteConstants.Demos_URL_SortableList, IconName = IconName.ArrowsMove, ParentId = "5" }, + new (){ Id = "526", Text = "Spinner", Href = DemoRouteConstants.Demos_URL_Spinners, IconName = IconName.ArrowRepeat, ParentId = "5" }, + new (){ Id = "5245", Text = "Split View", Href = DemoRouteConstants.Demos_URL_SplitView, IconName = IconName.LayoutSplit, ParentId = "5" }, + new (){ Id = "527", Text = "Tabs", Href = DemoRouteConstants.Demos_URL_Tabs, IconName = IconName.WindowPlus, ParentId = "5" }, + new (){ Id = "528", Text = "Theme Switcher", Href = DemoRouteConstants.Demos_URL_ThemeSwitcher, IconName = IconName.NintendoSwitch, ParentId = "5" }, + new (){ Id = "529", Text = "Toasts", Href = DemoRouteConstants.Demos_URL_Toasts, IconName = IconName.ExclamationTriangleFill, ParentId = "5" }, + new (){ Id = "530", Text = "Tooltips", Href = DemoRouteConstants.Demos_URL_Tooltips, IconName = IconName.ChatSquareDotsFill, ParentId = "5" }, + + new (){ Id = "6", Text = "Data Visualization", IconName = IconName.BarChartFill, IconColor = IconColor.Warning }, + new (){ Id = "600", Text = "Bar Chart", Href = DemoRouteConstants.Demos_URL_BarChart, IconName = IconName.BarChartFill, ParentId = "6", Match = NavLinkMatch.All }, + new (){ Id = "601", Text = "Bubble Chart", Href = DemoRouteConstants.Demos_URL_BubbleChart, IconName = IconName.CircleFill, ParentId = "6", Match = NavLinkMatch.All }, + new (){ Id = "602", Text = "Doughnut Chart", Href = DemoRouteConstants.Demos_URL_DoughnutChart, IconName = IconName.CircleFill, ParentId = "6", Match = NavLinkMatch.All }, + new (){ Id = "603", Text = "Line Chart", Href = DemoRouteConstants.Demos_URL_LineChart, IconName = IconName.GraphUp, ParentId = "6", Match = NavLinkMatch.All }, + new (){ Id = "604", Text = "Pie Chart", Href = DemoRouteConstants.Demos_URL_PieChart, IconName = IconName.PieChartFill, ParentId = "6", Match = NavLinkMatch.All }, + new (){ Id = "605", Text = "Polar Area Chart", Href = DemoRouteConstants.Demos_URL_PolarAreaChart, IconName = IconName.PieChartFill, ParentId = "6", Match = NavLinkMatch.All }, + new (){ Id = "606", Text = "Radar Chart", Href = DemoRouteConstants.Demos_URL_RadarChart, IconName = IconName.Radar, ParentId = "6", Match = NavLinkMatch.All }, + new (){ Id = "607", Text = "Scatter Chart", Href = DemoRouteConstants.Demos_URL_ScatterChart, IconName = IconName.GraphUpArrow, ParentId = "6", Match = NavLinkMatch.All }, + + new(){ Id = "7", Text = "Services", IconName = IconName.WrenchAdjustableCircleFill, IconColor = IconColor.Success }, + new (){ Id = "700", Text = "Breadcrumb Service", Href = DemoRouteConstants.Demos_URL_BreadcrumbService, IconName = IconName.SegmentedNav, ParentId = "7" }, + new (){ Id = "701", Text = "Modal Service", Href = DemoRouteConstants.Demos_URL_ModalService, IconName = IconName.WindowStack, ParentId = "7" }, + new (){ Id = "702", Text = "Preload Service", Href = DemoRouteConstants.Demos_URL_PreloadService, IconName = IconName.ArrowRepeat, ParentId = "7" }, + new (){ Id = "703", Text = "Toast Service", Href = DemoRouteConstants.Demos_URL_ToastService, IconName = IconName.InfoCircleFill, ParentId = "7" }, + + new(){ Id = "19", Text = "Utilities", IconName = IconName.GearWideConnected, IconColor = IconColor.Info }, + new (){ Id = "1900", Text = "Color Utility", Href = DemoRouteConstants.Demos_URL_ColorUtils, IconName = IconName.Palette2, ParentId = "19" }, + }; + + return navItems; + } +} diff --git a/BlazorBootstrap.Demo.RCL/Components/Layout/DocsMainLayout.razor b/BlazorBootstrap.Demo.RCL/Components/Layout/DocsMainLayout.razor new file mode 100644 index 000000000..160bec2c0 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Layout/DocsMainLayout.razor @@ -0,0 +1,97 @@ +@namespace BlazorBootstrap.Demo.RCL +@inherits MainLayoutBase + + + + + + + + + + + @Body + + + + + If you like Blazor Bootstrap, give it a star on GitHub! + + + + + + +
+
+ + Blazor Bootstrap + Blazor Bootstrap + +
    +
  • Designed and built with all the love in the world by the Blazor Bootstrap team with the help of our contributors.
  • +
  • Code licensed Apache License 2.0.
  • +
  • Currently @Version.
  • + @if (!string.IsNullOrWhiteSpace(DotNetVersion)) + { +
  • Powered by @DotNetVersion
  • + } +
+
+
+
Links
+ +
+ +
+
Community
+ +
+ +
+
+
+ + diff --git a/BlazorBootstrap.Demo.RCL/Components/Layout/DocsMainLayout.razor.cs b/BlazorBootstrap.Demo.RCL/Components/Layout/DocsMainLayout.razor.cs new file mode 100644 index 000000000..5efd1fb9f --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Layout/DocsMainLayout.razor.cs @@ -0,0 +1,84 @@ +namespace BlazorBootstrap.Demo.RCL; + +public partial class DocsMainLayout : MainLayoutBase +{ + internal override IEnumerable GetNavItems() + { + navItems ??= new List + { + new (){ Id = "1", Text = "Getting Started", Href = DemoRouteConstants.Docs_URL_GettingStarted, IconName = IconName.HouseDoorFill }, + + new (){ Id = "2", Text = "Layout", IconName = IconName.LayoutTextWindowReverse, IconColor = IconColor.Success }, + new (){ Id = "200", Text = "Blazor Bootstrap Layout", Href = DemoRouteConstants.Docs_URL_Layout, IconName = IconName.BrowserEdge, ParentId = "2" }, + + new (){ Id = "3", Text = "Content", IconName = IconName.BodyText, IconColor = IconColor.Primary }, + new (){ Id = "300", Text = "Icons", Href = DemoRouteConstants.Docs_URL_Icons, IconName = IconName.PersonSquare, ParentId = "3" }, + new (){ Id = "301", Text = "Images", Href = DemoRouteConstants.Docs_URL_Images, IconName = IconName.Image, ParentId = "3" }, + + new (){ Id = "4", Text = "Forms", IconName = IconName.InputCursorText, IconColor = IconColor.Success }, + new (){ Id = "400", Text = "Auto Complete", Href = DemoRouteConstants.Docs_URL_AutoComplete, IconName = IconName.InputCursorText, ParentId = "4" }, + new (){ Id = "401", Text = "Checkbox Input", Href = DemoRouteConstants.Docs_URL_CheckboxInput, IconName = IconName.CheckSquareFill, ParentId = "4" }, + new (){ Id = "402", Text = "Currency Input", Href = DemoRouteConstants.Docs_URL_CurrencyInput, IconName = IconName.CurrencyDollar, ParentId = "4" }, + new (){ Id = "403", Text = "Date Input", Href = DemoRouteConstants.Docs_URL_DateInput, IconName = IconName.CalendarDate, ParentId = "4" }, + new (){ Id = "415", Text = "Drag and Drop File Input", Href = DemoRouteConstants.Docs_URL_DragAndDropFileInput, IconName = IconName.FileEarmarkArrowUp, ParentId = "4" }, + new (){ Id = "404", Text = "Enum Input", Href = DemoRouteConstants.Docs_URL_EnumInput, IconName = IconName.MenuButtonWideFill, ParentId = "4" }, + new (){ Id = "414", Text = "File Input", Href = DemoRouteConstants.Docs_URL_FileInput, IconName = IconName.FileEarmarkArrowUp, ParentId = "4" }, + new (){ Id = "405", Text = "Number Input", Href = DemoRouteConstants.Docs_URL_NumberInput, IconName = IconName.InputCursor, ParentId = "4" }, + new (){ Id = "406", Text = "OTP Input", Href = DemoRouteConstants.Docs_URL_OTPInput, IconName = IconName.Asterisk, ParentId = "4" }, + new (){ Id = "407", Text = "Password Input", Href = DemoRouteConstants.Docs_URL_PasswordInput, IconName = IconName.EyeSlashFill, ParentId = "4" }, + new (){ Id = "408", Text = "Radio Input", Href = DemoRouteConstants.Docs_URL_RadioInput, IconName = IconName.RecordCircle, ParentId = "4" }, + new (){ Id = "409", Text = "Range Input", Href = DemoRouteConstants.Docs_URL_RangeInput, IconName = IconName.Sliders, ParentId = "4" }, + //new (){ Id = "404", Text = "Select Input", Href = DemoRouteConstants.Docs_URL_SelectInput, IconName = IconName.MenuButtonWideFill, ParentId = "4" }, + new (){ Id = "416", Text = "RichTextEditor", Href = DemoRouteConstants.Docs_URL_RichTextEditor, IconName = IconName.Type, ParentId = "4" }, + new (){ Id = "410", Text = "Switch", Href = DemoRouteConstants.Docs_URL_Switch, IconName = IconName.ToggleOn, ParentId = "4" }, + new (){ Id = "412", Text = "Text Area Input", Href = DemoRouteConstants.Docs_URL_TextAreaInput, IconName = IconName.InputCursorText, ParentId = "4" }, + new (){ Id = "411", Text = "Text Input", Href = DemoRouteConstants.Docs_URL_TextInput, IconName = IconName.InputCursorText, ParentId = "4" }, + new (){ Id = "413", Text = "Time Input", Href = DemoRouteConstants.Docs_URL_TimeInput, IconName = IconName.ClockFill, ParentId = "4" }, + + new (){ Id = "5", Text = "Components", IconName = IconName.GearFill, IconColor = IconColor.Danger }, + new (){ Id = "500", Text = "Accordion", Href = DemoRouteConstants.Docs_URL_Accordion, IconName = IconName.ChevronBarExpand, ParentId = "5" }, + new (){ Id = "501", Text = "Alerts", Href = DemoRouteConstants.Docs_URL_Alerts, IconName = IconName.CheckCircleFill, ParentId = "5" }, + new (){ Id = "502", Text = "Badge", Href = DemoRouteConstants.Docs_URL_Badge, IconName = IconName.AppIndicator, ParentId = "5" }, + new (){ Id = "503", Text = "Breadcrumb", Href = DemoRouteConstants.Docs_URL_Breadcrumb, IconName = IconName.SegmentedNav, ParentId = "5" }, + new (){ Id = "504", Text = "Buttons", Href = DemoRouteConstants.Docs_URL_Buttons, IconName = IconName.ToggleOn, ParentId = "5" }, + new (){ Id = "505", Text = "Callout", Href = DemoRouteConstants.Docs_URL_Callout, IconName = IconName.StickyFill, ParentId = "5" }, + new (){ Id = "506", Text = "Card", Href = DemoRouteConstants.Docs_URL_Card, IconName = IconName.CardHeading, ParentId = "5" }, + new (){ Id = "507", Text = "Carousel", Href = DemoRouteConstants.Docs_URL_Carousel, IconName = IconName.CollectionPlayFill, ParentId = "5" }, + new (){ Id = "509", Text = "Collapse", Href = DemoRouteConstants.Docs_URL_Collapse, IconName = IconName.ArrowsCollapse, ParentId = "5" }, + new (){ Id = "510", Text = "Confirm Dialog", Href = DemoRouteConstants.Docs_URL_ConfirmDialog, IconName = IconName.QuestionDiamondFill, ParentId = "5" }, + new (){ Id = "511", Text = "Dropdown", Href = DemoRouteConstants.Docs_URL_Dropdown, IconName = IconName.MenuButtonWideFill, ParentId = "5" }, + new (){ Id = "512", Text = "Google Map", Href = DemoRouteConstants.Docs_URL_GoogleMap, IconName = IconName.Map, ParentId = "5" }, + new (){ Id = "513", Text = "Grid", Href = DemoRouteConstants.Docs_URL_Grid, IconName = IconName.Grid, ParentId = "5" }, + new (){ Id = "514", Text = "Markdown", Href = DemoRouteConstants.Docs_URL_Markdown, IconName = IconName.MarkdownFill, ParentId = "5" }, + new (){ Id = "5145", Text = "Modals", Href = DemoRouteConstants.Docs_URL_Modal, IconName = IconName.WindowStack, ParentId = "5" }, + new (){ Id = "515", Text = "Offcanvas", Href = DemoRouteConstants.Docs_URL_Offcanvas, IconName = IconName.LayoutSidebarReverse, ParentId = "5" }, + new (){ Id = "516", Text = "Pagination", Href = DemoRouteConstants.Docs_URL_Pagination, IconName = IconName.ThreeDots, ParentId = "5" }, + new (){ Id = "517", Text = "PDF Viewer", Href = DemoRouteConstants.Docs_URL_PDFViewer, IconName = IconName.FilePdfFill, ParentId = "5" }, + new (){ Id = "518", Text = "Placeholders", Href = DemoRouteConstants.Docs_URL_Placeholders, IconName = IconName.ColumnsGap, ParentId = "5" }, + new (){ Id = "519", Text = "Preload", Href = DemoRouteConstants.Docs_URL_Preload, IconName = IconName.ArrowClockwise, ParentId = "5" }, + new (){ Id = "520", Text = "Progress", Href = DemoRouteConstants.Docs_URL_Progress, IconName = IconName.UsbC, ParentId = "5" }, + new (){ Id = "521", Text = "Ribbon", Href = DemoRouteConstants.Docs_URL_Ribbon, IconName = IconName.WindowStack, ParentId = "5" }, + new (){ Id = "522", Text = "Script Loader", Href = DemoRouteConstants.Docs_URL_ScriptLoader, IconName = IconName.CodeSlash, ParentId = "5" }, + new (){ Id = "523", Text = "Sidebar", Href = DemoRouteConstants.Docs_URL_Sidebar, IconName = IconName.LayoutSidebar, ParentId = "5" }, + new (){ Id = "524", Text = "Sidebar 2", Href = DemoRouteConstants.Docs_URL_Sidebar2, IconName = IconName.ListNested, ParentId = "5" }, + new (){ Id = "525", Text = "Sortable List", Href = DemoRouteConstants.Docs_URL_SortableList, IconName = IconName.ArrowsMove, ParentId = "5" }, + new (){ Id = "526", Text = "Spinner", Href = DemoRouteConstants.Docs_URL_Spinners, IconName = IconName.ArrowRepeat, ParentId = "5" }, + new (){ Id = "5245", Text = "Split View", Href = DemoRouteConstants.Docs_URL_SplitView, IconName = IconName.LayoutSplit, ParentId = "5" }, + new (){ Id = "527", Text = "Tabs", Href = DemoRouteConstants.Docs_URL_Tabs, IconName = IconName.WindowPlus, ParentId = "5" }, + new (){ Id = "528", Text = "Theme Switcher", Href = DemoRouteConstants.Docs_URL_ThemeSwitcher, IconName = IconName.NintendoSwitch, ParentId = "5" }, + new (){ Id = "529", Text = "Toasts", Href = DemoRouteConstants.Docs_URL_Toasts, IconName = IconName.ExclamationTriangleFill, ParentId = "5" }, + new (){ Id = "530", Text = "Tooltips", Href = DemoRouteConstants.Docs_URL_Tooltips, IconName = IconName.ChatSquareDotsFill, ParentId = "5" }, + + new(){ Id = "7", Text = "Services", IconName = IconName.WrenchAdjustableCircleFill, IconColor = IconColor.Success }, + new (){ Id = "700", Text = "Breadcrumb Service", Href = DemoRouteConstants.Docs_URL_BreadcrumbService, IconName = IconName.SegmentedNav, ParentId = "7" }, + new (){ Id = "701", Text = "Modal Service", Href = DemoRouteConstants.Docs_URL_ModalService, IconName = IconName.WindowStack, ParentId = "7" }, + new (){ Id = "702", Text = "Preload Service", Href = DemoRouteConstants.Docs_URL_PreloadService, IconName = IconName.ArrowRepeat, ParentId = "7" }, + new (){ Id = "703", Text = "Toast Service", Href = DemoRouteConstants.Docs_URL_ToastService, IconName = IconName.InfoCircleFill, ParentId = "7" }, + + //new(){ Id = "19", Text = "Utilities", IconName = IconName.GearWideConnected, IconColor = IconColor.Info }, + //new (){ Id = "1900", Text = "Color Utility", Href = DemoRouteConstants.Docs_URL_ColorUtils, IconName = IconName.Palette2, ParentId = "19" }, + }; + + return navItems; + } +} diff --git a/BlazorBootstrap.Demo.RCL/Components/Layout/EmptyLayout.razor b/BlazorBootstrap.Demo.RCL/Components/Layout/EmptyLayout.razor index 3167f32d0..769a47ffd 100644 --- a/BlazorBootstrap.Demo.RCL/Components/Layout/EmptyLayout.razor +++ b/BlazorBootstrap.Demo.RCL/Components/Layout/EmptyLayout.razor @@ -31,7 +31,7 @@
@@ -82,6 +82,7 @@ -
- - - -
-
- - - -
-
- - - -
-
- - - -
-
-
-
- - - +
-
+
Links
@@ -96,7 +69,26 @@
  • Stack Overflow
  • -
    +
    diff --git a/BlazorBootstrap.Demo.RCL/Components/Layout/MainLayout.razor.cs b/BlazorBootstrap.Demo.RCL/Components/Layout/MainLayout.razor.cs index e076eb178..603f63583 100644 --- a/BlazorBootstrap.Demo.RCL/Components/Layout/MainLayout.razor.cs +++ b/BlazorBootstrap.Demo.RCL/Components/Layout/MainLayout.razor.cs @@ -1,4 +1,4 @@ -namespace BlazorBootstrap.Demo.RCL; +namespace BlazorBootstrap.Demo.RCL; public partial class MainLayout : MainLayoutBase { @@ -6,100 +6,110 @@ internal override IEnumerable GetNavItems() { navItems ??= new List { - new (){ Id = "1", Text = "Getting Started", Href = "/getting-started", IconName = IconName.HouseDoorFill }, + new (){ Id = "1", Text = "Getting Started", Href = DemoRouteConstants.Demos_URL_GettingStarted, IconName = IconName.HouseDoorFill }, new (){ Id = "2", Text = "Layout", IconName = IconName.LayoutTextWindowReverse, IconColor = IconColor.Success }, - new (){ Id = "200", Text = "Blazor WebAssembly", Href = "/layout-setup/blazor-webassembly", IconName = IconName.BrowserEdge, ParentId = "2" }, - new (){ Id = "201", Text = "Blazor Server", Href = "/layout-setup/blazor-server", IconName = IconName.Server, ParentId = "2" }, + new (){ Id = "200", Text = "Blazor WebAssembly", Href = DemoRouteConstants.Demos_URL_Layout_BlazorWebAssembly, IconName = IconName.BrowserEdge, ParentId = "2" }, + new (){ Id = "201", Text = "Blazor Server", Href = DemoRouteConstants.Demos_URL_Layout_Blazor_Server, IconName = IconName.Server, ParentId = "2" }, new (){ Id = "3", Text = "Content", IconName = IconName.BodyText, IconColor = IconColor.Primary }, - new (){ Id = "300", Text = "Icons", Href = "/icons", IconName = IconName.PersonSquare, ParentId = "3" }, - new (){ Id = "301", Text = "Images", Href = "/images", IconName = IconName.Image, ParentId = "3" }, + new (){ Id = "300", Text = "Icons", Href = DemoRouteConstants.Demos_URL_Icons, IconName = IconName.PersonSquare, ParentId = "3" }, + new (){ Id = "301", Text = "Images", Href = DemoRouteConstants.Demos_URL_Images, IconName = IconName.Image, ParentId = "3" }, new (){ Id = "4", Text = "Forms", IconName = IconName.InputCursorText, IconColor = IconColor.Success }, - new (){ Id = "400", Text = "Auto Complete", Href = "/form/autocomplete", IconName = IconName.InputCursorText, ParentId = "4" }, - new (){ Id = "401", Text = "Currency Input", Href = "/form/currency-input", IconName = IconName.CurrencyDollar, ParentId = "4" }, - new (){ Id = "402", Text = "Date Input", Href = "/form/date-input", IconName = IconName.CalendarDate, ParentId = "4" }, - new (){ Id = "403", Text = "Number Input", Href = "/form/number-input", IconName = IconName.InputCursor, ParentId = "4" }, - new (){ Id = "404", Text = "Range Input", Href = "/form/range-input", IconName = IconName.Sliders, ParentId = "4" }, - new (){ Id = "405", Text = "Switch", Href = "/form/switch", IconName = IconName.ToggleOn, ParentId = "4" }, - new (){ Id = "406", Text = "Time Input", Href = "/form/time-input", IconName = IconName.ClockFill, ParentId = "4" }, + new (){ Id = "400", Text = "Auto Complete", Href = DemoRouteConstants.Demos_URL_AutoComplete, IconName = IconName.InputCursorText, ParentId = "4" }, + new (){ Id = "401", Text = "Checkbox Input", Href = DemoRouteConstants.Demos_URL_CheckboxInput, IconName = IconName.CheckSquareFill, ParentId = "4" }, + new (){ Id = "402", Text = "Currency Input", Href = DemoRouteConstants.Demos_URL_CurrencyInput, IconName = IconName.CurrencyDollar, ParentId = "4" }, + new (){ Id = "403", Text = "Date Input", Href = DemoRouteConstants.Demos_URL_DateInput, IconName = IconName.CalendarDate, ParentId = "4" }, + new (){ Id = "404", Text = "Enum Input", Href = DemoRouteConstants.Demos_URL_EnumInput, IconName = IconName.MenuButtonWideFill, ParentId = "4" }, + new (){ Id = "413", Text = "File Input", Href = DemoRouteConstants.Demos_URL_FileInput, IconName = IconName.FileEarmarkArrowUp, ParentId = "4" }, + new (){ Id = "414", Text = "Drag and Drop File Input", Href = DemoRouteConstants.Demos_URL_DragAndDropFileInput, IconName = IconName.FileEarmarkArrowUp, ParentId = "4" }, + new (){ Id = "405", Text = "Number Input", Href = DemoRouteConstants.Demos_URL_NumberInput, IconName = IconName.InputCursor, ParentId = "4" }, + new (){ Id = "406", Text = "Password Input", Href = DemoRouteConstants.Demos_URL_PasswordInput, IconName = IconName.EyeSlashFill, ParentId = "4" }, + new (){ Id = "407", Text = "Radio Input", Href = DemoRouteConstants.Demos_URL_RadioInput, IconName = IconName.RecordCircle, ParentId = "4" }, + new (){ Id = "408", Text = "Range Input", Href = DemoRouteConstants.Demos_URL_RangeInput, IconName = IconName.Sliders, ParentId = "4" }, + //new (){ Id = "404", Text = "Select Input", Href = DemoRouteConstants.Demos_URL_SelectInput, IconName = IconName.MenuButtonWideFill, ParentId = "4" }, + new (){ Id = "409", Text = "Switch", Href = DemoRouteConstants.Demos_URL_Switch, IconName = IconName.ToggleOn, ParentId = "4" }, + new (){ Id = "410", Text = "Text Input", Href = DemoRouteConstants.Demos_URL_TextInput, IconName = IconName.InputCursorText, ParentId = "4" }, + new (){ Id = "411", Text = "Text Area Input", Href = DemoRouteConstants.Demos_URL_TextAreaInput, IconName = IconName.InputCursorText, ParentId = "4" }, + new (){ Id = "412", Text = "Time Input", Href = DemoRouteConstants.Demos_URL_TimeInput, IconName = IconName.ClockFill, ParentId = "4" }, + new (){ Id = "415", Text = "RichTextEditor", Href = DemoRouteConstants.Demos_URL_RichTextEditor, IconName = IconName.Type, ParentId = "4" }, new (){ Id = "5", Text = "Components", IconName = IconName.GearFill, IconColor = IconColor.Danger }, - new (){ Id = "500", Text = "Accordion", Href = "/accordion", IconName = IconName.ChevronBarExpand, ParentId = "5" }, - new (){ Id = "501", Text = "Alerts", Href = "/alerts", IconName = IconName.CheckCircleFill, ParentId = "5" }, - new (){ Id = "502", Text = "Badge", Href = "/badge", IconName = IconName.AppIndicator, ParentId = "5" }, - new (){ Id = "503", Text = "Breadcrumb", Href = "/breadcrumb", IconName = IconName.SegmentedNav, ParentId = "5" }, - new (){ Id = "504", Text = "Buttons", Href = "/buttons", IconName = IconName.ToggleOn, ParentId = "5" }, - new (){ Id = "505", Text = "Callout", Href = "/callout", IconName = IconName.StickyFill, ParentId = "5" }, - new (){ Id = "506", Text = "Card", Href = "/card", IconName = IconName.CardHeading, ParentId = "5" }, - new (){ Id = "507", Text = "Carousel", Href = "/carousel", IconName = IconName.CollectionPlayFill, ParentId = "5" }, - new (){ Id = "508", Text = "Charts", Href = "/charts", IconName = IconName.BarChartLineFill, ParentId = "5", Match = NavLinkMatch.All }, - new (){ Id = "509", Text = "Collapse", Href = "/collapse", IconName = IconName.ArrowsCollapse, ParentId = "5" }, - new (){ Id = "510", Text = "Confirm Dialog", Href = "/confirm-dialog", IconName = IconName.QuestionDiamondFill, ParentId = "5" }, - new (){ Id = "511", Text = "Dropdown", Href = "/dropdown", IconName = IconName.MenuButtonWideFill, ParentId = "5" }, - new (){ Id = "512", Text = "Google Map", Href = "/google-map", IconName = IconName.Map, ParentId = "5" }, + new (){ Id = "500", Text = "Accordion", Href = DemoRouteConstants.Demos_URL_Accordion, IconName = IconName.ChevronBarExpand, ParentId = "5" }, + new (){ Id = "501", Text = "Alerts", Href = DemoRouteConstants.Demos_URL_Alerts, IconName = IconName.CheckCircleFill, ParentId = "5" }, + new (){ Id = "502", Text = "Badge", Href = DemoRouteConstants.Demos_URL_Badge, IconName = IconName.AppIndicator, ParentId = "5" }, + new (){ Id = "503", Text = "Breadcrumb", Href = DemoRouteConstants.Demos_URL_Breadcrumb, IconName = IconName.SegmentedNav, ParentId = "5" }, + new (){ Id = "504", Text = "Buttons", Href = DemoRouteConstants.Demos_URL_Buttons, IconName = IconName.ToggleOn, ParentId = "5" }, + new (){ Id = "505", Text = "Callout", Href = DemoRouteConstants.Demos_URL_Callout, IconName = IconName.StickyFill, ParentId = "5" }, + new (){ Id = "506", Text = "Card", Href = DemoRouteConstants.Demos_URL_Card, IconName = IconName.CardHeading, ParentId = "5" }, + new (){ Id = "507", Text = "Carousel", Href = DemoRouteConstants.Demos_URL_Carousel, IconName = IconName.CollectionPlayFill, ParentId = "5" }, + new (){ Id = "508", Text = "Charts", Href = DemoRouteConstants.Demos_URL_Charts, IconName = IconName.BarChartLineFill, ParentId = "5", Match = NavLinkMatch.All }, + new (){ Id = "509", Text = "Collapse", Href = DemoRouteConstants.Demos_URL_Collapse, IconName = IconName.ArrowsCollapse, ParentId = "5" }, + new (){ Id = "510", Text = "Confirm Dialog", Href = DemoRouteConstants.Demos_URL_ConfirmDialog, IconName = IconName.QuestionDiamondFill, ParentId = "5" }, + new (){ Id = "511", Text = "Dropdown", Href = DemoRouteConstants.Demos_URL_Dropdown, IconName = IconName.MenuButtonWideFill, ParentId = "5" }, + new (){ Id = "512", Text = "Google Map", Href = DemoRouteConstants.Demos_URL_GoogleMap, IconName = IconName.Map, ParentId = "5" }, #region Grid - new (){ Id = "513", Text = "Grid", IconName = IconName.Grid, ParentId = "5" }, - new (){ Id = "51101", Text = "Overview", Href = "/grid/overview", IconName = IconName.Grid, ParentId = "513" }, // first item - do not change - new (){ Id = "51102", Text = "Alignment", Href = "/grid/alignment", IconName = IconName.Justify, ParentId = "513" }, - new (){ Id = "51103", Text = "Custom CSS Class", Href = "/grid/custom-css-class", IconName = IconName.FileTypeCss, ParentId = "513" }, - new (){ Id = "51104", Text = "Data Binding", Href = "/grid/data-binding", IconName = IconName.GridFill, ParentId = "513" }, - new (){ Id = "51106", Text = "Detail View", Href = "/grid/detail-view", IconName = IconName.ListNested, ParentId = "513" }, - new (){ Id = "51107", Text = "Events", Href = "/grid/events", IconName = IconName.LightningChargeFill, ParentId = "513" }, - new (){ Id = "51107", Text = "Filters", Href = "/grid/filters", IconName = IconName.FunnelFill, ParentId = "513" }, - new (){ Id = "51108", Text = "Fixed Header", Href = "/grid/fixed-header", IconName = IconName.Table, ParentId = "513" }, - new (){ Id = "51109", Text = "Freeze Columns", Href = "/grid/freeze-columns", IconName = IconName.LayoutThreeColumns, ParentId = "513" }, - new (){ Id = "51110", Text = "Grid Settings", Href = "/grid/settings", IconName = IconName.GearFill, ParentId = "513" }, - new (){ Id = "51111", Text = "Nested Grid", Href = "/grid/nested-grid", IconName = IconName.Pip, ParentId = "513" }, - new (){ Id = "51112", Text = "Paging", Href = "/grid/paging", IconName = IconName.ChevronBarRight, ParentId = "513" }, - new (){ Id = "51113", Text = "Selection", Href = "/grid/selection", IconName = IconName.CheckSquareFill, ParentId = "513" }, - new (){ Id = "51114", Text = "Sorting", Href = "/grid/sorting", IconName = IconName.ArrowDownUp, ParentId = "513" }, - new (){ Id = "51115", Text = "Translations", Href = "/grid/translations", IconName = IconName.Translate, ParentId = "513" }, - new (){ Id = "51199", Text = "Other", Href = "/grid/other", IconName = IconName.PlusSquareFill, ParentId = "513" }, // last item - do not change + new (){ Id = "513", Text = "Grid", IconName = IconName.Grid, ParentId = "5" }, + new (){ Id = "51301", Text = "Overview", Href = DemoRouteConstants.Demos_URL_Grid_Overview, IconName = IconName.Grid, ParentId = "513" }, // first item - do not change + new (){ Id = "51302", Text = "Alignment", Href = DemoRouteConstants.Demos_URL_Grid_Alignment, IconName = IconName.Justify, ParentId = "513" }, + new (){ Id = "51303", Text = "Custom CSS Class", Href = DemoRouteConstants.Demos_URL_Grid_CustomCSSClass, IconName = IconName.FileTypeCss, ParentId = "513" }, + new (){ Id = "51304", Text = "Data Binding", Href = DemoRouteConstants.Demos_URL_Grid_DataBinding, IconName = IconName.GridFill, ParentId = "513" }, + new (){ Id = "51306", Text = "Detail View", Href = DemoRouteConstants.Demos_URL_Grid_DetailView, IconName = IconName.ListNested, ParentId = "513" }, + new (){ Id = "51307", Text = "Events", Href = DemoRouteConstants.Demos_URL_Grid_Events, IconName = IconName.LightningChargeFill, ParentId = "513" }, + new (){ Id = "51307", Text = "Filters", Href = DemoRouteConstants.Demos_URL_Grid_Filters, IconName = IconName.FunnelFill, ParentId = "513" }, + new (){ Id = "51308", Text = "Fixed Header", Href = DemoRouteConstants.Demos_URL_Grid_FixedHeader, IconName = IconName.Table, ParentId = "513" }, + new (){ Id = "51309", Text = "Freeze Columns", Href = DemoRouteConstants.Demos_URL_Grid_FreezeColumns, IconName = IconName.LayoutThreeColumns, ParentId = "513" }, + new (){ Id = "51310", Text = "Grid Settings", Href = DemoRouteConstants.Demos_URL_Grid_Settings, IconName = IconName.GearFill, ParentId = "513" }, + new (){ Id = "51311", Text = "Nested Grid", Href = DemoRouteConstants.Demos_URL_Grid_NestedGrid, IconName = IconName.Pip, ParentId = "513" }, + new (){ Id = "51312", Text = "Paging", Href = DemoRouteConstants.Demos_URL_Grid_Paging, IconName = IconName.ChevronBarRight, ParentId = "513" }, + new (){ Id = "51313", Text = "Selection", Href = DemoRouteConstants.Demos_URL_Grid_Selection, IconName = IconName.CheckSquareFill, ParentId = "513" }, + new (){ Id = "51314", Text = "Sorting", Href = DemoRouteConstants.Demos_URL_Grid_Sorting, IconName = IconName.ArrowDownUp, ParentId = "513" }, + new (){ Id = "51315", Text = "Summary", Href = DemoRouteConstants.Demos_URL_Grid_Summary, IconName = IconName.Calculator, ParentId = "513" }, + new (){ Id = "51316", Text = "Translations", Href = DemoRouteConstants.Demos_URL_Grid_Translations, IconName = IconName.Translate, ParentId = "513" }, + new (){ Id = "51399", Text = "Other", Href = DemoRouteConstants.Demos_URL_Grid_OtherExamples, IconName = IconName.PlusSquareFill, ParentId = "513" }, // last item - do not change #endregion Grid - new (){ Id = "514", Text = "Markdown", Href = "/markdown", IconName = IconName.MarkdownFill, ParentId = "5" }, - new (){ Id = "514", Text = "Modals", Href = "/modals", IconName = IconName.WindowStack, ParentId = "5" }, - new (){ Id = "515", Text = "Offcanvas", Href = "/offcanvas", IconName = IconName.LayoutSidebarReverse, ParentId = "5" }, - new (){ Id = "516", Text = "Pagination", Href = "/pagination", IconName = IconName.ThreeDots, ParentId = "5" }, - new (){ Id = "517", Text = "PDF Viewer", Href = "/pdf-viewer", IconName = IconName.FilePdfFill, ParentId = "5" }, - new (){ Id = "518", Text = "Placeholders", Href = "/placeholders", IconName = IconName.ColumnsGap, ParentId = "5" }, - new (){ Id = "519", Text = "Preload", Href = "/preload", IconName = IconName.ArrowClockwise, ParentId = "5" }, - new (){ Id = "520", Text = "Progress", Href = "/progress", IconName = IconName.UsbC, ParentId = "5" }, - new (){ Id = "521", Text = "Ribbon", Href = "/ribbon", IconName = IconName.WindowStack, ParentId = "5" }, - new (){ Id = "522", Text = "Script Loader", Href = "/script-loader", IconName = IconName.CodeSlash, ParentId = "5" }, - new (){ Id = "523", Text = "Sidebar", Href = "/sidebar", IconName = IconName.LayoutSidebar, ParentId = "5" }, - new (){ Id = "524", Text = "Sidebar 2", Href = "/sidebar2", IconName = IconName.ListNested, ParentId = "5" }, - new (){ Id = "525", Text = "Sortable List", Href = "/sortable-list", IconName = IconName.ArrowsMove, ParentId = "5" }, - new (){ Id = "526", Text = "Spinner", Href = "/spinners", IconName = IconName.ArrowRepeat, ParentId = "5" }, - new (){ Id = "527", Text = "Tabs", Href = "/tabs", IconName = IconName.WindowPlus, ParentId = "5" }, - new (){ Id = "528", Text = "Theme Switcher", Href = "/theme-switcher", IconName = IconName.NintendoSwitch, ParentId = "5" }, - new (){ Id = "529", Text = "Toasts", Href = "/toasts", IconName = IconName.ExclamationTriangleFill, ParentId = "5" }, - new (){ Id = "530", Text = "Tooltips", Href = "/tooltips", IconName = IconName.ChatSquareDotsFill, ParentId = "5" }, + new (){ Id = "514", Text = "Markdown", Href = DemoRouteConstants.Demos_URL_Markdown, IconName = IconName.MarkdownFill, ParentId = "5" }, + new (){ Id = "514", Text = "Modals", Href = DemoRouteConstants.Demos_URL_Modal, IconName = IconName.WindowStack, ParentId = "5" }, + new (){ Id = "515", Text = "Offcanvas", Href = DemoRouteConstants.Demos_URL_Offcanvas, IconName = IconName.LayoutSidebarReverse, ParentId = "5" }, + new (){ Id = "516", Text = "Pagination", Href = DemoRouteConstants.Demos_URL_Pagination, IconName = IconName.ThreeDots, ParentId = "5" }, + new (){ Id = "517", Text = "PDF Viewer", Href = DemoRouteConstants.Demos_URL_PDFViewer, IconName = IconName.FilePdfFill, ParentId = "5" }, + new (){ Id = "518", Text = "Placeholders", Href = DemoRouteConstants.Demos_URL_Placeholders, IconName = IconName.ColumnsGap, ParentId = "5" }, + new (){ Id = "519", Text = "Preload", Href = DemoRouteConstants.Demos_URL_Preload, IconName = IconName.ArrowClockwise, ParentId = "5" }, + new (){ Id = "520", Text = "Progress", Href = DemoRouteConstants.Demos_URL_Progress, IconName = IconName.UsbC, ParentId = "5" }, + new (){ Id = "521", Text = "Ribbon", Href = DemoRouteConstants.Demos_URL_Ribbon, IconName = IconName.WindowStack, ParentId = "5" }, + new (){ Id = "522", Text = "Script Loader", Href = DemoRouteConstants.Demos_URL_ScriptLoader, IconName = IconName.CodeSlash, ParentId = "5" }, + new (){ Id = "523", Text = "Sidebar", Href = DemoRouteConstants.Demos_URL_Sidebar, IconName = IconName.LayoutSidebar, ParentId = "5" }, + new (){ Id = "524", Text = "Sidebar 2", Href = DemoRouteConstants.Demos_URL_Sidebar2, IconName = IconName.ListNested, ParentId = "5" }, + new (){ Id = "5245", Text = "Split View", Href = DemoRouteConstants.Demos_URL_SplitView, IconName = IconName.LayoutSplit, ParentId = "5" }, + new (){ Id = "525", Text = "Sortable List", Href = DemoRouteConstants.Demos_URL_SortableList, IconName = IconName.ArrowsMove, ParentId = "5" }, + new (){ Id = "526", Text = "Spinner", Href = DemoRouteConstants.Demos_URL_Spinners, IconName = IconName.ArrowRepeat, ParentId = "5" }, + new (){ Id = "527", Text = "Tabs", Href = DemoRouteConstants.Demos_URL_Tabs, IconName = IconName.WindowPlus, ParentId = "5" }, + new (){ Id = "528", Text = "Theme Switcher", Href = DemoRouteConstants.Demos_URL_ThemeSwitcher, IconName = IconName.NintendoSwitch, ParentId = "5" }, + new (){ Id = "529", Text = "Toasts", Href = DemoRouteConstants.Demos_URL_Toasts, IconName = IconName.ExclamationTriangleFill, ParentId = "5" }, + new (){ Id = "530", Text = "Tooltips", Href = DemoRouteConstants.Demos_URL_Tooltips, IconName = IconName.ChatSquareDotsFill, ParentId = "5" }, new (){ Id = "6", Text = "Data Visualization", IconName = IconName.BarChartFill, IconColor = IconColor.Warning }, - new (){ Id = "600", Text = "Bar Chart", Href = "/charts/bar-chart", IconName = IconName.BarChartFill, ParentId = "6", Match = NavLinkMatch.All }, - new (){ Id = "601", Text = "Doughnut Chart", Href = "/charts/doughnut-chart", IconName = IconName.CircleFill, ParentId = "6", Match = NavLinkMatch.All }, - new (){ Id = "602", Text = "Line Chart", Href = "/charts/line-chart", IconName = IconName.GraphUp, ParentId = "6", Match = NavLinkMatch.All }, - new (){ Id = "603", Text = "Pie Chart", Href = "/charts/pie-chart", IconName = IconName.PieChartFill, ParentId = "6", Match = NavLinkMatch.All }, - new (){ Id = "604", Text = "Polar Area Chart", Href = "/charts/polar-area-chart", IconName = IconName.PieChartFill, ParentId = "6", Match = NavLinkMatch.All }, - new (){ Id = "605", Text = "Radar Chart", Href = "/charts/radar-chart", IconName = IconName.Radar, ParentId = "6", Match = NavLinkMatch.All }, - new (){ Id = "605", Text = "Scatter Chart", Href = "/charts/scatter-chart", IconName = IconName.GraphUpArrow, ParentId = "6", Match = NavLinkMatch.All }, + new (){ Id = "600", Text = "Bar Chart", Href = DemoRouteConstants.Demos_URL_BarChart, IconName = IconName.BarChartFill, ParentId = "6", Match = NavLinkMatch.All }, + new (){ Id = "601", Text = "Bubble Chart", Href = DemoRouteConstants.Demos_URL_BubbleChart, IconName = IconName.CircleFill, ParentId = "6", Match = NavLinkMatch.All }, + new (){ Id = "602", Text = "Doughnut Chart", Href = DemoRouteConstants.Demos_URL_DoughnutChart, IconName = IconName.CircleFill, ParentId = "6", Match = NavLinkMatch.All }, + new (){ Id = "603", Text = "Line Chart", Href = DemoRouteConstants.Demos_URL_LineChart, IconName = IconName.GraphUp, ParentId = "6", Match = NavLinkMatch.All }, + new (){ Id = "604", Text = "Pie Chart", Href = DemoRouteConstants.Demos_URL_PieChart, IconName = IconName.PieChartFill, ParentId = "6", Match = NavLinkMatch.All }, + new (){ Id = "605", Text = "Polar Area Chart", Href = DemoRouteConstants.Demos_URL_PolarAreaChart, IconName = IconName.PieChartFill, ParentId = "6", Match = NavLinkMatch.All }, + new (){ Id = "606", Text = "Radar Chart", Href = DemoRouteConstants.Demos_URL_RadarChart, IconName = IconName.Radar, ParentId = "6", Match = NavLinkMatch.All }, + new (){ Id = "607", Text = "Scatter Chart", Href = DemoRouteConstants.Demos_URL_ScatterChart, IconName = IconName.GraphUpArrow, ParentId = "6", Match = NavLinkMatch.All }, new(){ Id = "7", Text = "Services", IconName = IconName.WrenchAdjustableCircleFill, IconColor = IconColor.Success }, - new (){ Id = "700", Text = "Modal Service", Href = "/services/modal-service", IconName = IconName.WindowStack, ParentId = "7" }, + new (){ Id = "700", Text = "Modal Service", Href = DemoRouteConstants.Demos_URL_ModalService, IconName = IconName.WindowStack, ParentId = "7" }, new(){ Id = "19", Text = "Utilities", IconName = IconName.GearWideConnected, IconColor = IconColor.Info }, - new (){ Id = "1900", Text = "Color Utility", Href = "/utils/color-utility", IconName = IconName.Palette2, ParentId = "19" }, + new (){ Id = "1900", Text = "Color Utility", Href = DemoRouteConstants.Demos_URL_ColorUtils, IconName = IconName.Palette2, ParentId = "19" }, }; return navItems; } - - private async ValueTask OnThemeChanged(string themeName) - => await JS.InvokeVoidAsync("updateDemoCodeThemeCss", themeName); } diff --git a/BlazorBootstrap.Demo.RCL/Components/Layout/MainLayoutBase.cs b/BlazorBootstrap.Demo.RCL/Components/Layout/MainLayoutBase.cs index 68ae5a072..18f1e4118 100644 --- a/BlazorBootstrap.Demo.RCL/Components/Layout/MainLayoutBase.cs +++ b/BlazorBootstrap.Demo.RCL/Components/Layout/MainLayoutBase.cs @@ -4,6 +4,7 @@ public class MainLayoutBase : LayoutComponentBase { internal string version = default!; internal string dotNetVersion = default!; + internal string demosUrl = default!; internal string docsUrl = default!; internal string blogUrl = default!; internal string githubUrl = default!; @@ -25,6 +26,7 @@ protected override void OnInitialized() { version = $"v{Configuration["version"]}"; // example: v0.6.1 dotNetVersion = $".NET {Configuration["dotNetVersion"]}"; // example: 9.0.0 + demosUrl = $"{Configuration["urls:demos"]}"; docsUrl = $"{Configuration["urls:docs"]}"; blogUrl = $"{Configuration["urls:blog"]}"; githubUrl = $"{Configuration["urls:github"]}"; @@ -49,6 +51,7 @@ internal virtual async Task Sidebar2DataProvider(Sid public string Version => version; public string DotNetVersion => dotNetVersion; + public string DemosUrl => demosUrl; public string DocsUrl => docsUrl; public string BlogUrl => blogUrl; public string GithubUrl => githubUrl; diff --git a/BlazorBootstrap.Demo.RCL/Components/Layout/MainLayoutBaseFooter.razor b/BlazorBootstrap.Demo.RCL/Components/Layout/MainLayoutBaseFooter.razor index de129b136..0c5142705 100644 --- a/BlazorBootstrap.Demo.RCL/Components/Layout/MainLayoutBaseFooter.razor +++ b/BlazorBootstrap.Demo.RCL/Components/Layout/MainLayoutBaseFooter.razor @@ -23,7 +23,8 @@
    Links
    @@ -45,7 +46,26 @@
  • Stack Overflow
  • -
    + diff --git a/BlazorBootstrap.Demo.RCL/Components/Layout/MainLayoutBaseFooter.razor.cs b/BlazorBootstrap.Demo.RCL/Components/Layout/MainLayoutBaseFooter.razor.cs index 57e9eab0c..6ce585af5 100644 --- a/BlazorBootstrap.Demo.RCL/Components/Layout/MainLayoutBaseFooter.razor.cs +++ b/BlazorBootstrap.Demo.RCL/Components/Layout/MainLayoutBaseFooter.razor.cs @@ -4,6 +4,7 @@ public partial class MainLayoutBaseFooter : ComponentBase { [Parameter] public string? Version { get; set; } [Parameter] public string? DotNetVersion { get; set; } + [Parameter] public string? DemosUrl { get; set; } [Parameter] public string? DocsUrl { get; set; } [Parameter] public string? BlogUrl { get; set; } [Parameter] public string? GithubUrl { get; set; } diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/AI/AIChat/AIChatDocumentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/AI/AIChat/AIChatDocumentation.razor deleted file mode 100644 index fffd2c360..000000000 --- a/BlazorBootstrap.Demo.RCL/Components/Pages/AI/AIChat/AIChatDocumentation.razor +++ /dev/null @@ -1,26 +0,0 @@ -@attribute [Route(pageUrl)] - - - - - @pageDescription - - - - -
    -
    Alerts are available for any length of text, as well as an optional close button. For proper styling, use one of the eight colors.
    - -
    - -@code{ - private const string pageUrl = RouteConstants.Demos_AI_Chat_Documentation; - private const string pageTitle = "Blazor Open AI Chat Component"; - private const string pageDescription = "Provide contextual feedback messages for typical user actions with the handful of available and flexible Blazor Bootstrap alert messages."; // TODO: update - private const string metaTitle = "Blazor Open AI Chat Component"; - private const string metaDescription = "Provide contextual feedback messages for typical user actions with the handful of available and flexible Blazor Bootstrap alert messages."; // TODO: update - private const string imageUrl = "https://i.imgur.com/FGgEMp6.jpg"; // TODO: update -} \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/AI/AIChat/AIChat_Demo_01_Examples.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/AI/AIChat/AIChat_Demo_01_Examples.razor deleted file mode 100644 index a9cdd295b..000000000 --- a/BlazorBootstrap.Demo.RCL/Components/Pages/AI/AIChat/AIChat_Demo_01_Examples.razor +++ /dev/null @@ -1,4 +0,0 @@ - diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Blog/Index.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Blog/Index.razor new file mode 100644 index 000000000..45c70aa09 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Blog/Index.razor @@ -0,0 +1,22 @@ +@attribute [Route(pageUrl)] + + + + + @pageDescription + + + + + +@code{ + private const string pageUrl = DemoRouteConstants.Blog_URL_Prefix; + private const string pageTitle = "Blog"; + private const string pageDescription = "An Enterprise-class Blazor Bootstrap Component library built on the Blazor and Bootstrap CSS frameworks."; + private const string metaTitle = "Blog"; + private const string metaDescription = "An Enterprise-class Blazor Bootstrap Component library built on the Blazor and Bootstrap CSS frameworks."; + private const string imageUrl = "https://i.imgur.com/FGgEMp6.jpg"; +} \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Carousel/Carousel_Demo_01_Examples.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Carousel/Carousel_Demo_01_Examples.razor deleted file mode 100644 index bb2d2b0b5..000000000 --- a/BlazorBootstrap.Demo.RCL/Components/Pages/Carousel/Carousel_Demo_01_Examples.razor +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Carousel/Carousel_Demo_02_Indicators.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Carousel/Carousel_Demo_02_Indicators.razor deleted file mode 100644 index c0b533fbd..000000000 --- a/BlazorBootstrap.Demo.RCL/Components/Pages/Carousel/Carousel_Demo_02_Indicators.razor +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Carousel/Carousel_Demo_04_Crossfade.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Carousel/Carousel_Demo_04_Crossfade.razor deleted file mode 100644 index cd8b7ebd7..000000000 --- a/BlazorBootstrap.Demo.RCL/Components/Pages/Carousel/Carousel_Demo_04_Crossfade.razor +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Carousel/Carousel_Demo_05_Autoplay_A_StartOnPageLoad.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Carousel/Carousel_Demo_05_Autoplay_A_StartOnPageLoad.razor deleted file mode 100644 index 53f868140..000000000 --- a/BlazorBootstrap.Demo.RCL/Components/Pages/Carousel/Carousel_Demo_05_Autoplay_A_StartOnPageLoad.razor +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Carousel/Carousel_Demo_05_Autoplay_B_StartAfterUserInteraction.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Carousel/Carousel_Demo_05_Autoplay_B_StartAfterUserInteraction.razor deleted file mode 100644 index 354b0f3f2..000000000 --- a/BlazorBootstrap.Demo.RCL/Components/Pages/Carousel/Carousel_Demo_05_Autoplay_B_StartAfterUserInteraction.razor +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Carousel/Carousel_Demo_06_Individual_Carouselitem_Interval.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Carousel/Carousel_Demo_06_Individual_Carouselitem_Interval.razor deleted file mode 100644 index fbf1605cb..000000000 --- a/BlazorBootstrap.Demo.RCL/Components/Pages/Carousel/Carousel_Demo_06_Individual_Carouselitem_Interval.razor +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Carousel/Carousel_Demo_07_Autoplaying_Carousels_without_Controls.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Carousel/Carousel_Demo_07_Autoplaying_Carousels_without_Controls.razor deleted file mode 100644 index a152ece96..000000000 --- a/BlazorBootstrap.Demo.RCL/Components/Pages/Carousel/Carousel_Demo_07_Autoplaying_Carousels_without_Controls.razor +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Carousel/Carousel_Demo_08_Touch.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Carousel/Carousel_Demo_08_Touch.razor deleted file mode 100644 index f030da25a..000000000 --- a/BlazorBootstrap.Demo.RCL/Components/Pages/Carousel/Carousel_Demo_08_Touch.razor +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Charts/BarCharts/BarChartDocumentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Charts/BarCharts/BarChartDocumentation.razor deleted file mode 100644 index 45adfccd6..000000000 --- a/BlazorBootstrap.Demo.RCL/Components/Pages/Charts/BarCharts/BarChartDocumentation.razor +++ /dev/null @@ -1,52 +0,0 @@ -@attribute [Route(pageUrl)] - - - - - @pageDescription - - - - -
    -
    - Refer to the getting started guide for setting up charts. -
    - -
    -
    - In the following example, a categorical 12-color palette is used. -
    - - For data visualization, you can use the predefined palettes ColorUtility.CategoricalTwelveColors for a 12-color palette and ColorUtility.CategoricalSixColors for a 6-color palette. - These palettes offer a range of distinct and visually appealing colors that can be applied to represent different categories or data elements in your visualizations. - - - -
    - - -
    - - -
    -
    - By default, the chart is using the default locale of the platform on which it is running. - In the following example, you will see the chart in the German locale (de_DE). -
    - - -
    - - -@code { - private const string pageUrl = RouteConstants.Demos_BarChart_Documentation; - private const string pageTitle = "Blazor Bar Chart"; - private const string pageDescription = "A Blazor Bootstrap bar chart component is used to represent data values as vertical bars. It is sometimes used to show trend data and to compare multiple data sets side by side."; - private const string metaTitle = "Blazor Bar Chart Component"; - private const string metaDescription = "A Blazor Bootstrap bar chart component is used to represent data values as vertical bars. It is sometimes used to show trend data and to compare multiple data sets side by side."; - private const string imageUrl = "https://i.imgur.com/IX3bajc.png"; -} diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Charts/ChartsDocumentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Charts/ChartsDocumentation.razor deleted file mode 100644 index 211eb96f0..000000000 --- a/BlazorBootstrap.Demo.RCL/Components/Pages/Charts/ChartsDocumentation.razor +++ /dev/null @@ -1,48 +0,0 @@ -@attribute [Route(pageUrl)] - - - - - @pageDescription - - - - -
    - -
    - -
    -
    At this moment we are supporting seven blazor chart types.
    -
      -
    1. Bar Chart
    2. -
    3. Doughnut Chart
    4. -
    5. Line Chart
    6. -
    7. Pie Chart
    8. -
    9. Polar Area Chart
    10. -
    11. Radar Chart
    12. -
    13. Scatter Chart
    14. -
    - - - We will add Bubble Chart and Mixed Chart support in the subsequent versions. - -
    - -
    -
    - Refer to the getting started guide for setting up charts. -
    -
    - -@code { - private const string pageUrl = RouteConstants.Demos_Charts_Documentation; - private const string pageTitle = "Blazor Charts"; - private const string pageDescription = "Blazor Bootstrap charts are well-designed chart components on top of Chart.js to visualize data. It contains a rich UI gallery of charts that cater to all charting scenarios. Its high performance helps render large amounts of data quickly."; - private const string metaTitle = "Blazor Chart Components"; - private const string metaDescription = "Blazor Bootstrap charts are well-designed chart components on top of Chart.js to visualize data. It contains a rich UI gallery of charts that cater to all charting scenarios. Its high performance helps render large amounts of data quickly."; - private const string imageUrl = "https://i.imgur.com/IX3bajc.png"; -} diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Charts/DoughnutCharts/DoughnutChartDocumentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Charts/DoughnutCharts/DoughnutChartDocumentation.razor deleted file mode 100644 index 9b8b9897d..000000000 --- a/BlazorBootstrap.Demo.RCL/Components/Pages/Charts/DoughnutCharts/DoughnutChartDocumentation.razor +++ /dev/null @@ -1,42 +0,0 @@ -@attribute [Route(pageUrl)] - - - - - @pageDescription - - - - -
    -
    - Refer to the getting started guide for setting up charts. -
    -
    - -
    -
    - In the following example, a categorical 12-color palette is used. -
    - - For data visualization, you can use the predefined palettes ColorUtility.CategoricalTwelveColors for a 12-color palette and ColorUtility.CategoricalSixColors for a 6-color palette. - These palettes offer a range of distinct and visually appealing colors that can be applied to represent different categories or data elements in your visualizations. - - -
    - -
    - -
    - -@code { - private const string pageUrl = RouteConstants.Demos_DoughnutChart_Documentation; - private const string pageTitle = "Blazor Doughnut Chart"; - private const string pageDescription = "A Blazor donut chart component is a circular chart that shows the proportional values of different categories. It is similar to a pie chart, but the center of the donut chart is hollow. This makes it easier to see the individual values of each category."; - private const string metaTitle = "Blazor Doughnut Chart Component"; - private const string metaDescription = "A Blazor donut chart component is a circular chart that shows the proportional values of different categories. It is similar to a pie chart, but the center of the donut chart is hollow. This makes it easier to see the individual values of each category."; - private const string imageUrl = "https://i.imgur.com/xEPhAsW.png"; -} diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Charts/LineCharts/LineChartDocumentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Charts/LineCharts/LineChartDocumentation.razor deleted file mode 100644 index 441b7f087..000000000 --- a/BlazorBootstrap.Demo.RCL/Components/Pages/Charts/LineCharts/LineChartDocumentation.razor +++ /dev/null @@ -1,64 +0,0 @@ -@attribute [Route(pageUrl)] - - - - - @pageDescription - - - - -
    -
    - Refer to the getting started guide for setting up charts. -
    -
    - -
    -
    - In the following example, a categorical 12-color palette is used. -
    - - For data visualization, you can use the predefined palettes ColorUtility.CategoricalTwelveColors for a 12-color palette and ColorUtility.CategoricalSixColors for a 6-color palette. - These palettes offer a range of distinct and visually appealing colors that can be applied to represent different categories or data elements in your visualizations. - - -
    - -
    - -
    -
    - By default, the chart is using the default locale of the platform on which it is running. - In the following example, you will see the chart in the German locale (de_DE). -
    - -
    - -
    - -
    - -
    - -
    - -
    - -
    - -
    - -
    - -@code { - private const string pageUrl = RouteConstants.Demos_LineChart_Documentation; - private const string pageTitle = "Blazor Line Chart"; - private const string pageDescription = "A Blazor Bootstrap line chart component is a graphical representation of data that uses a series of connected points to show how the data changes over time. It is a type of x-y chart, where the x-axis represents the independent variable, such as time, and the y-axis represents the dependent variable, such as the value."; - private const string metaTitle = "Blazor Line Chart Component"; - private const string metaDescription = "A Blazor Bootstrap line chart component is a graphical representation of data that uses a series of connected points to show how the data changes over time. It is a type of x-y chart, where the x-axis represents the independent variable, such as time, and the y-axis represents the dependent variable, such as the value."; - private const string imageUrl = "https://i.imgur.com/8b7jH0D.png"; -} \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Charts/PolarAreaCharts/PolarAreaChartDocumentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Charts/PolarAreaCharts/PolarAreaChartDocumentation.razor deleted file mode 100644 index 14917b9ef..000000000 --- a/BlazorBootstrap.Demo.RCL/Components/Pages/Charts/PolarAreaCharts/PolarAreaChartDocumentation.razor +++ /dev/null @@ -1,38 +0,0 @@ -@attribute [Route(pageUrl)] - - - - - @pageDescription - - - - -
    -
    - Refer to the getting started guide for setting up charts. -
    -
    - -
    -
    - In the following example, a categorical 12-color palette is used. -
    - - For data visualization, you can use the predefined palettes ColorUtility.CategoricalTwelveColors for a 12-color palette and ColorUtility.CategoricalSixColors for a 6-color palette. - These palettes offer a range of distinct and visually appealing colors that can be applied to represent different categories or data elements in your visualizations. - - -
    - -@code { - private const string pageUrl = RouteConstants.Demos_PolarAreaChart_Documentation; - private const string pageTitle = "Blazor Polar Area Chart"; - private const string pageDescription = "A Blazor Bootstrap polar area charts are similar to pie charts, but each segment has the same angle - the radius of the segment differs depending on the value."; - private const string metaTitle = "Blazor Polar Area Chart Component"; - private const string metaDescription = "A Blazor Bootstrap polar area charts are similar to pie charts, but each segment has the same angle - the radius of the segment differs depending on the value."; - private const string imageUrl = "https://i.imgur.com/xLAqwGi.png"; -} diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Charts/RadarCharts/RadarChartDocumentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Charts/RadarCharts/RadarChartDocumentation.razor deleted file mode 100644 index c6e1abec6..000000000 --- a/BlazorBootstrap.Demo.RCL/Components/Pages/Charts/RadarCharts/RadarChartDocumentation.razor +++ /dev/null @@ -1,38 +0,0 @@ -@attribute [Route(pageUrl)] - - - - - @pageDescription - - - - -
    -
    - Refer to the getting started guide for setting up charts. -
    -
    - -
    -
    - In the following example, a categorical 12-color palette is used. -
    - - For data visualization, you can use the predefined palettes ColorUtility.CategoricalTwelveColors for a 12-color palette and ColorUtility.CategoricalSixColors for a 6-color palette. - These palettes offer a range of distinct and visually appealing colors that can be applied to represent different categories or data elements in your visualizations. - - -
    - -@code { - private const string pageUrl = RouteConstants.Demos_RadarChart_Documentation; - private const string pageTitle = "Blazor Radar Chart"; - private const string pageDescription = "A Blazor Bootstrap radar chart component is a way of showing multiple data points and the variation between them. They are often useful for comparing the points of two or more different data sets."; - private const string metaTitle = "Blazor Radar Chart Component"; - private const string metaDescription = "A Blazor Bootstrap radar chart component is a way of showing multiple data points and the variation between them. They are often useful for comparing the points of two or more different data sets."; - private const string imageUrl = "https://i.imgur.com/Urrb79M.png"; -} \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Accordion/AccordionDocumentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Accordion/AccordionDocumentation.razor similarity index 93% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Accordion/AccordionDocumentation.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Accordion/AccordionDocumentation.razor index 2aa5f2dea..aadbb8f41 100644 --- a/BlazorBootstrap.Demo.RCL/Components/Pages/Accordion/AccordionDocumentation.razor +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Accordion/AccordionDocumentation.razor @@ -1,15 +1,14 @@ @attribute [Route(pageUrl)] +@layout DemosMainLayout - + - - @pageDescription - - - +
    @@ -113,7 +112,7 @@
    @code { - private const string pageUrl = RouteConstants.Demos_Accordion_Documentation; + private const string pageUrl = DemoRouteConstants.Demos_URL_Accordion; private const string pageTitle = "Blazor Accordion"; private const string pageDescription = "Build vertically collapsing accordions in combination with our Collapse component."; private const string metaTitle = "Blazor Accordion Component"; diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Accordion/Accordion_Demo_01_Examples.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Accordion/Accordion_Demo_01_Examples.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Accordion/Accordion_Demo_01_Examples.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Accordion/Accordion_Demo_01_Examples.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Accordion/Accordion_Demo_02_Title_with_Icon.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Accordion/Accordion_Demo_02_Title_with_Icon.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Accordion/Accordion_Demo_02_Title_with_Icon.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Accordion/Accordion_Demo_02_Title_with_Icon.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Accordion/Accordion_Demo_03_Flush.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Accordion/Accordion_Demo_03_Flush.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Accordion/Accordion_Demo_03_Flush.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Accordion/Accordion_Demo_03_Flush.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Accordion/Accordion_Demo_04_Set_Default_Active.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Accordion/Accordion_Demo_04_Set_Default_Active.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Accordion/Accordion_Demo_04_Set_Default_Active.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Accordion/Accordion_Demo_04_Set_Default_Active.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Accordion/Accordion_Demo_05_Always_Open.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Accordion/Accordion_Demo_05_Always_Open.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Accordion/Accordion_Demo_05_Always_Open.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Accordion/Accordion_Demo_05_Always_Open.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Accordion/Accordion_Demo_06_Show_Hide_Individual_AccordionItems.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Accordion/Accordion_Demo_06_Show_Hide_Individual_AccordionItems.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Accordion/Accordion_Demo_06_Show_Hide_Individual_AccordionItems.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Accordion/Accordion_Demo_06_Show_Hide_Individual_AccordionItems.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Accordion/Accordion_Demo_07_Show_Hide_All_AccordionItems.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Accordion/Accordion_Demo_07_Show_Hide_All_AccordionItems.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Accordion/Accordion_Demo_07_Show_Hide_All_AccordionItems.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Accordion/Accordion_Demo_07_Show_Hide_All_AccordionItems.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Accordion/Accordion_Demo_08_Events.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Accordion/Accordion_Demo_08_Events.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Accordion/Accordion_Demo_08_Events.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Accordion/Accordion_Demo_08_Events.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Alerts/AlertDocumentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Alerts/AlertDocumentation.razor similarity index 86% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Alerts/AlertDocumentation.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Alerts/AlertDocumentation.razor index d49284a36..cd5bfcdcd 100644 --- a/BlazorBootstrap.Demo.RCL/Components/Pages/Alerts/AlertDocumentation.razor +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Alerts/AlertDocumentation.razor @@ -1,15 +1,14 @@ @attribute [Route(pageUrl)] +@layout DemosMainLayout - + - - @pageDescription - - - +
    Alerts are available for any length of text, as well as an optional close button. For proper styling, use one of the eight colors.
    @@ -48,8 +47,8 @@
    -@code{ - private const string pageUrl = RouteConstants.Demos_Alerts_Documentation; +@code { + private const string pageUrl = DemoRouteConstants.Demos_URL_Alerts; private const string pageTitle = "Blazor Alert"; private const string pageDescription = "Provide contextual feedback messages for typical user actions with the handful of available and flexible Blazor Bootstrap alert messages."; private const string metaTitle = "Blazor Alert Component"; diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Alerts/Alert_Demo_01_Examples.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Alerts/Alert_Demo_01_Examples.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Alerts/Alert_Demo_01_Examples.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Alerts/Alert_Demo_01_Examples.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Alerts/Alert_Demo_02_Link_Color.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Alerts/Alert_Demo_02_Link_Color.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Alerts/Alert_Demo_02_Link_Color.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Alerts/Alert_Demo_02_Link_Color.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Alerts/Alert_Demo_03_Additional_Content.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Alerts/Alert_Demo_03_Additional_Content.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Alerts/Alert_Demo_03_Additional_Content.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Alerts/Alert_Demo_03_Additional_Content.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Alerts/Alert_Demo_04_Icons.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Alerts/Alert_Demo_04_Icons.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Alerts/Alert_Demo_04_Icons.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Alerts/Alert_Demo_04_Icons.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Alerts/Alert_Demo_05_Dismissing_A.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Alerts/Alert_Demo_05_Dismissing_A.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Alerts/Alert_Demo_05_Dismissing_A.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Alerts/Alert_Demo_05_Dismissing_A.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Alerts/Alert_Demo_05_Dismissing_B.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Alerts/Alert_Demo_05_Dismissing_B.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Alerts/Alert_Demo_05_Dismissing_B.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Alerts/Alert_Demo_05_Dismissing_B.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Alerts/Alert_Demo_06_Switch_Alert_Type_Dynamically.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Alerts/Alert_Demo_06_Switch_Alert_Type_Dynamically.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Alerts/Alert_Demo_06_Switch_Alert_Type_Dynamically.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Alerts/Alert_Demo_06_Switch_Alert_Type_Dynamically.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Badge/BadgeDocumentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Badge/BadgeDocumentation.razor similarity index 88% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Badge/BadgeDocumentation.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Badge/BadgeDocumentation.razor index 1ac1ad314..0ca090336 100644 --- a/BlazorBootstrap.Demo.RCL/Components/Pages/Badge/BadgeDocumentation.razor +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Badge/BadgeDocumentation.razor @@ -1,15 +1,14 @@ @attribute [Route(pageUrl)] +@layout DemosMainLayout - + - - @pageDescription - - - +
    @@ -61,7 +60,7 @@
    @code { - private const string pageUrl = RouteConstants.Demos_Badge_Documentation; + private const string pageUrl = DemoRouteConstants.Demos_URL_Badge; private const string pageTitle = "Blazor Badge"; private const string pageDescription = "The Blazor Bootstrap Badge component shows the small count and labels."; private const string metaTitle = "Blazor Badge Component"; diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Badge/Badge_Demo_01_Examples.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Badge/Badge_Demo_01_Examples.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Badge/Badge_Demo_01_Examples.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Badge/Badge_Demo_01_Examples.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Badge/Badge_Demo_02_Background_Colors.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Badge/Badge_Demo_02_Background_Colors.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Badge/Badge_Demo_02_Background_Colors.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Badge/Badge_Demo_02_Background_Colors.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Badge/Badge_Demo_03_Pill_Badges.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Badge/Badge_Demo_03_Pill_Badges.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Badge/Badge_Demo_03_Pill_Badges.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Badge/Badge_Demo_03_Pill_Badges.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Badge/Badge_Demo_04_Buttons.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Badge/Badge_Demo_04_Buttons.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Badge/Badge_Demo_04_Buttons.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Badge/Badge_Demo_04_Buttons.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Badge/Badge_Demo_05_Positioned.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Badge/Badge_Demo_05_Positioned.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Badge/Badge_Demo_05_Positioned.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Badge/Badge_Demo_05_Positioned.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Badge/Badge_Demo_06_Generic_Indicator.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Badge/Badge_Demo_06_Generic_Indicator.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Badge/Badge_Demo_06_Generic_Indicator.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Badge/Badge_Demo_06_Generic_Indicator.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Breadcrumb/BreadcrumbDocumentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Breadcrumb/BreadcrumbDocumentation.razor similarity index 69% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Breadcrumb/BreadcrumbDocumentation.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Breadcrumb/BreadcrumbDocumentation.razor index 2afe81ab4..57e6073c2 100644 --- a/BlazorBootstrap.Demo.RCL/Components/Pages/Breadcrumb/BreadcrumbDocumentation.razor +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Breadcrumb/BreadcrumbDocumentation.razor @@ -1,15 +1,14 @@ @attribute [Route(pageUrl)] +@layout DemosMainLayout - + - - @pageDescription - - - +
    @@ -24,7 +23,7 @@
    @code { - private const string pageUrl = RouteConstants.Demos_Breadcrumb_Documentation; + private const string pageUrl = DemoRouteConstants.Demos_URL_Breadcrumb; private const string pageTitle = "Blazor Breadcrumb"; private const string pageDescription = "Indicate the current page's location within a navigational hierarchy that automatically adds separators."; private const string metaTitle = "Blazor Breadcrumb Component"; diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Breadcrumb/Breadcrumb_Demo_01_Examples.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Breadcrumb/Breadcrumb_Demo_01_Examples.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Breadcrumb/Breadcrumb_Demo_01_Examples.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Breadcrumb/Breadcrumb_Demo_01_Examples.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Breadcrumb/Breadcrumb_Demo_02_Dividers.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Breadcrumb/Breadcrumb_Demo_02_Dividers.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Breadcrumb/Breadcrumb_Demo_02_Dividers.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Breadcrumb/Breadcrumb_Demo_02_Dividers.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Breadcrumb/Breadcrumb_Demo_03_Embedded_SVG.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Breadcrumb/Breadcrumb_Demo_03_Embedded_SVG.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Breadcrumb/Breadcrumb_Demo_03_Embedded_SVG.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Breadcrumb/Breadcrumb_Demo_03_Embedded_SVG.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Buttons/ButtonDocumentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Buttons/ButtonDocumentation.razor similarity index 92% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Buttons/ButtonDocumentation.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Buttons/ButtonDocumentation.razor index 0ac15eb22..73558e068 100644 --- a/BlazorBootstrap.Demo.RCL/Components/Pages/Buttons/ButtonDocumentation.razor +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Buttons/ButtonDocumentation.razor @@ -1,15 +1,14 @@ @attribute [Route(pageUrl)] +@layout DemosMainLayout - + - - @pageDescription - - - +
    Bootstrap includes several predefined button styles, each serving its own semantic purpose, with a few extras thrown in for more control.
    @@ -101,7 +100,7 @@
    @code { - private const string pageUrl = RouteConstants.Demos_Buttons_Documentation; + private const string pageUrl = DemoRouteConstants.Demos_URL_Buttons; private const string pageTitle = "Blazor Button"; private const string pageDescription = "Use Blazor Bootstrap button styles for actions in forms, dialogs, and more with support for multiple sizes, states, etc."; private const string metaTitle = "Blazor Button Component"; diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Buttons/Button_Demo_01_Examples.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Buttons/Button_Demo_01_Examples.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Buttons/Button_Demo_01_Examples.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Buttons/Button_Demo_01_Examples.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Buttons/Button_Demo_02_Button_Tags.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Buttons/Button_Demo_02_Button_Tags.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Buttons/Button_Demo_02_Button_Tags.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Buttons/Button_Demo_02_Button_Tags.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Buttons/Button_Demo_03_Outline_Buttons.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Buttons/Button_Demo_03_Outline_Buttons.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Buttons/Button_Demo_03_Outline_Buttons.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Buttons/Button_Demo_03_Outline_Buttons.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Buttons/Button_Demo_04_Sizes_A.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Buttons/Button_Demo_04_Sizes_A.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Buttons/Button_Demo_04_Sizes_A.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Buttons/Button_Demo_04_Sizes_A.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Buttons/Button_Demo_04_Sizes_B.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Buttons/Button_Demo_04_Sizes_B.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Buttons/Button_Demo_04_Sizes_B.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Buttons/Button_Demo_04_Sizes_B.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Buttons/Button_Demo_04_Sizes_C.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Buttons/Button_Demo_04_Sizes_C.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Buttons/Button_Demo_04_Sizes_C.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Buttons/Button_Demo_04_Sizes_C.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Buttons/Button_Demo_05_Disabled_State_A.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Buttons/Button_Demo_05_Disabled_State_A.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Buttons/Button_Demo_05_Disabled_State_A.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Buttons/Button_Demo_05_Disabled_State_A.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Buttons/Button_Demo_05_Disabled_State_B.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Buttons/Button_Demo_05_Disabled_State_B.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Buttons/Button_Demo_05_Disabled_State_B.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Buttons/Button_Demo_05_Disabled_State_B.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Buttons/Button_Demo_06_Block_Buttons_A.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Buttons/Button_Demo_06_Block_Buttons_A.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Buttons/Button_Demo_06_Block_Buttons_A.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Buttons/Button_Demo_06_Block_Buttons_A.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Buttons/Button_Demo_06_Block_Buttons_B.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Buttons/Button_Demo_06_Block_Buttons_B.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Buttons/Button_Demo_06_Block_Buttons_B.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Buttons/Button_Demo_06_Block_Buttons_B.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Buttons/Button_Demo_06_Block_Buttons_C.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Buttons/Button_Demo_06_Block_Buttons_C.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Buttons/Button_Demo_06_Block_Buttons_C.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Buttons/Button_Demo_06_Block_Buttons_C.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Buttons/Button_Demo_06_Block_Buttons_D.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Buttons/Button_Demo_06_Block_Buttons_D.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Buttons/Button_Demo_06_Block_Buttons_D.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Buttons/Button_Demo_06_Block_Buttons_D.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Buttons/Button_Demo_07_Toggle_States_A.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Buttons/Button_Demo_07_Toggle_States_A.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Buttons/Button_Demo_07_Toggle_States_A.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Buttons/Button_Demo_07_Toggle_States_A.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Buttons/Button_Demo_07_Toggle_States_B.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Buttons/Button_Demo_07_Toggle_States_B.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Buttons/Button_Demo_07_Toggle_States_B.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Buttons/Button_Demo_07_Toggle_States_B.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Buttons/Button_Demo_08_Loading_Spinner.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Buttons/Button_Demo_08_Loading_Spinner.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Buttons/Button_Demo_08_Loading_Spinner.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Buttons/Button_Demo_08_Loading_Spinner.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Buttons/Button_Demo_08_Show_Hide_Loading_Spinner.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Buttons/Button_Demo_08_Show_Hide_Loading_Spinner.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Buttons/Button_Demo_08_Show_Hide_Loading_Spinner.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Buttons/Button_Demo_08_Show_Hide_Loading_Spinner.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Buttons/Button_Demo_09_A_Show_Tooltip.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Buttons/Button_Demo_09_A_Show_Tooltip.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Buttons/Button_Demo_09_A_Show_Tooltip.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Buttons/Button_Demo_09_A_Show_Tooltip.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Buttons/Button_Demo_09_B_Dynamically_update_the_tooltip_text.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Buttons/Button_Demo_09_B_Dynamically_update_the_tooltip_text.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Buttons/Button_Demo_09_B_Dynamically_update_the_tooltip_text.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Buttons/Button_Demo_09_B_Dynamically_update_the_tooltip_text.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Buttons/Button_Demo_09_C_Tooltip_Color.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Buttons/Button_Demo_09_C_Tooltip_Color.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Buttons/Button_Demo_09_C_Tooltip_Color.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Buttons/Button_Demo_09_C_Tooltip_Color.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Buttons/Button_Demo_10_Click_Event.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Buttons/Button_Demo_10_Click_Event.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Buttons/Button_Demo_10_Click_Event.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Buttons/Button_Demo_10_Click_Event.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Buttons/Button_Demo_11_Double_Click_Event.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Buttons/Button_Demo_11_Double_Click_Event.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Buttons/Button_Demo_11_Double_Click_Event.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Buttons/Button_Demo_11_Double_Click_Event.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Buttons/Button_Demo_12_Click_Event_With_Args.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Buttons/Button_Demo_12_Click_Event_With_Args.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Buttons/Button_Demo_12_Click_Event_With_Args.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Buttons/Button_Demo_12_Click_Event_With_Args.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Buttons/Button_Demo_13_Disable_Enable_Dynamically.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Buttons/Button_Demo_13_Disable_Enable_Dynamically.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Buttons/Button_Demo_13_Disable_Enable_Dynamically.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Buttons/Button_Demo_13_Disable_Enable_Dynamically.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Callout/CalloutDocumentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Callout/CalloutDocumentation.razor similarity index 72% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Callout/CalloutDocumentation.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Callout/CalloutDocumentation.razor index 61564e389..4710a88b5 100644 --- a/BlazorBootstrap.Demo.RCL/Components/Pages/Callout/CalloutDocumentation.razor +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Callout/CalloutDocumentation.razor @@ -1,15 +1,14 @@ @attribute [Route(pageUrl)] +@layout DemosMainLayout - + - - @pageDescription - - - +
    @@ -28,7 +27,7 @@
    @code { - private const string pageUrl = RouteConstants.Demos_Callout_Documentation; + private const string pageUrl = DemoRouteConstants.Demos_URL_Callout; private const string pageTitle = "Blazor Callout"; private const string pageDescription = "Blazor Bootstrap callout component provides content presentation in a visually distinct manner."; private const string metaTitle = "Blazor Callout Component"; diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Callout/Callout_Demo_01_Examples.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Callout/Callout_Demo_01_Examples.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Callout/Callout_Demo_01_Examples.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Callout/Callout_Demo_01_Examples.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Callout/Callout_Demo_02_Change_Heading.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Callout/Callout_Demo_02_Change_Heading.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Callout/Callout_Demo_02_Change_Heading.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Callout/Callout_Demo_02_Change_Heading.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Callout/Callout_Demo_03_Large_Text.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Callout/Callout_Demo_03_Large_Text.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Callout/Callout_Demo_03_Large_Text.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Callout/Callout_Demo_03_Large_Text.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Callout/Callout_Demo_04_Hide_Heading.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Callout/Callout_Demo_04_Hide_Heading.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Callout/Callout_Demo_04_Hide_Heading.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Callout/Callout_Demo_04_Hide_Heading.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Card/CardDocumentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Card/CardDocumentation.razor similarity index 91% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Card/CardDocumentation.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Card/CardDocumentation.razor index 1537aeabf..9bdfd52f4 100644 --- a/BlazorBootstrap.Demo.RCL/Components/Pages/Card/CardDocumentation.razor +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Card/CardDocumentation.razor @@ -1,15 +1,14 @@ @attribute [Route(pageUrl)] +@layout DemosMainLayout - + - - @pageDescription - - - +
    @@ -104,7 +103,7 @@
    @code { - private const string pageUrl = RouteConstants.Demos_Card_Documentation; + private const string pageUrl = DemoRouteConstants.Demos_URL_Card; private const string pageTitle = "Blazor Card"; private const string pageDescription = "BootstrapBootstrap's cards provide a flexible and extensible content container with multiple variants and options."; private const string metaTitle = "Blazor Card Component"; diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Card/Card_Demo_01_Examples.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Card/Card_Demo_01_Examples.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Card/Card_Demo_01_Examples.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Card/Card_Demo_01_Examples.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Card/Card_Demo_02_Content_Types_Body.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Card/Card_Demo_02_Content_Types_Body.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Card/Card_Demo_02_Content_Types_Body.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Card/Card_Demo_02_Content_Types_Body.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Card/Card_Demo_03_Content_Types_Titles_Text_And_Links.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Card/Card_Demo_03_Content_Types_Titles_Text_And_Links.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Card/Card_Demo_03_Content_Types_Titles_Text_And_Links.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Card/Card_Demo_03_Content_Types_Titles_Text_And_Links.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Card/Card_Demo_04_Content_Types_Images.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Card/Card_Demo_04_Content_Types_Images.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Card/Card_Demo_04_Content_Types_Images.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Card/Card_Demo_04_Content_Types_Images.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Card/Card_Demo_05_Content_Types_List_Groups.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Card/Card_Demo_05_Content_Types_List_Groups.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Card/Card_Demo_05_Content_Types_List_Groups.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Card/Card_Demo_05_Content_Types_List_Groups.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Card/Card_Demo_06_Content_Types_Kitchen_Sink.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Card/Card_Demo_06_Content_Types_Kitchen_Sink.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Card/Card_Demo_06_Content_Types_Kitchen_Sink.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Card/Card_Demo_06_Content_Types_Kitchen_Sink.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Card/Card_Demo_07_Header_And_Footer.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Card/Card_Demo_07_Header_And_Footer.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Card/Card_Demo_07_Header_And_Footer.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Card/Card_Demo_07_Header_And_Footer.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Card/Card_Demo_08_Sizing.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Card/Card_Demo_08_Sizing.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Card/Card_Demo_08_Sizing.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Card/Card_Demo_08_Sizing.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Card/Card_Demo_09_Text_Alignment.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Card/Card_Demo_09_Text_Alignment.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Card/Card_Demo_09_Text_Alignment.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Card/Card_Demo_09_Text_Alignment.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Card/Card_Demo_10_Background_And_Color.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Card/Card_Demo_10_Background_And_Color.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Card/Card_Demo_10_Background_And_Color.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Card/Card_Demo_10_Background_And_Color.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Card/Card_Demo_11_Card_Groups.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Card/Card_Demo_11_Card_Groups.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Card/Card_Demo_11_Card_Groups.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Card/Card_Demo_11_Card_Groups.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Card/Card_Demo_12_Card_Groups_With_Footer.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Card/Card_Demo_12_Card_Groups_With_Footer.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Card/Card_Demo_12_Card_Groups_With_Footer.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Card/Card_Demo_12_Card_Groups_With_Footer.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Carousel/CarouselDocumentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Carousel/CarouselDocumentation.razor similarity index 91% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Carousel/CarouselDocumentation.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Carousel/CarouselDocumentation.razor index ec55ccdce..54b8fa324 100644 --- a/BlazorBootstrap.Demo.RCL/Components/Pages/Carousel/CarouselDocumentation.razor +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Carousel/CarouselDocumentation.razor @@ -1,15 +1,14 @@ @attribute [Route(pageUrl)] +@layout DemosMainLayout - + - - @pageDescription - - - +
    Here is a basic example of a carousel with three slides.
    @@ -105,7 +104,7 @@ @code { - private const string pageUrl = RouteConstants.Demos_Carousel_Documentation; + private const string pageUrl = DemoRouteConstants.Demos_URL_Carousel; private const string pageTitle = "Blazor Carousel"; private const string pageDescription = "Blazor Carousel component is a slideshow component that cycles through elements, images, or slides of text."; private const string metaTitle = "Blazor Carousel Component"; diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Carousel/Carousel_Demo_01_Examples.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Carousel/Carousel_Demo_01_Examples.razor new file mode 100644 index 000000000..a5bd9c81b --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Carousel/Carousel_Demo_01_Examples.razor @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Carousel/Carousel_Demo_02_Indicators.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Carousel/Carousel_Demo_02_Indicators.razor new file mode 100644 index 000000000..dca44a406 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Carousel/Carousel_Demo_02_Indicators.razor @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Carousel/Carousel_Demo_03_Captions.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Carousel/Carousel_Demo_03_Captions.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Carousel/Carousel_Demo_03_Captions.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Carousel/Carousel_Demo_03_Captions.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Carousel/Carousel_Demo_04_Crossfade.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Carousel/Carousel_Demo_04_Crossfade.razor new file mode 100644 index 000000000..46324e7c2 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Carousel/Carousel_Demo_04_Crossfade.razor @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Carousel/Carousel_Demo_05_Autoplay_A_StartOnPageLoad.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Carousel/Carousel_Demo_05_Autoplay_A_StartOnPageLoad.razor new file mode 100644 index 000000000..bfbfac7e2 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Carousel/Carousel_Demo_05_Autoplay_A_StartOnPageLoad.razor @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Carousel/Carousel_Demo_05_Autoplay_B_StartAfterUserInteraction.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Carousel/Carousel_Demo_05_Autoplay_B_StartAfterUserInteraction.razor new file mode 100644 index 000000000..a134297d7 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Carousel/Carousel_Demo_05_Autoplay_B_StartAfterUserInteraction.razor @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Carousel/Carousel_Demo_06_Individual_Carouselitem_Interval.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Carousel/Carousel_Demo_06_Individual_Carouselitem_Interval.razor new file mode 100644 index 000000000..7dc7108d3 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Carousel/Carousel_Demo_06_Individual_Carouselitem_Interval.razor @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Carousel/Carousel_Demo_07_Autoplaying_Carousels_without_Controls.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Carousel/Carousel_Demo_07_Autoplaying_Carousels_without_Controls.razor new file mode 100644 index 000000000..1f7caee99 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Carousel/Carousel_Demo_07_Autoplaying_Carousels_without_Controls.razor @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Carousel/Carousel_Demo_08_Touch.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Carousel/Carousel_Demo_08_Touch.razor new file mode 100644 index 000000000..b93ab978e --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Carousel/Carousel_Demo_08_Touch.razor @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Carousel/Carousel_Demo_09_Events.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Carousel/Carousel_Demo_09_Events.razor similarity index 79% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Carousel/Carousel_Demo_09_Events.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Carousel/Carousel_Demo_09_Events.razor index b2370ebec..6c4c53888 100644 --- a/BlazorBootstrap.Demo.RCL/Components/Pages/Carousel/Carousel_Demo_09_Events.razor +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Carousel/Carousel_Demo_09_Events.razor @@ -1,12 +1,12 @@  - + - + - + diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/BarCharts/BarChartDocumentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/BarCharts/BarChartDocumentation.razor new file mode 100644 index 000000000..1a3601297 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/BarCharts/BarChartDocumentation.razor @@ -0,0 +1,88 @@ +@attribute [Route(pageUrl)] +@layout DemosMainLayout + + + +
    +
    + In the following example, a categorical 12-color palette is used. +
    + + For data visualization, you can use the predefined palettes ColorUtility.CategoricalTwelveColors for a 12-color palette and ColorUtility.CategoricalSixColors for a 6-color palette. + These palettes offer a range of distinct and visually appealing colors that can be applied to represent different categories or data elements in your visualizations. + + + +
    + + +
    + + +
    +
    + Set the Stack property on each dataset to group bars into separate stacked series within the same chart. +
    + + +
    +
    + Use BorderRadius on each dataset to soften bar edges and create rounded columns. +
    + + +
    +
    + By default, the chart is using the default locale of the platform on which it is running. + In the following example, you will see the chart in the German locale (de_DE). +
    + + +
    + + +
    +
    + Configure chart-level animation timing through ChartOptions.Animation to delay or pace the initial render. +
    + + +
    +
    + You can configure animations globally on the chart options or per dataset to stagger how each series enters the chart. +
    + + +
    +
    + Mix BarChartDataset and LineChartDataset in the same chart to combine columns with a trend line. +
    + + +
    +
    + Set the OnClick callback to react when a chart data item is selected. The callback receives ChartClickEventArgs with the dataset index and label, data-item index and label, and raw value. +
    + +
    + + + + + For a complete charts setup walkthrough, see the + Getting Started — Charts Setup section. + + +@code { + private const string pageUrl = DemoRouteConstants.Demos_URL_BarChart; + private const string pageTitle = "Blazor Bar Chart"; + private const string pageDescription = "A BlazorExpress.ChartJS bar chart component is used to represent data values as vertical bars. It is sometimes used to show trend data and to compare multiple data sets side by side."; + private const string metaTitle = "Blazor Bar Chart Component"; + private const string metaDescription = "A BlazorExpress.ChartJS bar chart component is used to represent data values as vertical bars. It is sometimes used to show trend data and to compare multiple data sets side by side."; + private const string imageUrl = "https://i.imgur.com/IX3bajc.png"; +} diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Charts/BarCharts/BarChart_Demo_01_Examples.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/BarCharts/BarChart_Demo_01_Examples.razor similarity index 95% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Charts/BarCharts/BarChart_Demo_01_Examples.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/BarCharts/BarChart_Demo_01_Examples.razor index 02cc0d82d..ce5827611 100644 --- a/BlazorBootstrap.Demo.RCL/Components/Pages/Charts/BarCharts/BarChart_Demo_01_Examples.razor +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/BarCharts/BarChart_Demo_01_Examples.razor @@ -1,4 +1,4 @@ - +
    @@ -120,7 +120,7 @@ private BarChartDataset GetRandomBarChartDataset() { - var c = ColorUtility.CategoricalTwelveColors[datasetsCount].ToColor(); + var c = ColorUtility.CategoricalTwelveColors[datasetsCount].ToChartColor(); datasetsCount += 1; @@ -128,8 +128,8 @@ { Label = $"Product {datasetsCount}", Data = GetRandomData(), - BackgroundColor = new List { c.ToRgbString() }, - BorderColor = new List { c.ToRgbString() }, + BackgroundColor = new List { c.ToChartRgbString() }, + BorderColor = new List { c.ToChartRgbString() }, BorderWidth = new List { 0 }, }; } diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Charts/BarCharts/BarChart_Demo_02_Horizontal_BarChart.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/BarCharts/BarChart_Demo_02_Horizontal_BarChart.razor similarity index 96% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Charts/BarCharts/BarChart_Demo_02_Horizontal_BarChart.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/BarCharts/BarChart_Demo_02_Horizontal_BarChart.razor index 948bf9ce0..f814b2c90 100644 --- a/BlazorBootstrap.Demo.RCL/Components/Pages/Charts/BarCharts/BarChart_Demo_02_Horizontal_BarChart.razor +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/BarCharts/BarChart_Demo_02_Horizontal_BarChart.razor @@ -1,4 +1,4 @@ - + @code { private BarChart barChart = default!; diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Charts/BarCharts/BarChart_Demo_03_Stacked_BarChart.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/BarCharts/BarChart_Demo_03_Stacked_BarChart.razor similarity index 97% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Charts/BarCharts/BarChart_Demo_03_Stacked_BarChart.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/BarCharts/BarChart_Demo_03_Stacked_BarChart.razor index 83b824549..06a271e18 100644 --- a/BlazorBootstrap.Demo.RCL/Components/Pages/Charts/BarCharts/BarChart_Demo_03_Stacked_BarChart.razor +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/BarCharts/BarChart_Demo_03_Stacked_BarChart.razor @@ -1,4 +1,4 @@ - + @code { private BarChart barChart = default!; diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Charts/BarCharts/BarChart_Demo_04_Locale.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/BarCharts/BarChart_Demo_04_Locale.razor similarity index 97% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Charts/BarCharts/BarChart_Demo_04_Locale.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/BarCharts/BarChart_Demo_04_Locale.razor index c28f87227..802d39d04 100644 --- a/BlazorBootstrap.Demo.RCL/Components/Pages/Charts/BarCharts/BarChart_Demo_04_Locale.razor +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/BarCharts/BarChart_Demo_04_Locale.razor @@ -1,4 +1,4 @@ - + @code { private BarChart barChart = default!; diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Charts/BarCharts/BarChart_Demo_05_Stacked_BarChart_with_Datalabels.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/BarCharts/BarChart_Demo_05_Stacked_BarChart_with_Datalabels.razor similarity index 97% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Charts/BarCharts/BarChart_Demo_05_Stacked_BarChart_with_Datalabels.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/BarCharts/BarChart_Demo_05_Stacked_BarChart_with_Datalabels.razor index a0f29f319..9af0adb37 100644 --- a/BlazorBootstrap.Demo.RCL/Components/Pages/Charts/BarCharts/BarChart_Demo_05_Stacked_BarChart_with_Datalabels.razor +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/BarCharts/BarChart_Demo_05_Stacked_BarChart_with_Datalabels.razor @@ -1,4 +1,4 @@ - + @code { private BarChart barChart = default!; diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/BarCharts/BarChart_Demo_07_Dataset_Animation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/BarCharts/BarChart_Demo_07_Dataset_Animation.razor new file mode 100644 index 000000000..00f6ba4f3 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/BarCharts/BarChart_Demo_07_Dataset_Animation.razor @@ -0,0 +1,61 @@ + + +@code { + private BarChart barChart = default!; + private BarChartOptions barChartOptions = default!; + private ChartData chartData = default!; + + protected override void OnInitialized() + { + var colors = ColorUtility.CategoricalTwelveColors; + + chartData = new ChartData + { + Labels = new List { "January", "February", "March", "April", "May", "June" }, + Datasets = new List + { + new BarChartDataset + { + Label = "Product A", + Data = new List { 65, 59, 80, 81, 56, 55 }, + BackgroundColor = new List { colors[0].ToChartColor().ToChartRgbString() }, + BorderColor = new List { colors[0].ToChartColor().ToChartRgbString() }, + BorderWidth = new List { 0 }, + Animation = new ChartAnimation { Delay = 0, Duration = 1200 } + }, + new BarChartDataset + { + Label = "Product B", + Data = new List { 28, 48, 40, 19, 86, 27 }, + BackgroundColor = new List { colors[1].ToChartColor().ToChartRgbString() }, + BorderColor = new List { colors[1].ToChartColor().ToChartRgbString() }, + BorderWidth = new List { 0 }, + Animation = new ChartAnimation { Delay = 250, Duration = 1200 } + }, + new BarChartDataset + { + Label = "Product C", + Data = new List { 18, 38, 50, 29, 66, 47 }, + BackgroundColor = new List { colors[2].ToChartColor().ToChartRgbString() }, + BorderColor = new List { colors[2].ToChartColor().ToChartRgbString() }, + BorderWidth = new List { 0 }, + Animation = new ChartAnimation { Delay = 500, Duration = 1200 } + } + } + }; + + barChartOptions = new BarChartOptions + { + Responsive = true, + Animation = new ChartAnimation { Duration = 1200, Easing = "easeOutQuart" } + }; + } + + protected override async Task OnAfterRenderAsync(bool firstRender) + { + if (firstRender) + await barChart.InitializeAsync(chartData, barChartOptions); + + await base.OnAfterRenderAsync(firstRender); + } +} \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/BarCharts/BarChart_Demo_08_Grouped_Stacks.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/BarCharts/BarChart_Demo_08_Grouped_Stacks.razor new file mode 100644 index 000000000..77360876b --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/BarCharts/BarChart_Demo_08_Grouped_Stacks.razor @@ -0,0 +1,77 @@ + + +@code { + private BarChart barChart = default!; + private BarChartOptions barChartOptions = default!; + private ChartData chartData = default!; + + protected override void OnInitialized() + { + var colors = ColorUtility.CategoricalTwelveColors; + + chartData = new ChartData + { + Labels = new List { "Q1", "Q2", "Q3", "Q4" }, + Datasets = new List + { + new BarChartDataset + { + Label = "North Budget", + Data = new List { 42, 47, 44, 50 }, + BackgroundColor = new List { colors[0] }, + BorderColor = new List { colors[0] }, + BorderWidth = new List { 0 }, + Stack = "North" + }, + new BarChartDataset + { + Label = "North Actual", + Data = new List { 39, 45, 48, 53 }, + BackgroundColor = new List { colors[1] }, + BorderColor = new List { colors[1] }, + BorderWidth = new List { 0 }, + Stack = "North" + }, + new BarChartDataset + { + Label = "South Budget", + Data = new List { 35, 38, 41, 46 }, + BackgroundColor = new List { colors[4] }, + BorderColor = new List { colors[4] }, + BorderWidth = new List { 0 }, + Stack = "South" + }, + new BarChartDataset + { + Label = "South Actual", + Data = new List { 33, 40, 43, 45 }, + BackgroundColor = new List { colors[5] }, + BorderColor = new List { colors[5] }, + BorderWidth = new List { 0 }, + Stack = "South" + } + } + }; + + barChartOptions = new BarChartOptions + { + Responsive = true, + Interaction = new Interaction { Mode = InteractionMode.Index } + }; + + barChartOptions.Scales.X!.Stacked = true; + barChartOptions.Scales.Y!.Stacked = true; + barChartOptions.Scales.X.Title = new ChartAxesTitle { Text = "Quarter", Display = true }; + barChartOptions.Scales.Y.Title = new ChartAxesTitle { Text = "Revenue (in millions)", Display = true }; + barChartOptions.Plugins.Title!.Text = "Grouped stacked revenue by region"; + barChartOptions.Plugins.Title.Display = true; + } + + protected override async Task OnAfterRenderAsync(bool firstRender) + { + if (firstRender) + await barChart.InitializeAsync(chartData, barChartOptions); + + await base.OnAfterRenderAsync(firstRender); + } +} \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/BarCharts/BarChart_Demo_09_Border_Radius.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/BarCharts/BarChart_Demo_09_Border_Radius.razor new file mode 100644 index 000000000..669425b6e --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/BarCharts/BarChart_Demo_09_Border_Radius.razor @@ -0,0 +1,94 @@ + + +
    + +
    + +@code { + private BarChart barChart = default!; + private BarChartOptions barChartOptions = default!; + private ChartData chartData = default!; + + private int datasetsCount; + private int labelsCount; + private readonly string[] months = { "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" }; + private readonly Random random = new(); + + protected override void OnInitialized() + { + chartData = new ChartData { Labels = GetDefaultDataLabels(6), Datasets = GetDefaultDataSets(3) }; + barChartOptions = new BarChartOptions { Responsive = true, Interaction = new Interaction { Mode = InteractionMode.Index } }; + } + + protected override async Task OnAfterRenderAsync(bool firstRender) + { + if (firstRender) + await barChart.InitializeAsync(chartData, barChartOptions); + + await base.OnAfterRenderAsync(firstRender); + } + + private async Task RandomizeAsync() + { + if (chartData.Datasets is null || !chartData.Datasets.Any()) + return; + + foreach (var dataset in chartData.Datasets.OfType()) + dataset.Data = Enumerable.Range(0, dataset.Data?.Count ?? 0) + .Select(_ => (double?)random.Next(-100, 100)) + .ToList(); + + await barChart.UpdateAsync(chartData, barChartOptions); + } + + private List GetDefaultDataSets(int numberOfDatasets) + { + var datasets = new List(); + + for (var index = 0; index < numberOfDatasets; index++) + datasets.Add(GetRandomBarChartDataset()); + + return datasets; + } + + private BarChartDataset GetRandomBarChartDataset() + { + var color = ColorUtility.CategoricalTwelveColors[datasetsCount].ToChartColor(); + + datasetsCount += 1; + + return new BarChartDataset + { + Label = $"Product {datasetsCount}", + Data = GetRandomData(), + BackgroundColor = new List { color.ToChartRgbaString(0.5) }, + BorderColor = new List { color.ToChartRgbString() }, + BorderWidth = new List { 2 }, + BorderRadius = new List { 10 } + }; + } + + private List GetRandomData() + { + var data = new List(); + for (var index = 0; index < labelsCount; index++) + data.Add(random.Next(-100, 100)); + + return data; + } + + private List GetDefaultDataLabels(int numberOfLabels) + { + var labels = new List(); + for (var index = 0; index < numberOfLabels; index++) + labels.Add(GetNextDataLabel()); + + return labels; + } + + private string GetNextDataLabel() + { + labelsCount += 1; + return months[labelsCount - 1]; + } +} \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/BarCharts/BarChart_Demo_10_Animation_Delay.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/BarCharts/BarChart_Demo_10_Animation_Delay.razor new file mode 100644 index 000000000..cd9a83146 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/BarCharts/BarChart_Demo_10_Animation_Delay.razor @@ -0,0 +1,64 @@ + + +@code { + private BarChart barChart = default!; + private BarChartOptions barChartOptions = default!; + private ChartData chartData = default!; + + protected override void OnInitialized() + { + var colors = ColorUtility.CategoricalTwelveColors; + + chartData = new ChartData + { + Labels = new List { "Chrome", "Firefox", "Safari", "Edge" }, + Datasets = new List + { + new BarChartDataset + { + Label = "Windows", + Data = new List { 28000, 8000, 2000, 17000 }, + BackgroundColor = new List { colors[3] }, + BorderColor = new List { colors[3] }, + BorderWidth = new List { 0 } + }, + new BarChartDataset + { + Label = "macOS", + Data = new List { 8000, 10000, 14000, 8000 }, + BackgroundColor = new List { colors[4] }, + BorderColor = new List { colors[4] }, + BorderWidth = new List { 0 } + }, + new BarChartDataset + { + Label = "Other", + Data = new List { 28000, 10000, 14000, 8000 }, + BackgroundColor = new List { colors[5] }, + BorderColor = new List { colors[5] }, + BorderWidth = new List { 0 } + } + } + }; + + barChartOptions = new(); + barChartOptions.Responsive = true; + barChartOptions.Interaction = new Interaction { Mode = InteractionMode.Y }; + barChartOptions.IndexAxis = "y"; + barChartOptions.Scales.X!.Title = new ChartAxesTitle { Text = "Visitors", Display = true }; + barChartOptions.Scales.Y!.Title = new ChartAxesTitle { Text = "Browser", Display = true }; + barChartOptions.Scales.X.Stacked = true; + barChartOptions.Scales.Y.Stacked = true; + barChartOptions.Plugins.Title!.Text = "Operating system"; + barChartOptions.Plugins.Title.Display = true; + barChartOptions.Animation = new ChartAnimation { Duration = 1000, Delay = 1500 }; + } + + protected override async Task OnAfterRenderAsync(bool firstRender) + { + if (firstRender) + await barChart.InitializeAsync(chartData, barChartOptions); + + await base.OnAfterRenderAsync(firstRender); + } +} \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/BarCharts/BarChart_Demo_11_Combo_Bar_Line.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/BarCharts/BarChart_Demo_11_Combo_Bar_Line.razor new file mode 100644 index 000000000..6bef8dfb5 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/BarCharts/BarChart_Demo_11_Combo_Bar_Line.razor @@ -0,0 +1,52 @@ + + +@code { + private BarChart barChart = default!; + private BarChartOptions barChartOptions = default!; + private ChartData chartData = default!; + + protected override void OnInitialized() + { + var revenueColor = ColorUtility.CategoricalTwelveColors[0].ToChartColor(); + var targetColor = ColorUtility.CategoricalTwelveColors[1].ToChartColor(); + + chartData = new ChartData + { + Labels = new List { "January", "February", "March", "April", "May", "June" }, + Datasets = new List + { + new BarChartDataset + { + Label = "Revenue", + Data = new List { 65, 59, 80, 81, 56, 55 }, + BackgroundColor = new List { revenueColor.ToChartRgbaString() }, + BorderColor = new List { revenueColor.ToChartRgbString() }, + BorderWidth = new List { 0 } + }, + new LineChartDataset + { + Label = "Target", + Data = new List { 50, 55, 60, 70, 72, 78 }, + BackgroundColor = targetColor.ToChartRgbaString(), + BorderColor = targetColor.ToChartRgbString(), + PointRadius = new List { 4 }, + PointHoverRadius = new List { 6 } + } + } + }; + + barChartOptions = new BarChartOptions + { + Responsive = true, + Interaction = new Interaction { Mode = InteractionMode.Index, Intersect = false } + }; + } + + protected override async Task OnAfterRenderAsync(bool firstRender) + { + if (firstRender) + await barChart.InitializeAsync(chartData, barChartOptions); + + await base.OnAfterRenderAsync(firstRender); + } +} \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/BarCharts/BarChart_Demo_12_Click_Event.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/BarCharts/BarChart_Demo_12_Click_Event.razor new file mode 100644 index 000000000..914be216c --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/BarCharts/BarChart_Demo_12_Click_Event.razor @@ -0,0 +1,54 @@ + + +@if (selectedChartItem is not null) +{ +

    + Selected: @selectedChartItem.DatasetLabel (dataset @selectedChartItem.DatasetIndex), + @FormatLabel(selectedChartItem) (index @selectedChartItem.Index), + value @FormatValue(selectedChartItem) +

    +} + +@code { + private BarChart barChart = default!; + private BarChartOptions barChartOptions = default!; + private ChartData chartData = default!; + private ChartClickEventArgs? selectedChartItem; + + protected override void OnInitialized() + { + chartData = new ChartData + { + Labels = new List { "January", "February", "March" }, + Datasets = new List + { + new BarChartDataset + { + Label = "Orders", + Data = new List { 45, 68, 54 }, + BackgroundColor = new List { "#36A2EB" }, + }, + }, + }; + + barChartOptions = new BarChartOptions { Responsive = true }; + } + + protected override async Task OnAfterRenderAsync(bool firstRender) + { + if (firstRender) + await barChart.InitializeAsync(chartData, barChartOptions); + + await base.OnAfterRenderAsync(firstRender); + } + + private Task HandleClickAsync(ChartClickEventArgs eventArgs) + { + selectedChartItem = eventArgs; + return Task.CompletedTask; + } + + private static string FormatLabel(ChartClickEventArgs eventArgs) => eventArgs.Label ?? $"item {eventArgs.Index}"; + + private static string FormatValue(ChartClickEventArgs eventArgs) => eventArgs.Value?.ToString() ?? "null"; +} diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/BubbleCharts/BubbleChartDocumentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/BubbleCharts/BubbleChartDocumentation.razor new file mode 100644 index 000000000..2cd759a66 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/BubbleCharts/BubbleChartDocumentation.razor @@ -0,0 +1,43 @@ +@attribute [Route(pageUrl)] +@layout DemosMainLayout + + + +
    +
    + The bubble chart visualizes three dimensions of data by mapping each point to X, Y, and R values. +
    + + For data visualization, you can use the predefined palettes ColorUtility.CategoricalTwelveColors for a 12-color palette and ColorUtility.CategoricalSixColors for a 6-color palette. + These palettes offer a range of distinct and visually appealing colors that can be applied to represent different categories or data elements in your visualizations. + + +
    + +
    +
    + Set the OnClick callback to react when a bubble is selected. The callback receives ChartClickEventArgs with the dataset, point index, label, and structured raw X, Y, and R value. +
    + +
    + + + + + For a complete charts setup walkthrough, see the + Getting Started — Charts Setup section. + + +@code { + private const string pageUrl = DemoRouteConstants.Demos_URL_BubbleChart; + private const string pageTitle = "Blazor Bubble Chart"; + private const string pageDescription = "A BlazorExpress.ChartJS bubble chart component is used to display three dimensions of data at the same time. The location of the bubble is determined by the first two dimensions and the size of each bubble represents a third value."; + private const string metaTitle = "Blazor Bubble Chart Component"; + private const string metaDescription = "A BlazorExpress.ChartJS bubble chart component is used to display three dimensions of data at the same time. The location of the bubble is determined by the first two dimensions and the size of each bubble represents a third value."; + private const string imageUrl = "https://i.imgur.com/GEox0tS.png"; +} diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/BubbleCharts/BubbleChart_Demo_01_Examples.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/BubbleCharts/BubbleChart_Demo_01_Examples.razor new file mode 100644 index 000000000..90657260e --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/BubbleCharts/BubbleChart_Demo_01_Examples.razor @@ -0,0 +1,137 @@ + + +
    + + + +
    + +@code { + private BubbleChart bubbleChart = default!; + private BubbleChartOptions bubbleChartOptions = default!; + private ChartData chartData = default!; + + private int datasetsCount = 0; + private int labelsCount = 0; + private readonly string[] months = { "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" }; + private readonly Random random = new(); + + protected override void OnInitialized() + { + chartData = new ChartData { Labels = GetDefaultDataLabels(6), Datasets = GetDefaultDataSets(3) }; + bubbleChartOptions = new BubbleChartOptions { Responsive = true }; + } + + protected override async Task OnAfterRenderAsync(bool firstRender) + { + if (firstRender) + await bubbleChart.InitializeAsync(chartData, bubbleChartOptions); + + await base.OnAfterRenderAsync(firstRender); + } + + private async Task RandomizeAsync() + { + if (chartData is null || chartData.Datasets is null || !chartData.Datasets.Any()) + return; + + var newDatasets = new List(); + + foreach (var dataset in chartData.Datasets) + if (dataset is BubbleChartDataset bubbleChartDataset && bubbleChartDataset.Data is not null) + { + var count = bubbleChartDataset.Data.Count; + var newData = new List(); + + for (var i = 0; i < count; i++) + newData.Add(NewBubbleChartDataPoint); + + bubbleChartDataset.Data = newData; + newDatasets.Add(bubbleChartDataset); + } + + chartData.Datasets = newDatasets; + + await bubbleChart.UpdateAsync(chartData, bubbleChartOptions); + } + + private async Task AddDatasetAsync() + { + if (chartData is null || chartData.Datasets is null || datasetsCount >= 12) + return; + + chartData = await bubbleChart.AddDatasetAsync(chartData, GetRandomBubbleChartDataset(), bubbleChartOptions); + } + + private async Task AddDataAsync() + { + if (chartData is null || chartData.Datasets is null || labelsCount >= 12) + return; + + var data = new List(); + + foreach (var dataset in chartData.Datasets) + if (dataset is BubbleChartDataset bubbleChartDataset) + data.Add(new BubbleChartDatasetData(bubbleChartDataset.Label, NewBubbleChartDataPoint)); + + chartData = await bubbleChart.AddDataAsync(chartData, GetNextDataLabel(), data); + } + + #region Data Preparation + + private List GetDefaultDataSets(int numberOfDatasets) + { + var datasets = new List(); + + for (var index = 0; index < numberOfDatasets; index++) + datasets.Add(GetRandomBubbleChartDataset()); + + return datasets; + } + + private BubbleChartDataset GetRandomBubbleChartDataset() + { + var color = ColorUtility.CategoricalTwelveColors[datasetsCount].ToChartColor(); + + datasetsCount += 1; + + return new BubbleChartDataset + { + Label = $"Product {datasetsCount}", + Data = GetRandomData(), + BackgroundColor = new List { color.ToChartRgbString() }, + BorderColor = new List { color.ToChartRgbString() }, + HoverBorderWidth = new List { 4 } + }; + } + + private List GetRandomData() + { + var data = new List(); + + for (var index = 0; index < labelsCount; index++) + data.Add(NewBubbleChartDataPoint); + + return data; + } + + private List GetDefaultDataLabels(int numberOfLabels) + { + var labels = new List(); + + for (var index = 0; index < numberOfLabels; index++) + labels.Add(GetNextDataLabel()); + + return labels; + } + + private string GetNextDataLabel() + { + labelsCount += 1; + return months[labelsCount - 1]; + } + + private BubbleChartDataPoint NewBubbleChartDataPoint => new(random.Next(40), random.Next(40), random.Next(10)); + + #endregion Data Preparation +} \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/BubbleCharts/BubbleChart_Demo_02_Click_Event.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/BubbleCharts/BubbleChart_Demo_02_Click_Event.razor new file mode 100644 index 000000000..ba1ccaff3 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/BubbleCharts/BubbleChart_Demo_02_Click_Event.razor @@ -0,0 +1,61 @@ + + +@if (selectedChartItem is not null) +{ +

    + Selected: @selectedChartItem.DatasetLabel (dataset @selectedChartItem.DatasetIndex), + @FormatLabel(selectedChartItem) (index @selectedChartItem.Index), + value @FormatValue(selectedChartItem) +

    +} + +@code { + private BubbleChart bubbleChart = default!; + private BubbleChartOptions bubbleChartOptions = default!; + private ChartData chartData = default!; + private ChartClickEventArgs? selectedChartItem; + + protected override void OnInitialized() + { + chartData = new ChartData + { + Labels = new List { "January", "February", "March" }, + Datasets = new List + { + new BubbleChartDataset + { + Label = "Projects", + Data = new List + { + new(10, 20, 8), + new(15, 12, 12), + new(8, 25, 6), + }, + BackgroundColor = new List { "rgba(255, 99, 132, 0.5)" }, + BorderColor = new List { "rgb(255, 99, 132)" }, + BorderWidth = 1, + }, + }, + }; + + bubbleChartOptions = new BubbleChartOptions { Responsive = true }; + } + + protected override async Task OnAfterRenderAsync(bool firstRender) + { + if (firstRender) + await bubbleChart.InitializeAsync(chartData, bubbleChartOptions); + + await base.OnAfterRenderAsync(firstRender); + } + + private Task HandleClickAsync(ChartClickEventArgs eventArgs) + { + selectedChartItem = eventArgs; + return Task.CompletedTask; + } + + private static string FormatLabel(ChartClickEventArgs eventArgs) => eventArgs.Label ?? $"item {eventArgs.Index}"; + + private static string FormatValue(ChartClickEventArgs eventArgs) => eventArgs.Value?.ToString() ?? "null"; +} diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/ChartColorExtensions.cs b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/ChartColorExtensions.cs new file mode 100644 index 000000000..e61af4b1e --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/ChartColorExtensions.cs @@ -0,0 +1,14 @@ +namespace BlazorBootstrap.Demo.RCL.Components.Pages.Demos.Charts; + +internal static class ChartColorExtensions +{ + internal static System.Drawing.Color ToChartColor(this string value) => BlazorExpress.ChartJS.ColorExtensions.ToColor(value); + + internal static string ToChartHexString(this System.Drawing.Color value) => BlazorExpress.ChartJS.ColorExtensions.ToHexString(value); + + internal static string ToChartHexaString(this System.Drawing.Color value) => BlazorExpress.ChartJS.ColorExtensions.ToHexaString(value); + + internal static string ToChartRgbString(this System.Drawing.Color value) => BlazorExpress.ChartJS.ColorExtensions.ToRgbString(value); + + internal static string ToChartRgbaString(this System.Drawing.Color value, double alpha = 0.2) => BlazorExpress.ChartJS.ColorExtensions.ToRgbaString(value, alpha); +} \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/ChartsDocumentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/ChartsDocumentation.razor new file mode 100644 index 000000000..6f0201ee9 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/ChartsDocumentation.razor @@ -0,0 +1,47 @@ +@attribute [Route(pageUrl)] +@layout DemosMainLayout + + + +
    + +
    + +
    +
    At this moment we are supporting eight blazor chart types.
    +
      +
    1. Bar Chart
    2. +
    3. Bubble Chart
    4. +
    5. Doughnut Chart
    6. +
    7. Line Chart
    8. +
    9. Pie Chart
    10. +
    11. Polar Area Chart
    12. +
    13. Radar Chart
    14. +
    15. Scatter Chart
    16. +
    + + + BarChart and LineChart now support mixed bar/line datasets, and BubbleChart is available alongside the rest of the chart gallery. + +
    + + + + + For a complete charts setup walkthrough, see the + Getting Started — Charts Setup section. + + +@code { + private const string pageUrl = DemoRouteConstants.Demos_URL_Charts; + private const string pageTitle = "Blazor Charts"; + private const string pageDescription = "BlazorExpress.ChartJS provides chart components on top of Chart.js to visualize data. It contains a rich UI gallery of charts that cater to all charting scenarios. Its high performance helps render large amounts of data quickly."; + private const string metaTitle = "Blazor Chart Components"; + private const string metaDescription = "BlazorExpress.ChartJS provides chart components on top of Chart.js to visualize data. It contains a rich UI gallery of charts that cater to all charting scenarios. Its high performance helps render large amounts of data quickly."; + private const string imageUrl = "https://i.imgur.com/IX3bajc.png"; +} diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Charts/Charts_Demo_00_Examples.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/Charts_Demo_00_Examples.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Charts/Charts_Demo_00_Examples.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/Charts_Demo_00_Examples.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/DoughnutCharts/DoughnutChartDocumentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/DoughnutCharts/DoughnutChartDocumentation.razor new file mode 100644 index 000000000..fdb4385d9 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/DoughnutCharts/DoughnutChartDocumentation.razor @@ -0,0 +1,47 @@ +@attribute [Route(pageUrl)] +@layout DemosMainLayout + + + +
    +
    + In the following example, a categorical 12-color palette is used. +
    + + For data visualization, you can use the predefined palettes ColorUtility.CategoricalTwelveColors for a 12-color palette and ColorUtility.CategoricalSixColors for a 6-color palette. + These palettes offer a range of distinct and visually appealing colors that can be applied to represent different categories or data elements in your visualizations. + + +
    + +
    + +
    + +
    +
    + Set the OnClick callback to react when a doughnut segment is selected. The callback receives ChartClickEventArgs with the dataset, item index, label, and raw value. +
    + +
    + + + + + For a complete charts setup walkthrough, see the + Getting Started — Charts Setup section. + + +@code { + private const string pageUrl = DemoRouteConstants.Demos_URL_DoughnutChart; + private const string pageTitle = "Blazor Doughnut Chart"; + private const string pageDescription = "A BlazorExpress.ChartJS doughnut chart component is a circular chart that shows the proportional values of different categories. It is similar to a pie chart, but the center of the doughnut chart is hollow. This makes it easier to see the individual values of each category."; + private const string metaTitle = "Blazor Doughnut Chart Component"; + private const string metaDescription = "A BlazorExpress.ChartJS doughnut chart component is a circular chart that shows the proportional values of different categories. It is similar to a pie chart, but the center of the doughnut chart is hollow. This makes it easier to see the individual values of each category."; + private const string imageUrl = "https://i.imgur.com/xEPhAsW.png"; +} diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Charts/DoughnutCharts/DoughnutChart_Demo_01_Examples.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/DoughnutCharts/DoughnutChart_Demo_01_Examples.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Charts/DoughnutCharts/DoughnutChart_Demo_01_Examples.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/DoughnutCharts/DoughnutChart_Demo_01_Examples.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Charts/DoughnutCharts/DoughnutChart_Demo_02_Datalabels.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/DoughnutCharts/DoughnutChart_Demo_02_Datalabels.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Charts/DoughnutCharts/DoughnutChart_Demo_02_Datalabels.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/DoughnutCharts/DoughnutChart_Demo_02_Datalabels.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/DoughnutCharts/DoughnutChart_Demo_03_Click_Event.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/DoughnutCharts/DoughnutChart_Demo_03_Click_Event.razor new file mode 100644 index 000000000..fe0a70c20 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/DoughnutCharts/DoughnutChart_Demo_03_Click_Event.razor @@ -0,0 +1,54 @@ + + +@if (selectedChartItem is not null) +{ +

    + Selected: @selectedChartItem.DatasetLabel (dataset @selectedChartItem.DatasetIndex), + @FormatLabel(selectedChartItem) (index @selectedChartItem.Index), + value @FormatValue(selectedChartItem) +

    +} + +@code { + private DoughnutChart doughnutChart = default!; + private DoughnutChartOptions doughnutChartOptions = default!; + private ChartData chartData = default!; + private ChartClickEventArgs? selectedChartItem; + + protected override void OnInitialized() + { + chartData = new ChartData + { + Labels = new List { "Direct", "Referral", "Social" }, + Datasets = new List + { + new DoughnutChartDataset + { + Label = "Visitors", + Data = new List { 55, 30, 15 }, + BackgroundColor = new List { "#36A2EB", "#FF6384", "#FFCE56" }, + }, + }, + }; + + doughnutChartOptions = new DoughnutChartOptions { Responsive = true }; + } + + protected override async Task OnAfterRenderAsync(bool firstRender) + { + if (firstRender) + await doughnutChart.InitializeAsync(chartData, doughnutChartOptions); + + await base.OnAfterRenderAsync(firstRender); + } + + private Task HandleClickAsync(ChartClickEventArgs eventArgs) + { + selectedChartItem = eventArgs; + return Task.CompletedTask; + } + + private static string FormatLabel(ChartClickEventArgs eventArgs) => eventArgs.Label ?? $"item {eventArgs.Index}"; + + private static string FormatValue(ChartClickEventArgs eventArgs) => eventArgs.Value?.ToString() ?? "null"; +} diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/LineCharts/LineChartDocumentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/LineCharts/LineChartDocumentation.razor new file mode 100644 index 000000000..dc78aa70b --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/LineCharts/LineChartDocumentation.razor @@ -0,0 +1,83 @@ +@attribute [Route(pageUrl)] +@layout DemosMainLayout + + + +
    +
    + In the following example, a categorical 12-color palette is used. +
    + + For data visualization, you can use the predefined palettes ColorUtility.CategoricalTwelveColors for a 12-color palette and ColorUtility.CategoricalSixColors for a 6-color palette. + These palettes offer a range of distinct and visually appealing colors that can be applied to represent different categories or data elements in your visualizations. + + +
    + +
    + +
    +
    + By default, the chart is using the default locale of the platform on which it is running. + In the following example, you will see the chart in the German locale (de_DE). +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    +
    + Compare monotone cubic interpolation, regular cubic interpolation, and the default linear rendering to control how line segments are smoothed. +
    + +
    + +
    + +
    + +
    +
    + Combine LineChartDataset and BarChartDataset in a single line chart to compare forecast and actual values. +
    + +
    + +
    +
    + Set the OnClick callback to react when a line data point is selected. The callback receives ChartClickEventArgs with the dataset, point index, label, and raw value. +
    + +
    + + + + + For a complete charts setup walkthrough, see the + Getting Started — Charts Setup section. + + +@code { + private const string pageUrl = DemoRouteConstants.Demos_URL_LineChart; + private const string pageTitle = "Blazor Line Chart"; + private const string pageDescription = "A BlazorExpress.ChartJS line chart component is a graphical representation of data that uses a series of connected points to show how the data changes over time. It is a type of x-y chart, where the x-axis represents the independent variable, such as time, and the y-axis represents the dependent variable, such as the value."; + private const string metaTitle = "Blazor Line Chart Component"; + private const string metaDescription = "A BlazorExpress.ChartJS line chart component is a graphical representation of data that uses a series of connected points to show how the data changes over time. It is a type of x-y chart, where the x-axis represents the independent variable, such as time, and the y-axis represents the dependent variable, such as the value."; + private const string imageUrl = "https://i.imgur.com/8b7jH0D.png"; +} diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Charts/LineCharts/LineChart_Demo_01_A_Examples.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/LineCharts/LineChart_Demo_01_A_Examples.razor similarity index 95% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Charts/LineCharts/LineChart_Demo_01_A_Examples.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/LineCharts/LineChart_Demo_01_A_Examples.razor index 6a6e950d5..aac4861f0 100644 --- a/BlazorBootstrap.Demo.RCL/Components/Pages/Charts/LineCharts/LineChart_Demo_01_A_Examples.razor +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/LineCharts/LineChart_Demo_01_A_Examples.razor @@ -1,4 +1,4 @@ -
    +
    @@ -67,7 +67,7 @@ chartData.Datasets = newDatasets; - await lineChart.UpdateValuesAsync(chartData); + await lineChart.UpdateAsync(chartData, lineChartOptions); } private async Task AddDatasetAsync() @@ -121,7 +121,7 @@ private LineChartDataset GetRandomLineChartDataset() { - var c = ColorUtility.CategoricalTwelveColors[datasetsCount].ToColor(); + var c = ColorUtility.CategoricalTwelveColors[datasetsCount].ToChartColor(); datasetsCount += 1; @@ -129,8 +129,8 @@ { Label = $"Team {datasetsCount}", Data = GetRandomData(), - BackgroundColor = c.ToRgbaString(), - BorderColor = c.ToRgbString(), + BackgroundColor = c.ToChartRgbaString(), + BorderColor = c.ToChartRgbString(), PointRadius = new List { 5 }, PointHoverRadius = new List { 8 }, }; diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Charts/LineCharts/LineChart_Demo_01_B_Examples.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/LineCharts/LineChart_Demo_01_B_Examples.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Charts/LineCharts/LineChart_Demo_01_B_Examples.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/LineCharts/LineChart_Demo_01_B_Examples.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Charts/LineCharts/LineChart_Demo_02_Locale.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/LineCharts/LineChart_Demo_02_Locale.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Charts/LineCharts/LineChart_Demo_02_Locale.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/LineCharts/LineChart_Demo_02_Locale.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Charts/LineCharts/LineChart_Demo_03_Dynamically_add_data.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/LineCharts/LineChart_Demo_03_Dynamically_add_data.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Charts/LineCharts/LineChart_Demo_03_Dynamically_add_data.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/LineCharts/LineChart_Demo_03_Dynamically_add_data.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Charts/LineCharts/LineChart_Demo_04_Datalabels.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/LineCharts/LineChart_Demo_04_Datalabels.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Charts/LineCharts/LineChart_Demo_04_Datalabels.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/LineCharts/LineChart_Demo_04_Datalabels.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Charts/LineCharts/LineChart_Demo_05_Tick_Configuration.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/LineCharts/LineChart_Demo_05_Tick_Configuration.razor similarity index 94% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Charts/LineCharts/LineChart_Demo_05_Tick_Configuration.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/LineCharts/LineChart_Demo_05_Tick_Configuration.razor index 1a9cbb827..44c157cc3 100644 --- a/BlazorBootstrap.Demo.RCL/Components/Pages/Charts/LineCharts/LineChart_Demo_05_Tick_Configuration.razor +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/LineCharts/LineChart_Demo_05_Tick_Configuration.razor @@ -1,4 +1,4 @@ -
    +
    @@ -71,7 +71,7 @@ private LineChartDataset GetRandomLineChartDataset() { - var c = ColorUtility.CategoricalTwelveColors[datasetsCount].ToColor(); + var c = ColorUtility.CategoricalTwelveColors[datasetsCount].ToChartColor(); datasetsCount += 1; @@ -79,11 +79,11 @@ { Label = $"Team {datasetsCount}", Data = GetRandomData(), - BackgroundColor = c.ToRgbString(), - BorderColor = c.ToRgbString(), + BackgroundColor = c.ToChartRgbString(), + BorderColor = c.ToChartRgbString(), BorderWidth = 2, HoverBorderWidth = 4, - // PointBackgroundColor = c.ToRgbString(), + // PointBackgroundColor = c.ToChartRgbString(), // PointRadius = 0, // hide points // PointHoverRadius = 4, }; diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Charts/LineCharts/LineChart_Demo_06_Dataset_Fill.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/LineCharts/LineChart_Demo_06_Dataset_Fill.razor similarity index 96% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Charts/LineCharts/LineChart_Demo_06_Dataset_Fill.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/LineCharts/LineChart_Demo_06_Dataset_Fill.razor index 7c91693f1..4557061ec 100644 --- a/BlazorBootstrap.Demo.RCL/Components/Pages/Charts/LineCharts/LineChart_Demo_06_Dataset_Fill.razor +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/LineCharts/LineChart_Demo_06_Dataset_Fill.razor @@ -1,4 +1,4 @@ - +
    @@ -102,7 +102,7 @@ private LineChartDataset GetRandomLineChartDataset() { - var c = ColorUtility.CategoricalTwelveColors[datasetsCount].ToColor(); + var c = ColorUtility.CategoricalTwelveColors[datasetsCount].ToChartColor(); datasetsCount += 1; @@ -110,12 +110,12 @@ { Label = $"Team {datasetsCount}", Data = GetRandomData(), - BackgroundColor = c.ToRgbaString(), + BackgroundColor = c.ToChartRgbaString(), BorderCapStyle = "round", - BorderColor = c.ToRgbString(), + BorderColor = c.ToChartRgbString(), BorderWidth = 2, HoverBorderWidth = 4, - PointBackgroundColor = new List() { c.ToRgbString() }, + PointBackgroundColor = new List() { c.ToChartRgbString() }, // PointRadius = 0, // hide points PointHoverRadius = new List() { 4 }, }; diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/LineCharts/LineChart_Demo_08_Interpolation_Modes.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/LineCharts/LineChart_Demo_08_Interpolation_Modes.razor new file mode 100644 index 000000000..cf0609111 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/LineCharts/LineChart_Demo_08_Interpolation_Modes.razor @@ -0,0 +1,72 @@ +
    + +
    + +@code { + private LineChart lineChart = default!; + private LineChartOptions lineChartOptions = default!; + private ChartData chartData = default!; + + private readonly int dataCount = 13; + private readonly List dataPoints = new() { 0, 20, 20, 60, 60, 120, null, 180, 120, 125, 105, 110, 170 }; + + protected override void OnInitialized() + { + chartData = new ChartData { Labels = GetDefaultDataLabels(), Datasets = GetDefaultDataSets() }; + lineChartOptions = new LineChartOptions + { + IndexAxis = "x", + Interaction = new Interaction { Mode = InteractionMode.Index, Intersect = false }, + Responsive = true + }; + } + + protected override async Task OnAfterRenderAsync(bool firstRender) + { + if (firstRender) + await lineChart.InitializeAsync(chartData, lineChartOptions); + + await base.OnAfterRenderAsync(firstRender); + } + + private List GetDefaultDataLabels() + { + var labels = new List(); + + for (var index = 0; index < dataCount; index++) + labels.Add(index.ToString()); + + return labels; + } + + private List GetDefaultDataSets() + { + return new List + { + new LineChartDataset + { + Label = "Cubic interpolation (monotone)", + Data = dataPoints, + BorderColor = ColorUtility.CategoricalSixColors[0].ToChartColor().ToChartRgbString(), + CubicInterpolationMode = "monotone", + Fill = false, + Tension = 0.4 + }, + new LineChartDataset + { + Label = "Cubic interpolation", + Data = dataPoints, + BorderColor = ColorUtility.CategoricalSixColors[1].ToChartColor().ToChartRgbString(), + Fill = false, + Tension = 0.4 + }, + new LineChartDataset + { + Label = "Linear interpolation (default)", + Data = dataPoints, + BorderColor = ColorUtility.CategoricalSixColors[2].ToChartColor().ToChartRgbString(), + Fill = false + } + }; + } +} \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/LineCharts/LineChart_Demo_09_Combo_Bar_Line.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/LineCharts/LineChart_Demo_09_Combo_Bar_Line.razor new file mode 100644 index 000000000..585300c0a --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/LineCharts/LineChart_Demo_09_Combo_Bar_Line.razor @@ -0,0 +1,54 @@ +
    + +
    + +@code { + private LineChart lineChart = default!; + private LineChartOptions lineChartOptions = default!; + private ChartData chartData = default!; + + protected override void OnInitialized() + { + var forecastColor = ColorUtility.CategoricalTwelveColors[2].ToChartColor(); + var actualColor = ColorUtility.CategoricalTwelveColors[3].ToChartColor(); + + chartData = new ChartData + { + Labels = new List { "January", "February", "March", "April", "May", "June" }, + Datasets = new List + { + new LineChartDataset + { + Label = "Forecast", + Data = new List { 45, 52, 61, 66, 73, 79 }, + BackgroundColor = forecastColor.ToChartRgbaString(), + BorderColor = forecastColor.ToChartRgbString(), + PointRadius = new List { 4 }, + PointHoverRadius = new List { 6 } + }, + new BarChartDataset + { + Label = "Actual", + Data = new List { 41, 49, 58, 70, 75, 82 }, + BackgroundColor = new List { actualColor.ToChartRgbaString() }, + BorderColor = new List { actualColor.ToChartRgbString() }, + BorderWidth = new List { 0 } + } + } + }; + + lineChartOptions = new LineChartOptions + { + Responsive = true, + Interaction = new Interaction { Mode = InteractionMode.Index, Intersect = false } + }; + } + + protected override async Task OnAfterRenderAsync(bool firstRender) + { + if (firstRender) + await lineChart.InitializeAsync(chartData, lineChartOptions); + + await base.OnAfterRenderAsync(firstRender); + } +} \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/LineCharts/LineChart_Demo_10_Click_Event.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/LineCharts/LineChart_Demo_10_Click_Event.razor new file mode 100644 index 000000000..8f7adc16d --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/LineCharts/LineChart_Demo_10_Click_Event.razor @@ -0,0 +1,57 @@ + + +@if (selectedChartItem is not null) +{ +

    + Selected: @selectedChartItem.DatasetLabel (dataset @selectedChartItem.DatasetIndex), + @FormatLabel(selectedChartItem) (index @selectedChartItem.Index), + value @FormatValue(selectedChartItem) +

    +} + +@code { + private LineChart lineChart = default!; + private LineChartOptions lineChartOptions = default!; + private ChartData chartData = default!; + private ChartClickEventArgs? selectedChartItem; + + protected override void OnInitialized() + { + chartData = new ChartData + { + Labels = new List { "Monday", "Tuesday", "Wednesday", "Thursday" }, + Datasets = new List + { + new LineChartDataset + { + Label = "Visitors", + Data = new List { 120, 190, 150, 230 }, + BackgroundColor = "rgba(54, 162, 235, 0.2)", + BorderColor = "rgb(54, 162, 235)", + PointRadius = new List { 5 }, + PointHoverRadius = new List { 8 }, + }, + }, + }; + + lineChartOptions = new LineChartOptions { Responsive = true }; + } + + protected override async Task OnAfterRenderAsync(bool firstRender) + { + if (firstRender) + await lineChart.InitializeAsync(chartData, lineChartOptions); + + await base.OnAfterRenderAsync(firstRender); + } + + private Task HandleClickAsync(ChartClickEventArgs eventArgs) + { + selectedChartItem = eventArgs; + return Task.CompletedTask; + } + + private static string FormatLabel(ChartClickEventArgs eventArgs) => eventArgs.Label ?? $"item {eventArgs.Index}"; + + private static string FormatValue(ChartClickEventArgs eventArgs) => eventArgs.Value?.ToString() ?? "null"; +} diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Charts/PieCharts/PieChartDocumentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/PieCharts/PieChartDocumentation.razor similarity index 52% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Charts/PieCharts/PieChartDocumentation.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/PieCharts/PieChartDocumentation.razor index 3434be298..fe68bf589 100644 --- a/BlazorBootstrap.Demo.RCL/Components/Pages/Charts/PieCharts/PieChartDocumentation.razor +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/PieCharts/PieChartDocumentation.razor @@ -1,21 +1,12 @@ @attribute [Route(pageUrl)] +@layout DemosMainLayout - - - - @pageDescription - - - - -
    -
    - Refer to the getting started guide for setting up charts. -
    -
    +
    @@ -39,11 +30,25 @@
    +
    +
    + Set the OnClick callback to react when a pie slice is selected. The callback receives ChartClickEventArgs with the dataset, item index, label, and raw value. +
    + +
    + + + + + For a complete charts setup walkthrough, see the + Getting Started — Charts Setup section. + + @code { - private const string pageUrl = RouteConstants.Demos_PieChart_Documentation; + private const string pageUrl = DemoRouteConstants.Demos_URL_PieChart; private const string pageTitle = "Blazor Pie Chart"; - private const string pageDescription = "A Blazor Bootstrap pie chart component is a circular chart that shows the proportional values of different categories."; + private const string pageDescription = "A BlazorExpress.ChartJS pie chart component is a circular chart that shows the proportional values of different categories."; private const string metaTitle = "Blazor Pie Chart"; - private const string metaDescription = "A Blazor Bootstrap pie chart component is a circular chart that shows the proportional values of different categories."; + private const string metaDescription = "A BlazorExpress.ChartJS pie chart component is a circular chart that shows the proportional values of different categories."; private const string imageUrl = "https://i.imgur.com/ieBupT2.png"; } diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Charts/PieCharts/PieChart_Demo_01_Examples.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/PieCharts/PieChart_Demo_01_Examples.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Charts/PieCharts/PieChart_Demo_01_Examples.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/PieCharts/PieChart_Demo_01_Examples.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Charts/PieCharts/PieChart_Demo_02_Datalabels.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/PieCharts/PieChart_Demo_02_Datalabels.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Charts/PieCharts/PieChart_Demo_02_Datalabels.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/PieCharts/PieChart_Demo_02_Datalabels.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Charts/PieCharts/PieChart_Demo_03_Change_Legend_Position.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/PieCharts/PieChart_Demo_03_Change_Legend_Position.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Charts/PieCharts/PieChart_Demo_03_Change_Legend_Position.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/PieCharts/PieChart_Demo_03_Change_Legend_Position.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/PieCharts/PieChart_Demo_04_Click_Event.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/PieCharts/PieChart_Demo_04_Click_Event.razor new file mode 100644 index 000000000..54448bb79 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/PieCharts/PieChart_Demo_04_Click_Event.razor @@ -0,0 +1,54 @@ + + +@if (selectedChartItem is not null) +{ +

    + Selected: @selectedChartItem.DatasetLabel (dataset @selectedChartItem.DatasetIndex), + @FormatLabel(selectedChartItem) (index @selectedChartItem.Index), + value @FormatValue(selectedChartItem) +

    +} + +@code { + private PieChart pieChart = default!; + private PieChartOptions pieChartOptions = default!; + private ChartData chartData = default!; + private ChartClickEventArgs? selectedChartItem; + + protected override void OnInitialized() + { + chartData = new ChartData + { + Labels = new List { "Desktop", "Tablet", "Mobile" }, + Datasets = new List + { + new PieChartDataset + { + Label = "Sessions", + Data = new List { 62, 18, 20 }, + BackgroundColor = new List { "#4BC0C0", "#9966FF", "#FF9F40" }, + }, + }, + }; + + pieChartOptions = new PieChartOptions { Responsive = true }; + } + + protected override async Task OnAfterRenderAsync(bool firstRender) + { + if (firstRender) + await pieChart.InitializeAsync(chartData, pieChartOptions); + + await base.OnAfterRenderAsync(firstRender); + } + + private Task HandleClickAsync(ChartClickEventArgs eventArgs) + { + selectedChartItem = eventArgs; + return Task.CompletedTask; + } + + private static string FormatLabel(ChartClickEventArgs eventArgs) => eventArgs.Label ?? $"item {eventArgs.Index}"; + + private static string FormatValue(ChartClickEventArgs eventArgs) => eventArgs.Value?.ToString() ?? "null"; +} diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/PolarAreaCharts/PolarAreaChartDocumentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/PolarAreaCharts/PolarAreaChartDocumentation.razor new file mode 100644 index 000000000..9b38ee347 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/PolarAreaCharts/PolarAreaChartDocumentation.razor @@ -0,0 +1,43 @@ +@attribute [Route(pageUrl)] +@layout DemosMainLayout + + + +
    +
    + In the following example, a categorical 12-color palette is used. +
    + + For data visualization, you can use the predefined palettes ColorUtility.CategoricalTwelveColors for a 12-color palette and ColorUtility.CategoricalSixColors for a 6-color palette. + These palettes offer a range of distinct and visually appealing colors that can be applied to represent different categories or data elements in your visualizations. + + +
    + +
    +
    + Set the OnClick callback to react when a polar-area segment is selected. The callback receives ChartClickEventArgs with the dataset, item index, label, and raw value. +
    + +
    + + + + + For a complete charts setup walkthrough, see the + Getting Started — Charts Setup section. + + +@code { + private const string pageUrl = DemoRouteConstants.Demos_URL_PolarAreaChart; + private const string pageTitle = "Blazor Polar Area Chart"; + private const string pageDescription = "BlazorExpress.ChartJS polar area charts are similar to pie charts, but each segment has the same angle - the radius of the segment differs depending on the value."; + private const string metaTitle = "Blazor Polar Area Chart Component"; + private const string metaDescription = "BlazorExpress.ChartJS polar area charts are similar to pie charts, but each segment has the same angle - the radius of the segment differs depending on the value."; + private const string imageUrl = "https://i.imgur.com/xLAqwGi.png"; +} diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Charts/PolarAreaCharts/PolarAreaChart_Demo_01_Examples.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/PolarAreaCharts/PolarAreaChart_Demo_01_Examples.razor similarity index 94% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Charts/PolarAreaCharts/PolarAreaChart_Demo_01_Examples.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/PolarAreaCharts/PolarAreaChart_Demo_01_Examples.razor index 73a2e2f6f..9dc95bf38 100644 --- a/BlazorBootstrap.Demo.RCL/Components/Pages/Charts/PolarAreaCharts/PolarAreaChart_Demo_01_Examples.razor +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/PolarAreaCharts/PolarAreaChart_Demo_01_Examples.razor @@ -1,4 +1,4 @@ - +
    @@ -59,7 +59,7 @@ var backgroundColors = new List(); for (var index = 0; index < count; index++) { - backgroundColors.Add(chartColors![index].ToColor().ToRgbaString(0.5)); // RGBA + backgroundColors.Add(chartColors![index].ToChartColor().ToChartRgbaString(0.5)); // RGBA } polarAreaChartDataset.Data = newData; @@ -95,7 +95,7 @@ foreach (var dataset in chartData.Datasets) { if (dataset is PolarAreaChartDataset polarAreaChartDataset) - data.Add(new PolarAreaChartDatasetData(polarAreaChartDataset.Label, random.Next(0, 100), chartColors![dataLabelsCount - 1].ToColor().ToRgbaString(0.5), null)); + data.Add(new PolarAreaChartDatasetData(polarAreaChartDataset.Label, random.Next(0, 100), chartColors![dataLabelsCount - 1].ToChartColor().ToChartRgbaString(0.5), null)); } chartData = await polarAreaChart.AddDataAsync(chartData, GetNextDataLabel(), data); @@ -156,7 +156,7 @@ var colors = new List(); for (var index = 0; index < dataLabelsCount; index++) { - colors.Add(chartColors![index].ToColor().ToRgbaString(0.5)); // RGBA + colors.Add(chartColors![index].ToChartColor().ToChartRgbaString(0.5)); // RGBA } return colors; @@ -167,7 +167,7 @@ var colors = new List(); for (var index = 0; index < dataLabelsCount; index++) { - colors.Add(chartColors![index].ToColor().ToRgbString()); // RGB + colors.Add(chartColors![index].ToChartColor().ToChartRgbString()); // RGB } return colors; diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/PolarAreaCharts/PolarAreaChart_Demo_02_Click_Event.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/PolarAreaCharts/PolarAreaChart_Demo_02_Click_Event.razor new file mode 100644 index 000000000..dc6df8745 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/PolarAreaCharts/PolarAreaChart_Demo_02_Click_Event.razor @@ -0,0 +1,60 @@ + + +@if (selectedChartItem is not null) +{ +

    + Selected: @selectedChartItem.DatasetLabel (dataset @selectedChartItem.DatasetIndex), + @FormatLabel(selectedChartItem) (index @selectedChartItem.Index), + value @FormatValue(selectedChartItem) +

    +} + +@code { + private PolarAreaChart polarAreaChart = default!; + private PolarAreaChartOptions polarAreaChartOptions = default!; + private ChartData chartData = default!; + private ChartClickEventArgs? selectedChartItem; + + protected override void OnInitialized() + { + chartData = new ChartData + { + Labels = new List { "North", "South", "East", "West" }, + Datasets = new List + { + new PolarAreaChartDataset + { + Label = "Sales", + Data = new List { 35, 55, 40, 25 }, + BackgroundColor = new List + { + "rgba(255, 99, 132, 0.5)", + "rgba(54, 162, 235, 0.5)", + "rgba(255, 206, 86, 0.5)", + "rgba(75, 192, 192, 0.5)", + }, + }, + }, + }; + + polarAreaChartOptions = new PolarAreaChartOptions { Responsive = true }; + } + + protected override async Task OnAfterRenderAsync(bool firstRender) + { + if (firstRender) + await polarAreaChart.InitializeAsync(chartData, polarAreaChartOptions); + + await base.OnAfterRenderAsync(firstRender); + } + + private Task HandleClickAsync(ChartClickEventArgs eventArgs) + { + selectedChartItem = eventArgs; + return Task.CompletedTask; + } + + private static string FormatLabel(ChartClickEventArgs eventArgs) => eventArgs.Label ?? $"item {eventArgs.Index}"; + + private static string FormatValue(ChartClickEventArgs eventArgs) => eventArgs.Value?.ToString() ?? "null"; +} diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/RadarCharts/RadarChartDocumentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/RadarCharts/RadarChartDocumentation.razor new file mode 100644 index 000000000..34776e8d1 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/RadarCharts/RadarChartDocumentation.razor @@ -0,0 +1,43 @@ +@attribute [Route(pageUrl)] +@layout DemosMainLayout + + + +
    +
    + In the following example, a categorical 12-color palette is used. +
    + + For data visualization, you can use the predefined palettes ColorUtility.CategoricalTwelveColors for a 12-color palette and ColorUtility.CategoricalSixColors for a 6-color palette. + These palettes offer a range of distinct and visually appealing colors that can be applied to represent different categories or data elements in your visualizations. + + +
    + +
    +
    + Set the OnClick callback to react when a radar data point is selected. The callback receives ChartClickEventArgs with the dataset, point index, label, and raw value. +
    + +
    + + + + + For a complete charts setup walkthrough, see the + Getting Started — Charts Setup section. + + +@code { + private const string pageUrl = DemoRouteConstants.Demos_URL_RadarChart; + private const string pageTitle = "Blazor Radar Chart"; + private const string pageDescription = "A BlazorExpress.ChartJS radar chart component is a way of showing multiple data points and the variation between them. They are often useful for comparing the points of two or more different data sets."; + private const string metaTitle = "Blazor Radar Chart Component"; + private const string metaDescription = "A BlazorExpress.ChartJS radar chart component is a way of showing multiple data points and the variation between them. They are often useful for comparing the points of two or more different data sets."; + private const string imageUrl = "https://i.imgur.com/Urrb79M.png"; +} diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Charts/RadarCharts/RadarChart_Demo_01_Examples.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/RadarCharts/RadarChart_Demo_01_Examples.razor similarity index 95% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Charts/RadarCharts/RadarChart_Demo_01_Examples.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/RadarCharts/RadarChart_Demo_01_Examples.razor index a4de5e1a6..34926e6dd 100644 --- a/BlazorBootstrap.Demo.RCL/Components/Pages/Charts/RadarCharts/RadarChart_Demo_01_Examples.razor +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/RadarCharts/RadarChart_Demo_01_Examples.razor @@ -1,4 +1,4 @@ - +
    @@ -124,7 +124,7 @@ private RadarChartDataset GetRandomRadarChartDataset() { - var c = chartColors![datasetsCount].ToColor(); + var c = chartColors![datasetsCount].ToChartColor(); datasetsCount += 1; @@ -132,8 +132,8 @@ { Label = $"Team {datasetsCount}", Data = GetRandomData(), - BackgroundColor = c.ToRgbaString(), - BorderColor = c.ToRgbaString(0.8), + BackgroundColor = c.ToChartRgbaString(), + BorderColor = c.ToChartRgbaString(0.8), BorderWidth = 2, Fill = true, HoverBorderWidth = 4, diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/RadarCharts/RadarChart_Demo_02_Click_Event.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/RadarCharts/RadarChart_Demo_02_Click_Event.razor new file mode 100644 index 000000000..4b58bd8a9 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/RadarCharts/RadarChart_Demo_02_Click_Event.razor @@ -0,0 +1,57 @@ + + +@if (selectedChartItem is not null) +{ +

    + Selected: @selectedChartItem.DatasetLabel (dataset @selectedChartItem.DatasetIndex), + @FormatLabel(selectedChartItem) (index @selectedChartItem.Index), + value @FormatValue(selectedChartItem) +

    +} + +@code { + private RadarChart radarChart = default!; + private RadarChartOptions radarChartOptions = default!; + private ChartData chartData = default!; + private ChartClickEventArgs? selectedChartItem; + + protected override void OnInitialized() + { + chartData = new ChartData + { + Labels = new List { "Speed", "Reliability", "Comfort", "Safety", "Efficiency" }, + Datasets = new List + { + new RadarChartDataset + { + Label = "Vehicle A", + Data = new List { 80, 72, 65, 90, 78 }, + BackgroundColor = "rgba(153, 102, 255, 0.2)", + BorderColor = "rgba(153, 102, 255, 0.8)", + BorderWidth = 2, + Fill = true, + }, + }, + }; + + radarChartOptions = new RadarChartOptions { Responsive = true }; + } + + protected override async Task OnAfterRenderAsync(bool firstRender) + { + if (firstRender) + await radarChart.InitializeAsync(chartData, radarChartOptions); + + await base.OnAfterRenderAsync(firstRender); + } + + private Task HandleClickAsync(ChartClickEventArgs eventArgs) + { + selectedChartItem = eventArgs; + return Task.CompletedTask; + } + + private static string FormatLabel(ChartClickEventArgs eventArgs) => eventArgs.Label ?? $"item {eventArgs.Index}"; + + private static string FormatValue(ChartClickEventArgs eventArgs) => eventArgs.Value?.ToString() ?? "null"; +} diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Charts/ScatterCharts/ScatterChartDocumentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/ScatterCharts/ScatterChartDocumentation.razor similarity index 51% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Charts/ScatterCharts/ScatterChartDocumentation.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/ScatterCharts/ScatterChartDocumentation.razor index 737a05ce0..3169140c9 100644 --- a/BlazorBootstrap.Demo.RCL/Components/Pages/Charts/ScatterCharts/ScatterChartDocumentation.razor +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/ScatterCharts/ScatterChartDocumentation.razor @@ -1,21 +1,12 @@ @attribute [Route(pageUrl)] +@layout DemosMainLayout - - - - @pageDescription - - - - -
    -
    - Refer to the getting started guide for setting up charts. -
    -
    +
    @@ -37,11 +28,25 @@
    +
    +
    + Set the OnClick callback to react when a scatter point is selected. The callback receives ChartClickEventArgs with the dataset, point index, label, and structured raw X and Y value. +
    + +
    + + + + + For a complete charts setup walkthrough, see the + Getting Started — Charts Setup section. + + @code { - private const string pageUrl = RouteConstants.Demos_ScatterChart_Documentation; + private const string pageUrl = DemoRouteConstants.Demos_URL_ScatterChart; private const string pageTitle = "Blazor Scatter Chart"; - private const string pageDescription = "A Blazor Bootstrap scatter chart components are based on basic line charts with the x-axis changed to a linear axis. To use a scatter chart, data must be passed as objects containing X and Y properties."; + private const string pageDescription = "BlazorExpress.ChartJS scatter chart components are based on basic line charts with the x-axis changed to a linear axis. To use a scatter chart, data must be passed as objects containing X and Y properties."; private const string metaTitle = "Blazor Scatter Chart Component"; - private const string metaDescription = "A Blazor Bootstrap scatter chart components are based on basic line charts with the x-axis changed to a linear axis. To use a scatter chart, data must be passed as objects containing X and Y properties."; + private const string metaDescription = "BlazorExpress.ChartJS scatter chart components are based on basic line charts with the x-axis changed to a linear axis. To use a scatter chart, data must be passed as objects containing X and Y properties."; private const string imageUrl = "https://i.imgur.com/GEox0tS.png"; } diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Charts/ScatterCharts/ScatterChart_Demo_01_Basic_Example.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/ScatterCharts/ScatterChart_Demo_01_Basic_Example.razor similarity index 88% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Charts/ScatterCharts/ScatterChart_Demo_01_Basic_Example.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/ScatterCharts/ScatterChart_Demo_01_Basic_Example.razor index 9e32eb5bd..5a48d5f8b 100644 --- a/BlazorBootstrap.Demo.RCL/Components/Pages/Charts/ScatterCharts/ScatterChart_Demo_01_Basic_Example.razor +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/ScatterCharts/ScatterChart_Demo_01_Basic_Example.razor @@ -1,4 +1,4 @@ - + @code { private ScatterChart scatterChart = default!; @@ -35,14 +35,14 @@ private ScatterChartDataset GetRandomRadarChartDataset(int recordIndex) { - var c = ColorUtility.CategoricalTwelveColors[recordIndex].ToColor(); + var c = ColorUtility.CategoricalTwelveColors[recordIndex].ToChartColor(); return new ScatterChartDataset { Label = $"Team {recordIndex + 1}", Data = GetRandomData(), - BackgroundColor = c.ToRgbaString(), // RGBA - BorderColor = c.ToRgbString(), // RGB + BackgroundColor = c.ToChartRgbaString(), // RGBA + BorderColor = c.ToChartRgbString(), // RGB BorderWidth = 2, HoverBorderWidth = 4, }; diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Charts/ScatterCharts/ScatterChart_Demo_02_Dynamic_Data.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/ScatterCharts/ScatterChart_Demo_02_Dynamic_Data.razor similarity index 96% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Charts/ScatterCharts/ScatterChart_Demo_02_Dynamic_Data.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/ScatterCharts/ScatterChart_Demo_02_Dynamic_Data.razor index 49b8b2acd..402c201a9 100644 --- a/BlazorBootstrap.Demo.RCL/Components/Pages/Charts/ScatterCharts/ScatterChart_Demo_02_Dynamic_Data.razor +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/ScatterCharts/ScatterChart_Demo_02_Dynamic_Data.razor @@ -1,4 +1,4 @@ - +
    @@ -120,7 +120,7 @@ private ScatterChartDataset GetRandomScatterChartDataset() { - var c = ColorUtility.CategoricalTwelveColors[datasetsCount].ToColor(); + var c = ColorUtility.CategoricalTwelveColors[datasetsCount].ToChartColor(); datasetsCount += 1; @@ -128,8 +128,8 @@ { Label = $"Team {datasetsCount}", Data = GetRandomData(), - BackgroundColor = c.ToRgbaString(), // RGBA - BorderColor = c.ToRgbString(), // RGB + BackgroundColor = c.ToChartRgbaString(), // RGBA + BorderColor = c.ToChartRgbString(), // RGB BorderWidth = 2, Fill = true, HoverBorderWidth = 4, diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/ScatterCharts/ScatterChart_Demo_03_Click_Event.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/ScatterCharts/ScatterChart_Demo_03_Click_Event.razor new file mode 100644 index 000000000..c84c959c2 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/ScatterCharts/ScatterChart_Demo_03_Click_Event.razor @@ -0,0 +1,62 @@ + + +@if (selectedChartItem is not null) +{ +

    + Selected: @selectedChartItem.DatasetLabel (dataset @selectedChartItem.DatasetIndex), + @FormatLabel(selectedChartItem) (index @selectedChartItem.Index), + value @FormatValue(selectedChartItem) +

    +} + +@code { + private ScatterChart scatterChart = default!; + private ScatterChartOptions scatterChartOptions = default!; + private ChartData chartData = default!; + private ChartClickEventArgs? selectedChartItem; + + protected override void OnInitialized() + { + chartData = new ChartData + { + Labels = new List { "First", "Second", "Third", "Fourth" }, + Datasets = new List + { + new ScatterChartDataset + { + Label = "Measurements", + Data = new List + { + new(10, 25), + new(25, 15), + new(35, 40), + new(50, 30), + }, + BackgroundColor = "rgba(255, 159, 64, 0.6)", + BorderColor = "rgb(255, 159, 64)", + BorderWidth = 2, + }, + }, + }; + + scatterChartOptions = new ScatterChartOptions { Responsive = true }; + } + + protected override async Task OnAfterRenderAsync(bool firstRender) + { + if (firstRender) + await scatterChart.InitializeAsync(chartData, scatterChartOptions); + + await base.OnAfterRenderAsync(firstRender); + } + + private Task HandleClickAsync(ChartClickEventArgs eventArgs) + { + selectedChartItem = eventArgs; + return Task.CompletedTask; + } + + private static string FormatLabel(ChartClickEventArgs eventArgs) => eventArgs.Label ?? $"point {eventArgs.Index}"; + + private static string FormatValue(ChartClickEventArgs eventArgs) => eventArgs.Value?.ToString() ?? "null"; +} diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Charts/Utils_Colors.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/Utils_Colors.razor similarity index 97% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Charts/Utils_Colors.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/Utils_Colors.razor index 0d47f71e6..d2fdbe00c 100644 --- a/BlazorBootstrap.Demo.RCL/Components/Pages/Charts/Utils_Colors.razor +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/Utils_Colors.razor @@ -1,4 +1,4 @@ -@using System.Drawing; +@using System.Drawing; @@ -183,10 +183,10 @@ public ChartColor(Color color) { Name = color.Name; - Hex = color.ToHexString(); - Hexa = color.ToHexaString(); - Rgb = color.ToRgbString(); - Rgba = color.ToRgbaString(); + Hex = color.ToChartHexString(); + Hexa = color.ToChartHexaString(); + Rgb = color.ToChartRgbString(); + Rgba = color.ToChartRgbaString(); } public string Name { get; set; } diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/_Imports.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/_Imports.razor new file mode 100644 index 000000000..ca55fbd66 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Charts/_Imports.razor @@ -0,0 +1,6 @@ +@using BlazorExpress.ChartJS +@using Unit = BlazorExpress.ChartJS.Unit +@using ColorUtility = BlazorExpress.ChartJS.ColorUtility +@using Alignment = BlazorExpress.ChartJS.DataLabelAlignment +@using Anchor = BlazorExpress.ChartJS.DataLabelAnchor +@using BlazorBootstrap.Demo.RCL.Components.Pages.Demos.Charts diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Collapse/CollapseDocumentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Collapse/CollapseDocumentation.razor similarity index 88% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Collapse/CollapseDocumentation.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Collapse/CollapseDocumentation.razor index f1aaa1d56..e1fa648bf 100644 --- a/BlazorBootstrap.Demo.RCL/Components/Pages/Collapse/CollapseDocumentation.razor +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Collapse/CollapseDocumentation.razor @@ -1,15 +1,14 @@ @attribute [Route(pageUrl)] +@layout DemosMainLayout - + - - @pageDescription - - - +
    @@ -71,7 +70,7 @@
    @code { - private const string pageUrl = RouteConstants.Demos_Collapse_Documentation; + private const string pageUrl = DemoRouteConstants.Demos_URL_Collapse; private const string pageTitle = "Blazor Collapse"; private const string pageDescription = "Toggle the visibility of content across your project with the Blazor Bootstrap Collapse component."; private const string metaTitle = "Blazor Collapse Component"; diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Collapse/Collapse_Demo_01_Examples.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Collapse/Collapse_Demo_01_Examples.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Collapse/Collapse_Demo_01_Examples.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Collapse/Collapse_Demo_01_Examples.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Collapse/Collapse_Demo_02_Horizontal.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Collapse/Collapse_Demo_02_Horizontal.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Collapse/Collapse_Demo_02_Horizontal.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Collapse/Collapse_Demo_02_Horizontal.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Collapse/Collapse_Demo_03_Events.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Collapse/Collapse_Demo_03_Events.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Collapse/Collapse_Demo_03_Events.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Collapse/Collapse_Demo_03_Events.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/ConfirmDialog/ConfirmDialogDocumentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/ConfirmDialog/ConfirmDialogDocumentation.razor similarity index 89% rename from BlazorBootstrap.Demo.RCL/Components/Pages/ConfirmDialog/ConfirmDialogDocumentation.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/ConfirmDialog/ConfirmDialogDocumentation.razor index 6b967413c..9d4139879 100644 --- a/BlazorBootstrap.Demo.RCL/Components/Pages/ConfirmDialog/ConfirmDialogDocumentation.razor +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/ConfirmDialog/ConfirmDialogDocumentation.razor @@ -1,15 +1,14 @@ @attribute [Route(pageUrl)] +@layout DemosMainLayout - + - - @pageDescription - - - +
    @@ -74,7 +73,7 @@
    @code { - private const string pageUrl = RouteConstants.Demos_ConfirmDialog_Documentation; + private const string pageUrl = DemoRouteConstants.Demos_URL_ConfirmDialog; private const string pageTitle = "Blazor Confirm Dialog"; private const string pageDescription = "Use Blazor Bootstrap confirm dialog component if you want the user to verify or accept something."; private const string metaTitle = "Blazor Confirm Dialog Component"; diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/ConfirmDialog/ConfirmDialog_Demo_01_Examples.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/ConfirmDialog/ConfirmDialog_Demo_01_Examples.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/ConfirmDialog/ConfirmDialog_Demo_01_Examples.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/ConfirmDialog/ConfirmDialog_Demo_01_Examples.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/ConfirmDialog/ConfirmDialog_Demo_03_Dynamic_Component_As_Confirm_Dialog.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/ConfirmDialog/ConfirmDialog_Demo_03_Dynamic_Component_As_Confirm_Dialog.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/ConfirmDialog/ConfirmDialog_Demo_03_Dynamic_Component_As_Confirm_Dialog.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/ConfirmDialog/ConfirmDialog_Demo_03_Dynamic_Component_As_Confirm_Dialog.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/ConfirmDialog/ConfirmDialog_Demo_04_Change_Buttons_Text_And_Color.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/ConfirmDialog/ConfirmDialog_Demo_04_Change_Buttons_Text_And_Color.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/ConfirmDialog/ConfirmDialog_Demo_04_Change_Buttons_Text_And_Color.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/ConfirmDialog/ConfirmDialog_Demo_04_Change_Buttons_Text_And_Color.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/ConfirmDialog/ConfirmDialog_Demo_05_Optional_Sizes.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/ConfirmDialog/ConfirmDialog_Demo_05_Optional_Sizes.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/ConfirmDialog/ConfirmDialog_Demo_05_Optional_Sizes.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/ConfirmDialog/ConfirmDialog_Demo_05_Optional_Sizes.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/ConfirmDialog/ConfirmDialog_Demo_06_Scrolling_Long_Content_01.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/ConfirmDialog/ConfirmDialog_Demo_06_Scrolling_Long_Content_01.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/ConfirmDialog/ConfirmDialog_Demo_06_Scrolling_Long_Content_01.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/ConfirmDialog/ConfirmDialog_Demo_06_Scrolling_Long_Content_01.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/ConfirmDialog/ConfirmDialog_Demo_06_Scrolling_Long_Content_02.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/ConfirmDialog/ConfirmDialog_Demo_06_Scrolling_Long_Content_02.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/ConfirmDialog/ConfirmDialog_Demo_06_Scrolling_Long_Content_02.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/ConfirmDialog/ConfirmDialog_Demo_06_Scrolling_Long_Content_02.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/ConfirmDialog/ConfirmDialog_Demo_07_Vertically_Centered_01.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/ConfirmDialog/ConfirmDialog_Demo_07_Vertically_Centered_01.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/ConfirmDialog/ConfirmDialog_Demo_07_Vertically_Centered_01.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/ConfirmDialog/ConfirmDialog_Demo_07_Vertically_Centered_01.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/ConfirmDialog/ConfirmDialog_Demo_07_Vertically_Centered_02.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/ConfirmDialog/ConfirmDialog_Demo_07_Vertically_Centered_02.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/ConfirmDialog/ConfirmDialog_Demo_07_Vertically_Centered_02.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/ConfirmDialog/ConfirmDialog_Demo_07_Vertically_Centered_02.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/ConfirmDialog/ConfirmDialog_Demo_08_Disable_AutoFocus_Yes_Button.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/ConfirmDialog/ConfirmDialog_Demo_08_Disable_AutoFocus_Yes_Button.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/ConfirmDialog/ConfirmDialog_Demo_08_Disable_AutoFocus_Yes_Button.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/ConfirmDialog/ConfirmDialog_Demo_08_Disable_AutoFocus_Yes_Button.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/ConfirmDialog/EmployeeDemoComponent.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/ConfirmDialog/EmployeeDemoComponent.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/ConfirmDialog/EmployeeDemoComponent.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/ConfirmDialog/EmployeeDemoComponent.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/ConfirmDialog/LongContentDemoComponent.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/ConfirmDialog/LongContentDemoComponent.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/ConfirmDialog/LongContentDemoComponent.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/ConfirmDialog/LongContentDemoComponent.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Dropdowns/DropdownDocumentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Dropdowns/DropdownDocumentation.razor similarity index 95% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Dropdowns/DropdownDocumentation.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Dropdowns/DropdownDocumentation.razor index af7d67f04..1709da1cc 100644 --- a/BlazorBootstrap.Demo.RCL/Components/Pages/Dropdowns/DropdownDocumentation.razor +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Dropdowns/DropdownDocumentation.razor @@ -1,15 +1,14 @@ @attribute [Route(pageUrl)] +@layout DemosMainLayout - + - - @pageDescription - - - +
    @@ -186,7 +185,7 @@
    @code { - private const string pageUrl = RouteConstants.Demos_Dropdown_Documentation; + private const string pageUrl = DemoRouteConstants.Demos_URL_Dropdown; private const string pageTitle = "Blazor Dropdown"; private const string pageDescription = "Dropdowns are toggleable, contextual overlays for displaying lists of links and more. They are toggled by clicking, not by hovering; this is an intentional design decision'by bootstrap."; private const string metaTitle = "Blazor Dropdown Component"; diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Dropdowns/Dropdown_Demo_01_Single_Button.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Dropdowns/Dropdown_Demo_01_Single_Button.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Dropdowns/Dropdown_Demo_01_Single_Button.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Dropdowns/Dropdown_Demo_01_Single_Button.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Dropdowns/Dropdown_Demo_02_Color.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Dropdowns/Dropdown_Demo_02_Color.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Dropdowns/Dropdown_Demo_02_Color.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Dropdowns/Dropdown_Demo_02_Color.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Dropdowns/Dropdown_Demo_03_Split_Button.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Dropdowns/Dropdown_Demo_03_Split_Button.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Dropdowns/Dropdown_Demo_03_Split_Button.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Dropdowns/Dropdown_Demo_03_Split_Button.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Dropdowns/Dropdown_Demo_04_A_Sizing.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Dropdowns/Dropdown_Demo_04_A_Sizing.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Dropdowns/Dropdown_Demo_04_A_Sizing.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Dropdowns/Dropdown_Demo_04_A_Sizing.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Dropdowns/Dropdown_Demo_04_B_Sizing.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Dropdowns/Dropdown_Demo_04_B_Sizing.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Dropdowns/Dropdown_Demo_04_B_Sizing.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Dropdowns/Dropdown_Demo_04_B_Sizing.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Dropdowns/Dropdown_Demo_05_A_Directions_Dropup.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Dropdowns/Dropdown_Demo_05_A_Directions_Dropup.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Dropdowns/Dropdown_Demo_05_A_Directions_Dropup.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Dropdowns/Dropdown_Demo_05_A_Directions_Dropup.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Dropdowns/Dropdown_Demo_05_B_Directions_DropupCentered.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Dropdowns/Dropdown_Demo_05_B_Directions_DropupCentered.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Dropdowns/Dropdown_Demo_05_B_Directions_DropupCentered.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Dropdowns/Dropdown_Demo_05_B_Directions_DropupCentered.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Dropdowns/Dropdown_Demo_05_C_Directions_Dropend.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Dropdowns/Dropdown_Demo_05_C_Directions_Dropend.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Dropdowns/Dropdown_Demo_05_C_Directions_Dropend.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Dropdowns/Dropdown_Demo_05_C_Directions_Dropend.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Dropdowns/Dropdown_Demo_05_D_Directions_Dropstart.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Dropdowns/Dropdown_Demo_05_D_Directions_Dropstart.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Dropdowns/Dropdown_Demo_05_D_Directions_Dropstart.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Dropdowns/Dropdown_Demo_05_D_Directions_Dropstart.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Dropdowns/Dropdown_Demo_06_Active.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Dropdowns/Dropdown_Demo_06_Active.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Dropdowns/Dropdown_Demo_06_Active.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Dropdowns/Dropdown_Demo_06_Active.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Dropdowns/Dropdown_Demo_07_A_Disabled.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Dropdowns/Dropdown_Demo_07_A_Disabled.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Dropdowns/Dropdown_Demo_07_A_Disabled.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Dropdowns/Dropdown_Demo_07_A_Disabled.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Dropdowns/Dropdown_Demo_07_B_Disabled.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Dropdowns/Dropdown_Demo_07_B_Disabled.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Dropdowns/Dropdown_Demo_07_B_Disabled.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Dropdowns/Dropdown_Demo_07_B_Disabled.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Dropdowns/Dropdown_Demo_08_Menu_Position.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Dropdowns/Dropdown_Demo_08_Menu_Position.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Dropdowns/Dropdown_Demo_08_Menu_Position.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Dropdowns/Dropdown_Demo_08_Menu_Position.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Dropdowns/Dropdown_Demo_09_Header.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Dropdowns/Dropdown_Demo_09_Header.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Dropdowns/Dropdown_Demo_09_Header.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Dropdowns/Dropdown_Demo_09_Header.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Dropdowns/Dropdown_Demo_10_Dividers.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Dropdowns/Dropdown_Demo_10_Dividers.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Dropdowns/Dropdown_Demo_10_Dividers.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Dropdowns/Dropdown_Demo_10_Dividers.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Dropdowns/Dropdown_Demo_11_Text.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Dropdowns/Dropdown_Demo_11_Text.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Dropdowns/Dropdown_Demo_11_Text.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Dropdowns/Dropdown_Demo_11_Text.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Dropdowns/Dropdown_Demo_12_Forms.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Dropdowns/Dropdown_Demo_12_Forms.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Dropdowns/Dropdown_Demo_12_Forms.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Dropdowns/Dropdown_Demo_12_Forms.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Dropdowns/Dropdown_Demo_13_AutoClose.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Dropdowns/Dropdown_Demo_13_AutoClose.razor new file mode 100644 index 000000000..4bb9589c2 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Dropdowns/Dropdown_Demo_13_AutoClose.razor @@ -0,0 +1,37 @@ +
    + + Default dropdown + + Menu item + Menu item + Menu item + + + + + Clickable outside + + Menu item + Menu item + Menu item + + + + + Clickable inside + + Menu item + Menu item + Menu item + + + + + Manual close + + Menu item + Menu item + Menu item + + +
    \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Dropdowns/Dropdown_Demo_14_Methods.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Dropdowns/Dropdown_Demo_14_Methods.razor new file mode 100644 index 000000000..9b16514a2 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Dropdowns/Dropdown_Demo_14_Methods.razor @@ -0,0 +1,40 @@ +
    +
    + + Dropdown button + + Action + Another action + Something else here + + + + + +
    +
    + +
    +
    + + Dropdown button + + Action + Another action + Something else here + + + + +
    +
    + +@code { + private Dropdown dropdown1 = default!; + private Dropdown dropdown2 = default!; + + private async Task ShowAsync() => await dropdown1.ShowAsync(); + private async Task HideAsync() => await dropdown1.HideAsync(); + + private async Task ToggleAsync() => await dropdown2.ToggleAsync(); +} diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Dropdowns/Dropdown_Demo_15_Events.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Dropdowns/Dropdown_Demo_15_Events.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Dropdowns/Dropdown_Demo_15_Events.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Dropdowns/Dropdown_Demo_15_Events.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Form/AutoComplete/AutoCompleteDocumentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/AutoComplete/AutoCompleteDocumentation.razor similarity index 90% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Form/AutoComplete/AutoCompleteDocumentation.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/AutoComplete/AutoCompleteDocumentation.razor index 4c0f008b9..27462228b 100644 --- a/BlazorBootstrap.Demo.RCL/Components/Pages/Form/AutoComplete/AutoCompleteDocumentation.razor +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/AutoComplete/AutoCompleteDocumentation.razor @@ -1,17 +1,16 @@ @page "/autocomplete" @attribute [Route(pageUrl)] +@layout DemosMainLayout - + - - @pageDescription - - - +
    @@ -96,7 +95,7 @@
    @code { - private const string pageUrl = RouteConstants.Demos_AutoComplete_Documentation; + private const string pageUrl = DemoRouteConstants.Demos_URL_AutoComplete; private const string pageTitle = "Blazor AutoComplete"; private const string pageDescription = "Blazor Bootstrap autocomplete component is a textbox that offers the users suggestions as they type from the data source. And it supports client-side and server-side filtering."; private const string metaTitle = "Blazor AutoComplete Component"; diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Form/AutoComplete/AutoComplete_Demo_01_A_Client_Side_Filtering.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/AutoComplete/AutoComplete_Demo_01_A_Client_Side_Filtering.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Form/AutoComplete/AutoComplete_Demo_01_A_Client_Side_Filtering.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/AutoComplete/AutoComplete_Demo_01_A_Client_Side_Filtering.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Form/AutoComplete/AutoComplete_Demo_01_B_Client_Side_Filtering_With_StringComparision.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/AutoComplete/AutoComplete_Demo_01_B_Client_Side_Filtering_With_StringComparision.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Form/AutoComplete/AutoComplete_Demo_01_B_Client_Side_Filtering_With_StringComparision.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/AutoComplete/AutoComplete_Demo_01_B_Client_Side_Filtering_With_StringComparision.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Form/AutoComplete/AutoComplete_Demo_02_Server_Side_Filtering.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/AutoComplete/AutoComplete_Demo_02_Server_Side_Filtering.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Form/AutoComplete/AutoComplete_Demo_02_Server_Side_Filtering.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/AutoComplete/AutoComplete_Demo_02_Server_Side_Filtering.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Form/AutoComplete/AutoComplete_Demo_03_Set_Default_Value.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/AutoComplete/AutoComplete_Demo_03_Set_Default_Value.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Form/AutoComplete/AutoComplete_Demo_03_Set_Default_Value.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/AutoComplete/AutoComplete_Demo_03_Set_Default_Value.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Form/AutoComplete/AutoComplete_Demo_04_Validations.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/AutoComplete/AutoComplete_Demo_04_Validations.razor similarity index 92% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Form/AutoComplete/AutoComplete_Demo_04_Validations.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/AutoComplete/AutoComplete_Demo_04_Validations.razor index 376eb2fe7..37b6a2291 100644 --- a/BlazorBootstrap.Demo.RCL/Components/Pages/Form/AutoComplete/AutoComplete_Demo_04_Validations.razor +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/AutoComplete/AutoComplete_Demo_04_Validations.razor @@ -1,19 +1,5 @@ @using System.ComponentModel.DataAnnotations - - diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Form/AutoComplete/AutoComplete_Demo_05_A_Disable.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/AutoComplete/AutoComplete_Demo_05_A_Disable.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Form/AutoComplete/AutoComplete_Demo_05_A_Disable.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/AutoComplete/AutoComplete_Demo_05_A_Disable.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Form/AutoComplete/AutoComplete_Demo_05_B_Disable.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/AutoComplete/AutoComplete_Demo_05_B_Disable.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Form/AutoComplete/AutoComplete_Demo_05_B_Disable.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/AutoComplete/AutoComplete_Demo_05_B_Disable.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Form/AutoComplete/AutoComplete_Demo_06_Sizing.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/AutoComplete/AutoComplete_Demo_06_Sizing.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Form/AutoComplete/AutoComplete_Demo_06_Sizing.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/AutoComplete/AutoComplete_Demo_06_Sizing.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/CheckboxInput/CheckboxInputDocumentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/CheckboxInput/CheckboxInputDocumentation.razor new file mode 100644 index 000000000..25caa024c --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/CheckboxInput/CheckboxInputDocumentation.razor @@ -0,0 +1,41 @@ +@page "/checkbox-input" + +@attribute [Route(pageUrl)] +@layout DemosMainLayout + + + + + +
    + +
    + +
    +
    Use the Disabled parameter to disable the CheckboxInput.
    + +
    Also, use Enable() and Disable() methods to enable and disable the CheckboxInput.
    + + Do not use both the Disabled parameter and Enable() & Disable() methods. + + +
    + +
    +
    This event fires when the CheckboxInput value changes, but not on every keystroke.
    + +
    + +@code { + private const string pageUrl = DemoRouteConstants.Demos_URL_CheckboxInput; + private const string pageTitle = "Blazor CheckboxInput"; + private const string pageDescription = "The Blazor Bootstrap CheckboxInput component is constructed using an HTML input of type 'checkbox'."; + private const string metaTitle = "Blazor CheckboxInput Component"; + private const string metaDescription = "The Blazor Bootstrap CheckboxInput component is constructed using an HTML input of type 'checkbox'."; + private const string imageUrl = "https://i.imgur.com/kqSggFK.png"; +} diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/CheckboxInput/CheckboxInput_Demo_01_Basic_Usage.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/CheckboxInput/CheckboxInput_Demo_01_Basic_Usage.razor new file mode 100644 index 000000000..5b0d142d0 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/CheckboxInput/CheckboxInput_Demo_01_Basic_Usage.razor @@ -0,0 +1,13 @@ + + + +
    +
    Option 1: @option1
    +
    Option 2: @option2
    +
    + +@code +{ + private bool option1; + private bool option2 = true; +} diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/CheckboxInput/CheckboxInput_Demo_02_Disable_A.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/CheckboxInput/CheckboxInput_Demo_02_Disable_A.razor new file mode 100644 index 000000000..0966297e2 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/CheckboxInput/CheckboxInput_Demo_02_Disable_A.razor @@ -0,0 +1,22 @@ + + + +
    + + + +
    + +@code +{ + private bool isChecked; + private bool isChecked2 = true; + + private bool disabled = true; + + private void Enable() => disabled = false; + + private void Disable() => disabled = true; + + private void Toggle() => disabled = !disabled; +} diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/CheckboxInput/CheckboxInput_Demo_02_Disable_B.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/CheckboxInput/CheckboxInput_Demo_02_Disable_B.razor new file mode 100644 index 000000000..4ca9f8739 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/CheckboxInput/CheckboxInput_Demo_02_Disable_B.razor @@ -0,0 +1,28 @@ + + + +
    + + +
    + +@code +{ + private CheckboxInput? checkboxInputRef1; + private CheckboxInput? checkboxInputRef2; + + private bool isChecked; + private bool isChecked2 = true; + + private void Disable() + { + checkboxInputRef1.Disable(); + checkboxInputRef2.Disable(); + } + + private void Enable() + { + checkboxInputRef1.Enable(); + checkboxInputRef2.Enable(); + } +} diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/CheckboxInput/CheckboxInput_Demo_03_Events_ValueChanged.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/CheckboxInput/CheckboxInput_Demo_03_Events_ValueChanged.razor new file mode 100644 index 000000000..ad0f2601a --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/CheckboxInput/CheckboxInput_Demo_03_Events_ValueChanged.razor @@ -0,0 +1,13 @@ + +Current value: @isChecked +@code +{ + private bool isChecked; + + private void CheckboxValueChanged(bool value) + { + isChecked = value; + + // do something + } +} diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Form/CurrencyInput/CurrencyInputDocumentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/CurrencyInput/CurrencyInputDocumentation.razor similarity index 93% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Form/CurrencyInput/CurrencyInputDocumentation.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/CurrencyInput/CurrencyInputDocumentation.razor index f4a2088a2..36f224c57 100644 --- a/BlazorBootstrap.Demo.RCL/Components/Pages/Form/CurrencyInput/CurrencyInputDocumentation.razor +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/CurrencyInput/CurrencyInputDocumentation.razor @@ -1,17 +1,16 @@ @page "/currency-input" @attribute [Route(pageUrl)] +@layout DemosMainLayout - + - - @pageDescription - - - +
    By default, e + - are blocked. For all integral numeric types, dot . is blocked.
    @@ -96,7 +95,7 @@
    @code { - private const string pageUrl = RouteConstants.Demos_CurrencyInput_Documentation; + private const string pageUrl = DemoRouteConstants.Demos_URL_CurrencyInput; private const string pageTitle = "Blazor CurrencyInput"; private const string pageDescription = "Use the Blazor Bootstrap CurrencyInput component to show the numbers in the user's locale format, including the currency symbol."; private const string metaTitle = "Blazor CurrencyInput Component"; diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Form/CurrencyInput/CurrencyInput_Demo_01_Basic_Usage.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/CurrencyInput/CurrencyInput_Demo_01_Basic_Usage.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Form/CurrencyInput/CurrencyInput_Demo_01_Basic_Usage.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/CurrencyInput/CurrencyInput_Demo_01_Basic_Usage.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Form/CurrencyInput/CurrencyInput_Demo_02_Show_Currency_Symbols_for_the_Different_Locales.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/CurrencyInput/CurrencyInput_Demo_02_Show_Currency_Symbols_for_the_Different_Locales.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Form/CurrencyInput/CurrencyInput_Demo_02_Show_Currency_Symbols_for_the_Different_Locales.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/CurrencyInput/CurrencyInput_Demo_02_Show_Currency_Symbols_for_the_Different_Locales.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Form/CurrencyInput/CurrencyInput_Demo_03_Hide_Currency_Symbol.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/CurrencyInput/CurrencyInput_Demo_03_Hide_Currency_Symbol.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Form/CurrencyInput/CurrencyInput_Demo_03_Hide_Currency_Symbol.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/CurrencyInput/CurrencyInput_Demo_03_Hide_Currency_Symbol.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Form/CurrencyInput/CurrencyInput_Demo_04_Using_FractionDigits_and_IntegerDigits.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/CurrencyInput/CurrencyInput_Demo_04_Using_FractionDigits_and_IntegerDigits.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Form/CurrencyInput/CurrencyInput_Demo_04_Using_FractionDigits_and_IntegerDigits.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/CurrencyInput/CurrencyInput_Demo_04_Using_FractionDigits_and_IntegerDigits.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Form/CurrencyInput/CurrencyInput_Demo_05_Parentheses_Instead_of_Appending_A_Minus_Sign.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/CurrencyInput/CurrencyInput_Demo_05_Parentheses_Instead_of_Appending_A_Minus_Sign.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Form/CurrencyInput/CurrencyInput_Demo_05_Parentheses_Instead_of_Appending_A_Minus_Sign.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/CurrencyInput/CurrencyInput_Demo_05_Parentheses_Instead_of_Appending_A_Minus_Sign.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Form/CurrencyInput/CurrencyInput_Demo_06_Generic_Type.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/CurrencyInput/CurrencyInput_Demo_06_Generic_Type.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Form/CurrencyInput/CurrencyInput_Demo_06_Generic_Type.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/CurrencyInput/CurrencyInput_Demo_06_Generic_Type.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Form/CurrencyInput/CurrencyInput_Demo_07_Enable_Min_Max.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/CurrencyInput/CurrencyInput_Demo_07_Enable_Min_Max.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Form/CurrencyInput/CurrencyInput_Demo_07_Enable_Min_Max.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/CurrencyInput/CurrencyInput_Demo_07_Enable_Min_Max.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Form/CurrencyInput/CurrencyInput_Demo_08_Text_Alignment.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/CurrencyInput/CurrencyInput_Demo_08_Text_Alignment.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Form/CurrencyInput/CurrencyInput_Demo_08_Text_Alignment.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/CurrencyInput/CurrencyInput_Demo_08_Text_Alignment.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Form/CurrencyInput/CurrencyInput_Demo_09_Allow_Negative_Numbers.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/CurrencyInput/CurrencyInput_Demo_09_Allow_Negative_Numbers.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Form/CurrencyInput/CurrencyInput_Demo_09_Allow_Negative_Numbers.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/CurrencyInput/CurrencyInput_Demo_09_Allow_Negative_Numbers.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Form/CurrencyInput/CurrencyInput_Demo_10_A_Disable_Number_Input.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/CurrencyInput/CurrencyInput_Demo_10_A_Disable_Number_Input.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Form/CurrencyInput/CurrencyInput_Demo_10_A_Disable_Number_Input.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/CurrencyInput/CurrencyInput_Demo_10_A_Disable_Number_Input.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Form/CurrencyInput/CurrencyInput_Demo_10_B_Disable_Number_Input.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/CurrencyInput/CurrencyInput_Demo_10_B_Disable_Number_Input.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Form/CurrencyInput/CurrencyInput_Demo_10_B_Disable_Number_Input.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/CurrencyInput/CurrencyInput_Demo_10_B_Disable_Number_Input.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Form/CurrencyInput/CurrencyInput_Demo_11_Validations.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/CurrencyInput/CurrencyInput_Demo_11_Validations.razor similarity index 94% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Form/CurrencyInput/CurrencyInput_Demo_11_Validations.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/CurrencyInput/CurrencyInput_Demo_11_Validations.razor index 44912cd46..fde5114b6 100644 --- a/BlazorBootstrap.Demo.RCL/Components/Pages/Form/CurrencyInput/CurrencyInput_Demo_11_Validations.razor +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/CurrencyInput/CurrencyInput_Demo_11_Validations.razor @@ -1,19 +1,5 @@ @using System.ComponentModel.DataAnnotations - - diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Form/CurrencyInput/CurrencyInput_Demo_12_Decimals.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/CurrencyInput/CurrencyInput_Demo_12_Decimals.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Form/CurrencyInput/CurrencyInput_Demo_12_Decimals.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/CurrencyInput/CurrencyInput_Demo_12_Decimals.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Form/CurrencyInput/CurrencyInput_Demo_13_Events_Value_Changed.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/CurrencyInput/CurrencyInput_Demo_13_Events_Value_Changed.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Form/CurrencyInput/CurrencyInput_Demo_13_Events_Value_Changed.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/CurrencyInput/CurrencyInput_Demo_13_Events_Value_Changed.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Form/DateInput/DateInputDocumentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/DateInput/DateInputDocumentation.razor similarity index 91% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Form/DateInput/DateInputDocumentation.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/DateInput/DateInputDocumentation.razor index 0e77f37d2..2e0a44580 100644 --- a/BlazorBootstrap.Demo.RCL/Components/Pages/Form/DateInput/DateInputDocumentation.razor +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/DateInput/DateInputDocumentation.razor @@ -1,17 +1,16 @@ @page "/date-input" @attribute [Route(pageUrl)] +@layout DemosMainLayout - + - - @pageDescription - - - +
    @@ -79,7 +78,7 @@
    @code { - private const string pageUrl = RouteConstants.Demos_DateInput_Documentation; + private const string pageUrl = DemoRouteConstants.Demos_URL_DateInput; private const string pageTitle = "Blazor DateInput"; private const string pageDescription = "The Blazor Bootstrap DateInput component is constructed using an HTML input of type 'date' which limits user input based on pre-defined parameters. This component enables users to input a date using a text box with validation or a special date picker interface."; private const string metaTitle = "Blazor DateInput Component"; diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Form/DateInput/DateInput_Demo_01_Basic_Usage.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/DateInput/DateInput_Demo_01_Basic_Usage.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Form/DateInput/DateInput_Demo_01_Basic_Usage.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/DateInput/DateInput_Demo_01_Basic_Usage.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Form/DateInput/DateInput_Demo_02_Generic_Type.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/DateInput/DateInput_Demo_02_Generic_Type.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Form/DateInput/DateInput_Demo_02_Generic_Type.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/DateInput/DateInput_Demo_02_Generic_Type.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Form/DateInput/DateInput_Demo_03_Max_Min.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/DateInput/DateInput_Demo_03_Max_Min.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Form/DateInput/DateInput_Demo_03_Max_Min.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/DateInput/DateInput_Demo_03_Max_Min.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Form/DateInput/DateInput_Demo_04_A_Disable_Date_Input.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/DateInput/DateInput_Demo_04_A_Disable_Date_Input.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Form/DateInput/DateInput_Demo_04_A_Disable_Date_Input.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/DateInput/DateInput_Demo_04_A_Disable_Date_Input.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Form/DateInput/DateInput_Demo_04_B_Disable_Date_Input.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/DateInput/DateInput_Demo_04_B_Disable_Date_Input.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Form/DateInput/DateInput_Demo_04_B_Disable_Date_Input.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/DateInput/DateInput_Demo_04_B_Disable_Date_Input.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Form/DateInput/DateInput_Demo_05_Validations.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/DateInput/DateInput_Demo_05_Validations.razor similarity index 90% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Form/DateInput/DateInput_Demo_05_Validations.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/DateInput/DateInput_Demo_05_Validations.razor index e94f3616e..4992c4c27 100644 --- a/BlazorBootstrap.Demo.RCL/Components/Pages/Form/DateInput/DateInput_Demo_05_Validations.razor +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/DateInput/DateInput_Demo_05_Validations.razor @@ -1,19 +1,5 @@ @using System.ComponentModel.DataAnnotations - - diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Form/DateInput/DateInput_Demo_06_Events_Value_Changed.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/DateInput/DateInput_Demo_06_Events_Value_Changed.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Form/DateInput/DateInput_Demo_06_Events_Value_Changed.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/DateInput/DateInput_Demo_06_Events_Value_Changed.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Form/DateInput/DateInput_Demo_07_Restrict_The_Date_Field_Based_On_The_Entry_In_Another_Date_Field.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/DateInput/DateInput_Demo_07_Restrict_The_Date_Field_Based_On_The_Entry_In_Another_Date_Field.razor similarity index 94% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Form/DateInput/DateInput_Demo_07_Restrict_The_Date_Field_Based_On_The_Entry_In_Another_Date_Field.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/DateInput/DateInput_Demo_07_Restrict_The_Date_Field_Based_On_The_Entry_In_Another_Date_Field.razor index a00d2c9c6..294cc816c 100644 --- a/BlazorBootstrap.Demo.RCL/Components/Pages/Form/DateInput/DateInput_Demo_07_Restrict_The_Date_Field_Based_On_The_Entry_In_Another_Date_Field.razor +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/DateInput/DateInput_Demo_07_Restrict_The_Date_Field_Based_On_The_Entry_In_Another_Date_Field.razor @@ -1,19 +1,5 @@ @using System.ComponentModel.DataAnnotations - - diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/DragAndDropFileInput/DragAndDropFileInputDocumentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/DragAndDropFileInput/DragAndDropFileInputDocumentation.razor new file mode 100644 index 000000000..d15a2f0ce --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/DragAndDropFileInput/DragAndDropFileInputDocumentation.razor @@ -0,0 +1,37 @@ +@page "/drag-and-drop-file-input" + +@attribute [Route(pageUrl)] +@layout DemosMainLayout + + + + + +
    +
    Drop files onto the area on desktop, or tap it on touch devices to open the native file picker.
    + +
    + +
    +
    Drop and picker selection share the same extension, size, and count validation behavior. Configure validation-message templates with {FileName}, {MaxFileSize}, {AllowedFileTypes}, or {MaxFileCount} where applicable; the single-file message is static.
    + +
    + +
    +
    Use FilesChanged to update a form model while retaining the drag-and-drop area and touch picker fallback.
    + +
    + +@code { + private const string pageUrl = DemoRouteConstants.Demos_URL_DragAndDropFileInput; + private const string pageTitle = "Blazor DragAndDropFileInput"; + private const string pageDescription = "The Blazor Bootstrap DragAndDropFileInput component supports desktop drag and drop and touch file-picker selection."; + private const string metaTitle = "Blazor DragAndDropFileInput Component"; + private const string metaDescription = "The Blazor Bootstrap DragAndDropFileInput component supports desktop drag and drop and touch file-picker selection."; + private const string imageUrl = DemoScreenshotSrcConstants.Demos_URL_Forms_Prefix; +} diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/DragAndDropFileInput/DragAndDropFileInput_Demo_01_Basic_Usage.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/DragAndDropFileInput/DragAndDropFileInput_Demo_01_Basic_Usage.razor new file mode 100644 index 000000000..91a16521c --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/DragAndDropFileInput/DragAndDropFileInput_Demo_01_Basic_Usage.razor @@ -0,0 +1 @@ + diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/DragAndDropFileInput/DragAndDropFileInput_Demo_02_Validation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/DragAndDropFileInput/DragAndDropFileInput_Demo_02_Validation.razor new file mode 100644 index 000000000..ad0490057 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/DragAndDropFileInput/DragAndDropFileInput_Demo_02_Validation.razor @@ -0,0 +1,13 @@ + + +@code { + private readonly string[] allowedFileTypes = [".pdf", "png"]; +} diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/DragAndDropFileInput/DragAndDropFileInput_Demo_03_Form_Validation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/DragAndDropFileInput/DragAndDropFileInput_Demo_03_Form_Validation.razor new file mode 100644 index 000000000..2b3473f48 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/DragAndDropFileInput/DragAndDropFileInput_Demo_03_Form_Validation.razor @@ -0,0 +1,50 @@ +@using System.ComponentModel.DataAnnotations +@using Microsoft.AspNetCore.Components.Forms + + + + + +
    + + + +
    + + + + @if (submitted) + { +
    Form submitted with @upload.DocumentName.
    + } +
    + +@code { + private readonly string[] allowedFileTypes = ["pdf"]; + private readonly UploadModel upload = new(); + private EditContext editContext = null!; + private bool submitted; + + protected override void OnInitialized() + { + editContext = new EditContext(upload); + } + + private void HandleValidSubmit() => submitted = true; + + private void OnFilesChanged(IReadOnlyList files) + { + upload.DocumentName = files.FirstOrDefault()?.Name; + submitted = false; + editContext.NotifyFieldChanged(new FieldIdentifier(upload, nameof(upload.DocumentName))); + } + + private sealed class UploadModel + { + [Required(ErrorMessage = "A supporting document is required.")] + public string? DocumentName { get; set; } + } +} diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/EnumInput/EnumInputDocumentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/EnumInput/EnumInputDocumentation.razor new file mode 100644 index 000000000..15c9a795e --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/EnumInput/EnumInputDocumentation.razor @@ -0,0 +1,116 @@ +@page "/enum-input" + +@attribute [Route(pageUrl)] +@layout DemosMainLayout + + + + + +
    +
    + The EnumInput component displays enum values in a dropdown, allowing users to select from a predefined set of options. + Enum labels use DisplayAttribute.GetName() when a DisplayAttribute is present, including resource-backed names, and fall back to the enum member name. +
    + How to use: +
    +
      +
    1. Define an enum representing your options.
    2. +
    3. Add the EnumInput component to your page, specifying the TEnum type parameter.
    4. +
    5. Bind the selected value using @@bind-Value or @@bind-Text as needed.
    6. +
    7. Use the selected value or text in your logic as shown in the demo.
    8. +
    +
    + This demo shows how to bind both the enum value and text, and how to display the selected result. +
    + +
    + +
    +
    + The EnumInput component can be rendered in various sizes to fit different UI requirements. +
    + How to use: +
    +
      +
    1. Set the Size parameter to one of the EnumInputSize values (Small, Normal, Large).
    2. +
    3. Bind the selected value as needed.
    4. +
    +
    + This demo shows how to display EnumInput in different sizes for flexible layout integration. +
    + +
    + +
    +
    + The EnumInput component can be disabled to prevent user interaction. +

    + How to use: +
    +
      +
    1. Set the Disabled parameter to true to make the dropdown non-interactive.
    2. +
    3. Bind the value as usual; the user will not be able to change it.
    4. +
    +
    + This demo demonstrates how to render EnumInput in a disabled state. +
    + +
    + +
    +
    + The EnumInput component supports event callbacks for value and text changes, enabling custom logic when the selection changes. +
    + How to use (ValueChanged): +
    +
      +
    1. Set the Value parameter and handle the ValueChanged event to respond to selection changes.
    2. +
    3. Update your logic based on the new value in the event handler.
    4. +
    +
    + This demo shows how to handle value changes using the ValueChanged event. +
    + +
    + How to use (TextChanged): +
    +
      +
    1. Set the Text parameter and handle the TextChanged event to respond to text changes.
    2. +
    3. Update your logic based on the new text in the event handler.
    4. +
    +
    + This demo shows how to handle text changes using the TextChanged event. +
    + +
    + +
    +
    + The EnumInput component can be enabled or disabled dynamically at runtime. +
    + How to use: +
    +
      +
    1. Bind the Disabled parameter to a boolean property in your component.
    2. +
    3. Update the property in your code (e.g., via button click) to enable or disable the EnumInput as needed.
    4. +
    +
    + This demo demonstrates how to programmatically enable or disable the EnumInput component. +
    + +
    + +@code { + private const string pageUrl = DemoRouteConstants.Demos_URL_EnumInput; + private const string pageTitle = "Blazor EnumInput"; + private const string pageDescription = "The Blazor Bootstrap EnumInput component renders a dropdown list from an enumeration (enum), enabling users to select from a predefined set of options. It simplifies data entry by binding directly to enum types and supports customization with sizes."; + private const string metaTitle = "Blazor EnumInput Component"; + private const string metaDescription = "The Blazor Bootstrap EnumInput component renders a dropdown list from an enumeration (enum), enabling users to select from a predefined set of options. It simplifies data entry by binding directly to enum types and supports customization with sizes."; + private const string imageUrl = "https://i.imgur.com/1mVjqQv.png"; +} diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/EnumInput/EnumInput_Demo_01_How_it_works.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/EnumInput/EnumInput_Demo_01_How_it_works.razor new file mode 100644 index 000000000..2351d6781 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/EnumInput/EnumInput_Demo_01_How_it_works.razor @@ -0,0 +1,33 @@ +@using System.ComponentModel.DataAnnotations + + +
    Selected value: @selectedStatusValue
    + + +
    Selected text: @selectedStatusText
    + +@code { + private int selectedStatusValue; + private string? selectedStatusText; + + override protected void OnInitialized() + { + selectedStatusValue = (int)Status.Active; + selectedStatusText = StatusLabels.Pending; + } + + public enum Status + { + Active, + [Display(Name = "Inactive user")] + Inactive, + + [Display(Name = nameof(StatusLabels.Pending), ResourceType = typeof(StatusLabels))] + Pending + } + + public static class StatusLabels + { + public static string Pending => "Waiting for review"; + } +} diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/EnumInput/EnumInput_Demo_03_Sizes.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/EnumInput/EnumInput_Demo_03_Sizes.razor new file mode 100644 index 000000000..592158433 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/EnumInput/EnumInput_Demo_03_Sizes.razor @@ -0,0 +1,18 @@ + + + + + +@code { + private int value1 = (int)Status.Pending; + private int value2 = (int)Status.Pending; + private int value3 = (int)Status.Pending; + private int value4 = (int)Status.Pending; + + public enum Status + { + Active, + Inactive, + Pending + } +} \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/EnumInput/EnumInput_Demo_06_Disabled.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/EnumInput/EnumInput_Demo_06_Disabled.razor new file mode 100644 index 000000000..b55c02f61 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/EnumInput/EnumInput_Demo_06_Disabled.razor @@ -0,0 +1,12 @@ + + +@code { + private int value1 = (int)Status.Pending; + + public enum Status + { + Active, + Inactive, + Pending + } +} \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/EnumInput/EnumInput_Demo_07_Events_A_ValueChanged.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/EnumInput/EnumInput_Demo_07_Events_A_ValueChanged.razor new file mode 100644 index 000000000..79145f75b --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/EnumInput/EnumInput_Demo_07_Events_A_ValueChanged.razor @@ -0,0 +1,31 @@ + +
    Selected value: @value1
    + +@code { + private int value1 = (int)Status.Pending; + + private void OnValueChanged(int value) + { + value1 = value; + + if (value == (int)Status.Active) + { + // Do something when the value is Active + } + else if (value == (int)Status.Inactive) + { + // Do something when the value is Inactive + } + else if (value == (int)Status.Pending) + { + // Do something when the value is Pending + } + } + + public enum Status + { + Active, + Inactive, + Pending + } +} \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/EnumInput/EnumInput_Demo_07_Events_B_TextChanged.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/EnumInput/EnumInput_Demo_07_Events_B_TextChanged.razor new file mode 100644 index 000000000..8b475a5f7 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/EnumInput/EnumInput_Demo_07_Events_B_TextChanged.razor @@ -0,0 +1,31 @@ + +
    Selected text: @text1
    + +@code { + private string text1 = Status.Pending.ToString(); + + private void OnTextChanged(string value) + { + text1 = value; + + if (value == "Active") + { + // Do something when the text is "Active" + } + else if (value == "Inactive") + { + // Do something when the text is "Inactive" + } + else if (value == "Pending") + { + // Do something when the text is "Pending" + } + } + + public enum Status + { + Active, + Inactive, + Pending + } +} \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/EnumInput/EnumInput_Demo_08_Methods_Enable_Disable.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/EnumInput/EnumInput_Demo_08_Methods_Enable_Disable.razor new file mode 100644 index 000000000..c4fce4c9f --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/EnumInput/EnumInput_Demo_08_Methods_Enable_Disable.razor @@ -0,0 +1,28 @@ + + +
    + + +
    + +@code { + private bool isDisabled = true; + private int value1 = (int)Status.Pending; + + private void EnableInput() + { + isDisabled = false; + } + + private void DisableInput() + { + isDisabled = true; + } + + public enum Status + { + Active, + Inactive, + Pending + } +} \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/FileInput/FileInputDocumentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/FileInput/FileInputDocumentation.razor new file mode 100644 index 000000000..10e6abf37 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/FileInput/FileInputDocumentation.razor @@ -0,0 +1,52 @@ +@page "/file-input" + +@attribute [Route(pageUrl)] +@layout DemosMainLayout + + + + + +
    +
    FileInput uses Bootstrap's standard visible file-control presentation. Use DragAndDropFileInput when a drop area is needed.
    + +
    + +
    +
    Set Multiple to allow a selected file to be removed without clearing the others.
    + +
    + +
    +
    Use Size to apply Bootstrap's form-control-lg and form-control-sm file-control sizes.
    + +
    + +
    +
    FileInput validates sizes, counts, and extensions selected from the file dialog. Configure validation-message templates with {FileName}, {MaxFileSize}, {AllowedFileTypes}, or {MaxFileCount} where applicable; the single-file message is static.
    + +
    + +
    +
    Use FilesChanged to update a form model and combine file-selection rules with standard form validation.
    + +
    + +
    +
    An empty AllowedFileTypes collection accepts every extension while other configured rules remain active.
    + +
    + +@code { + private const string pageUrl = DemoRouteConstants.Demos_URL_FileInput; + private const string pageTitle = "Blazor FileInput"; + private const string pageDescription = "The Blazor Bootstrap FileInput component provides a standard Bootstrap file control with validation and removal."; + private const string metaTitle = "Blazor FileInput Component"; + private const string metaDescription = "The Blazor Bootstrap FileInput component provides a standard Bootstrap file control with validation and removal."; + private const string imageUrl = DemoScreenshotSrcConstants.Demos_URL_Forms_Prefix; +} diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/FileInput/FileInput_Demo_01_Basic_Usage.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/FileInput/FileInput_Demo_01_Basic_Usage.razor new file mode 100644 index 000000000..5ac7324fe --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/FileInput/FileInput_Demo_01_Basic_Usage.razor @@ -0,0 +1 @@ + diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/FileInput/FileInput_Demo_02_Multiple_Files_And_Removal.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/FileInput/FileInput_Demo_02_Multiple_Files_And_Removal.razor new file mode 100644 index 000000000..cfc68955a --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/FileInput/FileInput_Demo_02_Multiple_Files_And_Removal.razor @@ -0,0 +1 @@ + diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/FileInput/FileInput_Demo_03_Colors_And_Sizes.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/FileInput/FileInput_Demo_03_Colors_And_Sizes.razor new file mode 100644 index 000000000..42e456842 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/FileInput/FileInput_Demo_03_Colors_And_Sizes.razor @@ -0,0 +1,4 @@ +
    + + +
    diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/FileInput/FileInput_Demo_04_Validation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/FileInput/FileInput_Demo_04_Validation.razor new file mode 100644 index 000000000..0278bb949 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/FileInput/FileInput_Demo_04_Validation.razor @@ -0,0 +1,13 @@ + + +@code { + private readonly string[] allowedFileTypes = [".pdf", "png"]; +} diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/FileInput/FileInput_Demo_05_Hint_And_Unrestricted_Extensions.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/FileInput/FileInput_Demo_05_Hint_And_Unrestricted_Extensions.razor new file mode 100644 index 000000000..32a834d6e --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/FileInput/FileInput_Demo_05_Hint_And_Unrestricted_Extensions.razor @@ -0,0 +1,8 @@ + + +@code { + private readonly string[] allowedFileTypes = []; +} diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/FileInput/FileInput_Demo_06_Form_Validation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/FileInput/FileInput_Demo_06_Form_Validation.razor new file mode 100644 index 000000000..d510e4f17 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/FileInput/FileInput_Demo_06_Form_Validation.razor @@ -0,0 +1,50 @@ +@using System.ComponentModel.DataAnnotations +@using Microsoft.AspNetCore.Components.Forms + + + + + +
    + + + +
    + + + + @if (submitted) + { +
    Form submitted with @upload.DocumentName.
    + } +
    + +@code { + private readonly string[] allowedFileTypes = ["pdf"]; + private readonly UploadModel upload = new(); + private EditContext editContext = null!; + private bool submitted; + + protected override void OnInitialized() + { + editContext = new EditContext(upload); + } + + private void HandleValidSubmit() => submitted = true; + + private void OnFilesChanged(IReadOnlyList files) + { + upload.DocumentName = files.FirstOrDefault()?.Name; + submitted = false; + editContext.NotifyFieldChanged(new FieldIdentifier(upload, nameof(upload.DocumentName))); + } + + private sealed class UploadModel + { + [Required(ErrorMessage = "A supporting document is required.")] + public string? DocumentName { get; set; } + } +} diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Form/NumberInput/NumberInputDocumentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/NumberInput/NumberInputDocumentation.razor similarity index 91% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Form/NumberInput/NumberInputDocumentation.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/NumberInput/NumberInputDocumentation.razor index 819c761fc..86145679f 100644 --- a/BlazorBootstrap.Demo.RCL/Components/Pages/Form/NumberInput/NumberInputDocumentation.razor +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/NumberInput/NumberInputDocumentation.razor @@ -1,17 +1,16 @@ @page "/number-input" @attribute [Route(pageUrl)] +@layout DemosMainLayout - + - - @pageDescription - - - +
    By default, e + - are blocked. For all integral numeric types, dot . is blocked.
    @@ -74,7 +73,7 @@
    @code { - private const string pageUrl = RouteConstants.Demos_NumberInput_Documentation; + private const string pageUrl = DemoRouteConstants.Demos_URL_NumberInput; private const string pageTitle = "Blazor NumberInput"; private const string pageDescription = "Blazor Bootstrap NumberInput component is built around HTML input of type=\"number\" that prevents the user input based on the parameters set."; private const string metaTitle = "Blazor NumberInput Component"; diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Form/NumberInput/NumberInput_Demo_01_Basic_Usage.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/NumberInput/NumberInput_Demo_01_Basic_Usage.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Form/NumberInput/NumberInput_Demo_01_Basic_Usage.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/NumberInput/NumberInput_Demo_01_Basic_Usage.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Form/NumberInput/NumberInput_Demo_02_Generic_Type.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/NumberInput/NumberInput_Demo_02_Generic_Type.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Form/NumberInput/NumberInput_Demo_02_Generic_Type.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/NumberInput/NumberInput_Demo_02_Generic_Type.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Form/NumberInput/NumberInput_Demo_03_Enable_Min_Max.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/NumberInput/NumberInput_Demo_03_Enable_Min_Max.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Form/NumberInput/NumberInput_Demo_03_Enable_Min_Max.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/NumberInput/NumberInput_Demo_03_Enable_Min_Max.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Form/NumberInput/NumberInput_Demo_04_Step.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/NumberInput/NumberInput_Demo_04_Step.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Form/NumberInput/NumberInput_Demo_04_Step.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/NumberInput/NumberInput_Demo_04_Step.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Form/NumberInput/NumberInput_Demo_05_Text_Alignment.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/NumberInput/NumberInput_Demo_05_Text_Alignment.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Form/NumberInput/NumberInput_Demo_05_Text_Alignment.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/NumberInput/NumberInput_Demo_05_Text_Alignment.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Form/NumberInput/NumberInput_Demo_06_Allow_Negative_Numbers.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/NumberInput/NumberInput_Demo_06_Allow_Negative_Numbers.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Form/NumberInput/NumberInput_Demo_06_Allow_Negative_Numbers.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/NumberInput/NumberInput_Demo_06_Allow_Negative_Numbers.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Form/NumberInput/NumberInput_Demo_07_A_Disable_Number_Input.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/NumberInput/NumberInput_Demo_07_A_Disable_Number_Input.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Form/NumberInput/NumberInput_Demo_07_A_Disable_Number_Input.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/NumberInput/NumberInput_Demo_07_A_Disable_Number_Input.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Form/NumberInput/NumberInput_Demo_07_B_Disable_Number_Input.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/NumberInput/NumberInput_Demo_07_B_Disable_Number_Input.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Form/NumberInput/NumberInput_Demo_07_B_Disable_Number_Input.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/NumberInput/NumberInput_Demo_07_B_Disable_Number_Input.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Form/NumberInput/NumberInput_Demo_08_Validations.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/NumberInput/NumberInput_Demo_08_Validations.razor similarity index 94% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Form/NumberInput/NumberInput_Demo_08_Validations.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/NumberInput/NumberInput_Demo_08_Validations.razor index c0a09f30d..30eef6b86 100644 --- a/BlazorBootstrap.Demo.RCL/Components/Pages/Form/NumberInput/NumberInput_Demo_08_Validations.razor +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/NumberInput/NumberInput_Demo_08_Validations.razor @@ -1,19 +1,5 @@ @using System.ComponentModel.DataAnnotations - - diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Form/NumberInput/NumberInput_Demo_09_Events_Value_Changed.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/NumberInput/NumberInput_Demo_09_Events_Value_Changed.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Form/NumberInput/NumberInput_Demo_09_Events_Value_Changed.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/NumberInput/NumberInput_Demo_09_Events_Value_Changed.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/OTPInput/OTPInputDocumentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/OTPInput/OTPInputDocumentation.razor new file mode 100644 index 000000000..7b5d29bb6 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/OTPInput/OTPInputDocumentation.razor @@ -0,0 +1,57 @@ +@page "/otp-input" +@attribute [Route(pageUrl)] +@layout DemosMainLayout + + + + + +
    +
    + The OTPInput component provides a user-friendly interface for entering one-time passwords (OTP), commonly used for authentication and verification flows. +

    + How to use: +
    +
      +
    1. Add the OTPInput component to your page.
    2. +
    3. Handle the OnOTPChanged event to capture the OTP value as the user types.
    4. +
    5. Handle the OnOTPCompleted event to respond when the user has entered the complete OTP.
    6. +
    7. Bind the entered OTP to a variable for display or further processing as needed.
    8. +
    +
    + This demo illustrates the basic usage of the OTPInput component, including event handling for OTP entry and completion. +
    + +
    + +
    +
    + The OTPInput component allows you to specify the required OTP length, adapting the number of input fields accordingly. +

    + How to use: +
    +
      +
    1. Set the Length parameter to define how many digits or characters the OTP should have (e.g., Length="5").
    2. +
    3. Handle the OnOTPChanged and OnOTPCompleted events as shown in the demo to process the OTP input.
    4. +
    5. Display or use the entered OTP value as needed in your application.
    6. +
    +
    + This demo demonstrates how to configure the OTPInput component for a custom OTP length and handle user input accordingly. +
    + +
    + +@code { + private const string componentName = nameof(OTPInput); + private const string pageUrl = DemoRouteConstants.Demos_URL_OTPInput; + private const string pageTitle = componentName; + private const string pageDescription = $"The {componentName} component allows users to enter a one-time password (OTP) in a secure and user-friendly manner. The component is designed to enhance the user experience by providing a visually appealing and functional input field for OTP entry."; + private const string metaTitle = $"Blazor {componentName} Component"; + private const string metaDescription = $"The {componentName} component allows users to enter a one-time password (OTP) in a secure and user-friendly manner. The component is designed to enhance the user experience by providing a visually appealing and functional input field for OTP entry."; + private const string imageUrl = DemoScreenshotSrcConstants.Demos_URL_OTPInput; +} diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/OTPInput/OTPInput_Demo_01_How_it_works.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/OTPInput/OTPInput_Demo_01_How_it_works.razor new file mode 100644 index 000000000..824373cf4 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/OTPInput/OTPInput_Demo_01_How_it_works.razor @@ -0,0 +1,19 @@ + + +
    Entered OTP: @enteredOTP
    + +@code { + private string? enteredOTP = null; + + private void HandleOtpChanged(string otp) + { + enteredOTP = otp; + } + + private void HandleOtpCompleted(string otp) + { + Console.WriteLine($"OTP Completed: {otp}"); + enteredOTP = otp; + } +} \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/OTPInput/OTPInput_Demo_02_Length.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/OTPInput/OTPInput_Demo_02_Length.razor new file mode 100644 index 000000000..7194b3841 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/OTPInput/OTPInput_Demo_02_Length.razor @@ -0,0 +1,20 @@ + + +
    Entered OTP: @enteredOTP
    + +@code { + private string? enteredOTP = null; + + private void HandleOtpChanged(string otp) + { + enteredOTP = otp; + } + + private void HandleOtpCompleted(string otp) + { + Console.WriteLine($"OTP Completed: {otp}"); + enteredOTP = otp; + } +} \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/PasswordInput/PasswordInputDocumentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/PasswordInput/PasswordInputDocumentation.razor new file mode 100644 index 000000000..975f482e3 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/PasswordInput/PasswordInputDocumentation.razor @@ -0,0 +1,50 @@ +@page "/password-input" + +@attribute [Route(pageUrl)] +@layout DemosMainLayout + + + + + +
    + +
    + +
    +
    Use the Disabled parameter to disable the PasswordInput.
    + +
    Also, use Enable() and Disable() methods to enable and disable the PasswordInput.
    + + Do not use both the Disabled parameter and Enable() & Disable() methods. + + +
    + +
    +
    + Like any other blazor input component, PasswordInput supports validations. + Add the DataAnnotations on the PasswordInput component to validate the user input before submitting the form. + In the below example, we used Required attribute. +
    + +
    + +
    +
    This event fires when the PasswordInput value changes, but not on every keystroke.
    + +
    + +@code { + private const string pageUrl = DemoRouteConstants.Demos_URL_PasswordInput; + private const string pageTitle = "Blazor PasswordInput"; + private const string pageDescription = "The Blazor Bootstrap PasswordInput component is constructed using an HTML input of type 'password'."; + private const string metaTitle = "Blazor PasswordInput Component"; + private const string metaDescription = "The Blazor Bootstrap PasswordInput component is constructed using an HTML input of type 'password'."; + private const string imageUrl = "https://i.imgur.com/0k1C2XS.png"; +} diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/PasswordInput/PasswordInput_Demo_01_Basic_Usage.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/PasswordInput/PasswordInput_Demo_01_Basic_Usage.razor new file mode 100644 index 000000000..4b0c05b09 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/PasswordInput/PasswordInput_Demo_01_Basic_Usage.razor @@ -0,0 +1,8 @@ +
    + +
    +
    Entered password: @enteredPassword
    + +@code { + private string? enteredPassword = null; +} diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/PasswordInput/PasswordInput_Demo_02_Disable_A.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/PasswordInput/PasswordInput_Demo_02_Disable_A.razor new file mode 100644 index 000000000..d47989563 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/PasswordInput/PasswordInput_Demo_02_Disable_A.razor @@ -0,0 +1,20 @@ +
    + +
    +
    Entered password: @enteredPassword
    + + + + + +@code { + private string? enteredPassword = null; + + private bool disabled = true; + + private void Enable() => disabled = false; + + private void Disable() => disabled = true; + + private void Toggle() => disabled = !disabled; +} diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/PasswordInput/PasswordInput_Demo_02_Disable_B.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/PasswordInput/PasswordInput_Demo_02_Disable_B.razor new file mode 100644 index 000000000..367c8bbc8 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/PasswordInput/PasswordInput_Demo_02_Disable_B.razor @@ -0,0 +1,17 @@ +
    + +
    +
    Entered text: @enteredPassword
    + + + + +@code { + private PasswordInput? passwordInputRef; + + private string? enteredPassword = null; + + private void Disable() => passwordInputRef.Disable(); + + private void Enable() => passwordInputRef.Enable(); +} diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/PasswordInput/PasswordInput_Demo_03_Validations.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/PasswordInput/PasswordInput_Demo_03_Validations.razor new file mode 100644 index 000000000..f2b1b42b1 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/PasswordInput/PasswordInput_Demo_03_Validations.razor @@ -0,0 +1,66 @@ +@using System.ComponentModel.DataAnnotations + + + + +
    + +
    + + +
    +
    + +
    + +
    + + +
    +
    + +
    +
    + + +
    +
    + +
    + +@code { + private UserLogin userLogin = new(); + private EditContext? editContext; + + protected override void OnInitialized() + { + editContext = new EditContext(userLogin); + base.OnInitialized(); + } + + public void HandleOnValidSubmit() + { + // additional check + if (editContext.Validate()) + { + // do something + // submit the form + Console.WriteLine("Login successful"); + } + } + + private void ResetForm() + { + userLogin = new(); + editContext = new EditContext(userLogin); + } + + public class UserLogin + { + [Required(ErrorMessage = "User name required.")] + public string? UserName { get; set; } + + [Required(ErrorMessage = "Password required.")] + public string? Password { get; set; } + } +} diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/PasswordInput/PasswordInput_Demo_04_Events_ValueChanged.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/PasswordInput/PasswordInput_Demo_04_Events_ValueChanged.razor new file mode 100644 index 000000000..1aab225aa --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/PasswordInput/PasswordInput_Demo_04_Events_ValueChanged.razor @@ -0,0 +1,15 @@ +
    + +
    +
    Entered password: @enteredPassword
    + +@code { + private string? enteredPassword = null; + + private void PasswordChanged(string? value) + { + enteredPassword = value; + + // do something + } +} diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/RadioInput/RadioInputDocumentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/RadioInput/RadioInputDocumentation.razor new file mode 100644 index 000000000..c50959ea1 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/RadioInput/RadioInputDocumentation.razor @@ -0,0 +1,36 @@ +@page "/radio-input" + +@attribute [Route(pageUrl)] +@layout DemosMainLayout + + + + + +
    + +
    + +
    +
    Use the Disabled parameter to disable the RadioInput.
    + +
    Also, use Enable() and Disable() methods to enable and disable the RadioInput.
    + + Do not use both the Disabled parameter and Enable() & Disable() methods. + + +
    + +@code { + private const string pageUrl = DemoRouteConstants.Demos_URL_RadioInput; + private const string pageTitle = "Blazor RadioInput"; + private const string pageDescription = "The Blazor Bootstrap RadioInput component is constructed using an HTML input of type 'radio'."; + private const string metaTitle = "Blazor RadioInput Component"; + private const string metaDescription = "The Blazor Bootstrap RadioInput component is constructed using an HTML input of type 'radio'."; + private const string imageUrl = "https://i.imgur.com/8koE00q.png"; +} diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/RadioInput/RadioInput_Demo_01_Basic_Usage.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/RadioInput/RadioInput_Demo_01_Basic_Usage.razor new file mode 100644 index 000000000..4ae480b3b --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/RadioInput/RadioInput_Demo_01_Basic_Usage.razor @@ -0,0 +1,13 @@ +

    Would you like to receive notifications?

    + + + +
    +
    IsYesOn: @isYesOn
    +
    IsNoOn: @isNoOn
    +
    +@code +{ + private bool isYesOn; + private bool isNoOn = true; +} diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/RadioInput/RadioInput_Demo_02_Disable_A.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/RadioInput/RadioInput_Demo_02_Disable_A.razor new file mode 100644 index 000000000..6260b867d --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/RadioInput/RadioInput_Demo_02_Disable_A.razor @@ -0,0 +1,23 @@ +

    Would you like to receive notifications?

    + + + +
    + + + +
    + +@code +{ + private bool isChecked; + private bool isChecked2 = true; + + private bool disabled = true; + + private void Enable() => disabled = false; + + private void Disable() => disabled = true; + + private void Toggle() => disabled = !disabled; +} diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/RadioInput/RadioInput_Demo_02_Disable_B.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/RadioInput/RadioInput_Demo_02_Disable_B.razor new file mode 100644 index 000000000..b0a91473c --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/RadioInput/RadioInput_Demo_02_Disable_B.razor @@ -0,0 +1,29 @@ +

    Would you like to receive notifications?

    + + + +
    + + +
    + +@code +{ + private RadioInput? radioInputRef; + private RadioInput? radioInputRef2; + + private bool isChecked; + private bool isChecked2 = true; + + private void Disable() + { + radioInputRef.Disable(); + radioInputRef2.Disable(); + } + + private void Enable() + { + radioInputRef.Enable(); + radioInputRef2.Enable(); + } +} diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Form/RangeInput/RangeInputDocumentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/RangeInput/RangeInputDocumentation.razor similarity index 88% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Form/RangeInput/RangeInputDocumentation.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/RangeInput/RangeInputDocumentation.razor index cee95d4de..d921ebf98 100644 --- a/BlazorBootstrap.Demo.RCL/Components/Pages/Form/RangeInput/RangeInputDocumentation.razor +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/RangeInput/RangeInputDocumentation.razor @@ -1,17 +1,16 @@ @page "/range-input" @attribute [Route(pageUrl)] +@layout DemosMainLayout - + - - @pageDescription - - - +
    @@ -64,7 +63,7 @@
    @code { - private const string pageUrl = RouteConstants.Demos_RangeInput_Documentation; + private const string pageUrl = DemoRouteConstants.Demos_URL_RangeInput; private const string pageTitle = "Blazor RangeInput"; private const string pageDescription = "Blazor Bootstrap RangeInput component is built around HTML input of type=\"range\"."; private const string metaTitle = "Blazor RangeInput Component"; diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Form/RangeInput/RangeInput_Demo_01_Basic_Usage_A.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/RangeInput/RangeInput_Demo_01_Basic_Usage_A.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Form/RangeInput/RangeInput_Demo_01_Basic_Usage_A.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/RangeInput/RangeInput_Demo_01_Basic_Usage_A.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Form/RangeInput/RangeInput_Demo_01_Basic_Usage_B.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/RangeInput/RangeInput_Demo_01_Basic_Usage_B.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Form/RangeInput/RangeInput_Demo_01_Basic_Usage_B.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/RangeInput/RangeInput_Demo_01_Basic_Usage_B.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Form/RangeInput/RangeInput_Demo_02_Disabled_A.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/RangeInput/RangeInput_Demo_02_Disabled_A.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Form/RangeInput/RangeInput_Demo_02_Disabled_A.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/RangeInput/RangeInput_Demo_02_Disabled_A.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Form/RangeInput/RangeInput_Demo_02_Disabled_B.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/RangeInput/RangeInput_Demo_02_Disabled_B.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Form/RangeInput/RangeInput_Demo_02_Disabled_B.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/RangeInput/RangeInput_Demo_02_Disabled_B.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Form/RangeInput/RangeInput_Demo_03_Min_Max.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/RangeInput/RangeInput_Demo_03_Min_Max.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Form/RangeInput/RangeInput_Demo_03_Min_Max.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/RangeInput/RangeInput_Demo_03_Min_Max.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Form/RangeInput/RangeInput_Demo_04_Step.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/RangeInput/RangeInput_Demo_04_Step.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Form/RangeInput/RangeInput_Demo_04_Step.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/RangeInput/RangeInput_Demo_04_Step.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Form/RangeInput/RangeInput_Demo_05_Decimals.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/RangeInput/RangeInput_Demo_05_Decimals.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Form/RangeInput/RangeInput_Demo_05_Decimals.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/RangeInput/RangeInput_Demo_05_Decimals.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Form/RangeInput/RangeInput_Demo_06_Tick_Marks.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/RangeInput/RangeInput_Demo_06_Tick_Marks.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Form/RangeInput/RangeInput_Demo_06_Tick_Marks.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/RangeInput/RangeInput_Demo_06_Tick_Marks.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/RichTextEditor/RichTextEditorDocumentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/RichTextEditor/RichTextEditorDocumentation.razor new file mode 100644 index 000000000..77c567a32 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/RichTextEditor/RichTextEditorDocumentation.razor @@ -0,0 +1,124 @@ +@page "/rich-text-editor" + +@attribute [Route(DemoRouteConstants.Demos_URL_RichTextEditor)] +@layout DemosMainLayout + + + + + +
    +
    + Start with the complete toolbar when authors need the full RichTextEditor feature set in one place. Keep Disabled set to false so every toolbar action remains available, from document styles and text formatting through media, tables, history, printing, and fullscreen mode. +

    + How to use: +
    +
      +
    1. Add RichTextEditor to the page and provide an initial Value.
    2. +
    3. Omit ToolbarItems to render every supported toolbar control.
    4. +
    5. Keep Disabled set to false, then use toolbar actions to build a complete document.
    6. +
    +
    +
    + +
    + +
    +
    + Use a focused authoring toolbar to turn a rough release-note draft into structured, scannable content. While Disabled is false, each toolbar action can apply headings, emphasis, color, alignment, lists, and quotations. +

    + How to use: +
    +
      +
    1. Choose the commands that match the authoring workflow in ToolbarItems.
    2. +
    3. Place the caret in a paragraph or select text in the draft.
    4. +
    5. Use each toolbar action needed for a heading, emphasis, list, alignment, or quotation as the document takes shape.
    6. +
    +
    +
    + +
    + +
    +
    + Give a publishing workflow only the insertion commands it needs to add a link, image, separator, or table to an already-authored announcement. This example does not configure ImageUploadHandler, so its Image dialog intentionally shows only the Image URL tab. Keep Disabled set to false while authors use each toolbar action. +

    + How to use: +
    +
      +
    1. Configure the insertion-focused commands in ToolbarItems.
    2. +
    3. Place the caret where the new content belongs in the announcement.
    4. +
    5. Use the link, image, horizontal-rule, or table toolbar action and complete its dialog when prompted.
    6. +
    +
    +
    + +
    + +
    +
    + Configure ImageUploadHandler in the host application instead of configuring a browser endpoint. The Upload image tab is conditional: editors without this callback intentionally show only Image URL. This shared demo supplies the callback, accepts JPEG, PNG, WebP, and GIF files up to 5 MB, returns a trusted temporary HTTPS preview URL, and exposes callback counts so rejected files can be distinguished from host-handler failures. The selectable outcomes also demonstrate cancellation and domain policy rejection. +

    + How to use: +
    +
      +
    1. Set ImageUploadHandler, the allowed raster types, size limit, and optional HTTPS domain allow-list.
    2. +
    3. Open the Image dialog, choose Upload image, and select a valid local raster image.
    4. +
    5. Review the preview and accessibility options before insertion; use the simulated outcomes to observe host failure, cancellation, and URL-policy feedback.
    6. +
    +
    +
    + +
    + +
    +
    + Use Disabled when rich text should remain visible for review. Editing is disabled: users cannot change the content or invoke a toolbar action. +

    + How to use: +
    +
      +
    1. Provide the rich text through Value.
    2. +
    3. Set Disabled to true when editing is disabled.
    4. +
    5. Keep the visible content as context; hovering the inactive toolbar explains that editing is disabled, and no toolbar action is available.
    6. +
    +
    +
    + +
    + +
    +
    + Use ValueExpression inside an EditForm to validate the editor's plain-text content while retaining its HTML separately for submission. Keep Disabled set to false while users edit content and use a toolbar action. +

    + How to use: +
    +
      +
    1. Add DataAnnotationsValidator and a ValidationMessage for the model property.
    2. +
    3. Set ValueExpression to the validated model property and update that property from ValueChanged.
    4. +
    5. Keep editing enabled, then delete the editor content and submit to see required validation feedback before entering content and submitting again.
    6. +
    +
    +
    + +
    + +
    +
    + Use ValueChanged to react to committed content and show its text metrics in surrounding UI. Keep Disabled set to false while observing edits and toolbar actions. This typing-focused example deliberately reports the callback without assigning its HTML back to the editor value. +

    + How to use: +
    +
      +
    1. Handle ValueChanged to receive sanitized HTML, plain text, and count metrics after an edit is committed.
    2. +
    3. Update external UI such as metrics or a save indicator without writing the callback HTML back into the active editor value.
    4. +
    5. Edit the text or use a toolbar action, then observe the committed word and character counts.
    6. +
    +
    +
    + +
    + +@code { + private const string pageUrl = DemoRouteConstants.Demos_URL_RichTextEditor; +} diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/RichTextEditor/RichTextEditor_Demo_01_Full_Toolbar.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/RichTextEditor/RichTextEditor_Demo_01_Full_Toolbar.razor new file mode 100644 index 000000000..91eff9fa7 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/RichTextEditor/RichTextEditor_Demo_01_Full_Toolbar.razor @@ -0,0 +1,4 @@ +
    + +
    \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/RichTextEditor/RichTextEditor_Demo_02_Article_Draft.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/RichTextEditor/RichTextEditor_Demo_02_Article_Draft.razor new file mode 100644 index 000000000..0a7c2972b --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/RichTextEditor/RichTextEditor_Demo_02_Article_Draft.razor @@ -0,0 +1,22 @@ +
    + +
    + +@code { + private string content = "

    June release notes

    This draft needs a clear structure before it is published.

    Highlight the most important update, then organize the remaining details for readers.

    • Improved editor workflow
    • Updated content guidance
    "; + + private readonly RichTextEditorToolbarItem[] toolbarItems = + { + RichTextEditorToolbarItem.Heading2, + RichTextEditorToolbarItem.Bold, + RichTextEditorToolbarItem.Italic, + RichTextEditorToolbarItem.TextColor, + RichTextEditorToolbarItem.AlignLeft, + RichTextEditorToolbarItem.AlignCenter, + RichTextEditorToolbarItem.OrderedList, + RichTextEditorToolbarItem.UnorderedList, + RichTextEditorToolbarItem.Blockquote + }; +} \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/RichTextEditor/RichTextEditor_Demo_03_Publish_Rich_Update.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/RichTextEditor/RichTextEditor_Demo_03_Publish_Rich_Update.razor new file mode 100644 index 000000000..aebd36f88 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/RichTextEditor/RichTextEditor_Demo_03_Publish_Rich_Update.razor @@ -0,0 +1,18 @@ +
    + +
    + +@code { + private string content = "

    Service update

    We have published the latest service update. Add the supporting link, image, or availability table before sharing it.

    "; + + private readonly RichTextEditorToolbarItem[] toolbarItems = + { + RichTextEditorToolbarItem.Link, + RichTextEditorToolbarItem.Image, + RichTextEditorToolbarItem.HorizontalRule, + RichTextEditorToolbarItem.Table, + RichTextEditorToolbarItem.Fullscreen + }; +} \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/RichTextEditor/RichTextEditor_Demo_04_Disabled.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/RichTextEditor/RichTextEditor_Demo_04_Disabled.razor new file mode 100644 index 000000000..c66355d6a --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/RichTextEditor/RichTextEditor_Demo_04_Disabled.razor @@ -0,0 +1,5 @@ +
    + +
    diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/RichTextEditor/RichTextEditor_Demo_05_Form_Validation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/RichTextEditor/RichTextEditor_Demo_05_Form_Validation.razor new file mode 100644 index 000000000..be57f9ebe --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/RichTextEditor/RichTextEditor_Demo_05_Form_Validation.razor @@ -0,0 +1,50 @@ +@using System.ComponentModel.DataAnnotations + + + + +
    + + +
    + + + + @if (submitted) + { +
    The announcement passed validation.
    + } +
    + +@code { + private const string editorInitialHtml = "

    Review this announcement, then submit the form.

    "; + + private readonly AnnouncementDraft draft = new() + { + Content = "Review this announcement, then submit the form.", + Html = editorInitialHtml + }; + + private bool submitted; + + private void HandleValidSubmit() => submitted = true; + + private Task OnValueChanged(RichTextEditorChange change) + { + draft.Content = change.Text; + draft.Html = change.Html; + submitted = false; + return Task.CompletedTask; + } + + private sealed class AnnouncementDraft + { + [Required(ErrorMessage = "Announcement content is required.")] + public string Content { get; set; } = string.Empty; + + public string Html { get; set; } = string.Empty; + } +} diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/RichTextEditor/RichTextEditor_Demo_06_Events.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/RichTextEditor/RichTextEditor_Demo_06_Events.razor new file mode 100644 index 000000000..478d4fd2c --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/RichTextEditor/RichTextEditor_Demo_06_Events.razor @@ -0,0 +1,38 @@ + + +
    + Last committed change +

    @lastChange

    +
    + +
    + Committed HTML preview +
    @(new MarkupString(content))
    +
    + +@code { + private readonly RichTextEditorToolbarItem[] toolbarItems = + { + RichTextEditorToolbarItem.Bold, + RichTextEditorToolbarItem.Italic, + RichTextEditorToolbarItem.Link, + RichTextEditorToolbarItem.OrderedList, + RichTextEditorToolbarItem.UnorderedList + }; + + private const string editorInitialContent = + "

    Change this project update and pause briefly to commit the editor value.

    "; + + private string content = editorInitialContent; + private string lastChange = "No committed change yet."; + + private Task OnValueChanged(RichTextEditorChange change) + { + content = change.Html; // Updates the external preview only. + lastChange = $"Committed {change.WordCount} words and {change.CharacterCount} characters."; + return Task.CompletedTask; + } +} \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/RichTextEditor/RichTextEditor_Demo_07_Image_Upload_Handler.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/RichTextEditor/RichTextEditor_Demo_07_Image_Upload_Handler.razor new file mode 100644 index 000000000..5090b145c --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/RichTextEditor/RichTextEditor_Demo_07_Image_Upload_Handler.razor @@ -0,0 +1,62 @@ +
    + +
    + +
    + + +
    This editor shows Upload image because it supplies ImageUploadHandler; editors without that callback show only Image URL. Invalid, too-large, or unsupported files are rejected before this callback is invoked.
    +
    + Host callback invocations: @callbackCount
    + @hostStatus +
    +
    + +@code { + private const long maxImageFileSize = 5 * 1024 * 1024; + private const string successImageUrl = "https://placehold.co/800x450/png?text=Hosted+image"; + + private readonly string[] allowedImageDomains = { "placehold.co" }; + private readonly string[] allowedImageFileTypes = { "jpg", "jpeg", "png", "webp", "gif" }; + private readonly RichTextEditorToolbarItem[] toolbarItems = { RichTextEditorToolbarItem.Image }; + + private int callbackCount; + private string content = "

    Choose the image command, then use the host-controlled upload flow.

    "; + private string hostStatus = "No host callback has been invoked yet."; + private string selectedOutcome = "success"; + + private async Task UploadImageAsync(RichTextEditorImageUploadRequest request) + { + callbackCount++; + hostStatus = $"The host received {request.File.Name}. It must authorize, revalidate, scan, and store the upload before returning a temporary HTTPS URL."; + await InvokeAsync(StateHasChanged); + + request.CancellationToken.ThrowIfCancellationRequested(); + + switch (selectedOutcome) + { + case "failure": + throw new InvalidOperationException("Simulated host upload failure."); + case "cancellation": + hostStatus = "The host callback is waiting. Close the Image modal or select another file to cancel it."; + await InvokeAsync(StateHasChanged); + await Task.Delay(Timeout.InfiniteTimeSpan, request.CancellationToken); + return null; + case "off-policy-url": + return new RichTextEditorImageUploadResult("https://example.com/untrusted-image.png"); + default: + return new RichTextEditorImageUploadResult(successImageUrl); + } + } +} \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Form/Switch/SwitchDocumentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/Switch/SwitchDocumentation.razor similarity index 82% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Form/Switch/SwitchDocumentation.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/Switch/SwitchDocumentation.razor index 5007a50b4..a70af4256 100644 --- a/BlazorBootstrap.Demo.RCL/Components/Pages/Form/Switch/SwitchDocumentation.razor +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/Switch/SwitchDocumentation.razor @@ -1,17 +1,16 @@ @page "/switch" @attribute [Route(pageUrl)] +@layout DemosMainLayout - + - - @pageDescription - - - +
    @@ -46,7 +45,7 @@
    @code { - private const string pageUrl = RouteConstants.Demos_Switch_Documentation; + private const string pageUrl = DemoRouteConstants.Demos_URL_Switch; private const string pageTitle = "Blazor Switch"; private const string pageDescription = "Create consistent cross-browser and cross-device checkboxes with our blazor switches. A switch has the markup of a custom checkbox."; private const string metaTitle = "Blazor Switch Component"; diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Form/Switch/Switch_Demo_01_Basic_Usage.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/Switch/Switch_Demo_01_Basic_Usage.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Form/Switch/Switch_Demo_01_Basic_Usage.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/Switch/Switch_Demo_01_Basic_Usage.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Form/Switch/Switch_Demo_02_A_Disable.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/Switch/Switch_Demo_02_A_Disable.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Form/Switch/Switch_Demo_02_A_Disable.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/Switch/Switch_Demo_02_A_Disable.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Form/Switch/Switch_Demo_02_B_Disable.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/Switch/Switch_Demo_02_B_Disable.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Form/Switch/Switch_Demo_02_B_Disable.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/Switch/Switch_Demo_02_B_Disable.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Form/Switch/Switch_Demo_03_Reverse.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/Switch/Switch_Demo_03_Reverse.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Form/Switch/Switch_Demo_03_Reverse.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/Switch/Switch_Demo_03_Reverse.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Form/Switch/Switch_Demo_04_Events_Value_Changed.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/Switch/Switch_Demo_04_Events_Value_Changed.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Form/Switch/Switch_Demo_04_Events_Value_Changed.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/Switch/Switch_Demo_04_Events_Value_Changed.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Form/Switch/Switch_Demo_05_Form.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/Switch/Switch_Demo_05_Form.razor similarity index 94% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Form/Switch/Switch_Demo_05_Form.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/Switch/Switch_Demo_05_Form.razor index 4c9fec7d7..3b8fe39ec 100644 --- a/BlazorBootstrap.Demo.RCL/Components/Pages/Form/Switch/Switch_Demo_05_Form.razor +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/Switch/Switch_Demo_05_Form.razor @@ -1,19 +1,5 @@ @using System.ComponentModel.DataAnnotations - - diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/TextAreaInput/TextAreaInputDocumentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/TextAreaInput/TextAreaInputDocumentation.razor new file mode 100644 index 000000000..fffab5362 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/TextAreaInput/TextAreaInputDocumentation.razor @@ -0,0 +1,60 @@ +@page "/text-area-input" + +@attribute [Route(pageUrl)] +@layout DemosMainLayout + + + + + +
    + +
    + +
    +
    You can change the text alignment according to your need. Use the TextAlignment parameter to set the alignment. In the below example, alignment is set to center and end.
    + +
    + +
    +
    Use the Disabled parameter to disable the TextAreaInput.
    + +
    Also, use Enable() and Disable() methods to enable and disable the TextAreaInput.
    + + Do not use both the Disabled parameter and Enable() & Disable() methods. + + +
    + +
    +
    Use the MaxLength parameter to set the maximum length of the TextAreaInput.
    + +
    + +
    +
    + Like any other blazor input component, TextAreaInput supports validations. + Add the DataAnnotations on the TextAreaInput component to validate the user input before submitting the form. + In the below example, we used Required attribute. +
    + +
    + +
    +
    This event fires when the TextAreaInput value changes, but not on every keystroke.
    + +
    + +@code { + private const string pageUrl = DemoRouteConstants.Demos_URL_TextAreaInput; + private const string pageTitle = "Blazor TextAreaInput"; + private const string pageDescription = "The Blazor Bootstrap TextAreaInput component provides a multi-line plain-text editing control, ideal for scenarios requiring users to input substantial amounts of free-form text. Common use cases include comment sections on reviews or review descriptions, or feedback forms."; + private const string metaTitle = "Blazor TextAreaInput Component"; + private const string metaDescription = "The Blazor Bootstrap TextAreaInput component provides a multi-line plain-text editing control, ideal for scenarios requiring users to input substantial amounts of free-form text. Common use cases include comment sections on reviews or review descriptions, or feedback forms."; + private const string imageUrl = "https://i.imgur.com/aSVKMqv.png"; +} diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/TextAreaInput/TextAreaInput_Demo_01_Basic_Usage.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/TextAreaInput/TextAreaInput_Demo_01_Basic_Usage.razor new file mode 100644 index 000000000..9f919c39e --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/TextAreaInput/TextAreaInput_Demo_01_Basic_Usage.razor @@ -0,0 +1,8 @@ +
    + +
    +
    Entered text: @enteredText
    + +@code { + private string? enteredText = null; +} diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/TextAreaInput/TextAreaInput_Demo_02_Text_Alignment.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/TextAreaInput/TextAreaInput_Demo_02_Text_Alignment.razor new file mode 100644 index 000000000..9e69ca909 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/TextAreaInput/TextAreaInput_Demo_02_Text_Alignment.razor @@ -0,0 +1,13 @@ +
    + +
    +
    Entered text: @enteredText
    +
    + +
    +
    Entered text: @enteredText2
    + +@code { + private string? enteredText = "sample text"; + private string? enteredText2 = "sample text 2"; +} diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/TextAreaInput/TextAreaInput_Demo_03_Disable_A.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/TextAreaInput/TextAreaInput_Demo_03_Disable_A.razor new file mode 100644 index 000000000..be32069bd --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/TextAreaInput/TextAreaInput_Demo_03_Disable_A.razor @@ -0,0 +1,20 @@ +
    + +
    +
    Entered text: @enteredText
    + + + + + +@code { + private string? enteredText = null; + + private bool disabled = true; + + private void Enable() => disabled = false; + + private void Disable() => disabled = true; + + private void Toggle() => disabled = !disabled; +} diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/TextAreaInput/TextAreaInput_Demo_03_Disable_B.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/TextAreaInput/TextAreaInput_Demo_03_Disable_B.razor new file mode 100644 index 000000000..24bf642c3 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/TextAreaInput/TextAreaInput_Demo_03_Disable_B.razor @@ -0,0 +1,17 @@ +
    + +
    +
    Entered text: @enteredText
    + + + + +@code { + private TextAreaInput? textAreaInputRef; + + private string? enteredText = null; + + private void Disable() => textAreaInputRef.Disable(); + + private void Enable() => textAreaInputRef.Enable(); +} diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/TextAreaInput/TextAreaInput_Demo_04_MaxLength.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/TextAreaInput/TextAreaInput_Demo_04_MaxLength.razor new file mode 100644 index 000000000..44e93ce26 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/TextAreaInput/TextAreaInput_Demo_04_MaxLength.razor @@ -0,0 +1,8 @@ +
    + +
    +
    Entered text: @enteredText
    + +@code { + private string? enteredText = null; +} diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/TextAreaInput/TextAreaInput_Demo_05_Validations.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/TextAreaInput/TextAreaInput_Demo_05_Validations.razor new file mode 100644 index 000000000..d2f667ef2 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/TextAreaInput/TextAreaInput_Demo_05_Validations.razor @@ -0,0 +1,66 @@ +@using System.ComponentModel.DataAnnotations + + + + +
    + +
    + + +
    +
    + +
    + +
    + + +
    +
    + +
    +
    + + +
    +
    + +
    + +@code { + private Product product = new(); + private EditContext? editContext; + + protected override void OnInitialized() + { + editContext = new EditContext(product); + base.OnInitialized(); + } + + public void HandleOnValidSubmit() + { + // additional check + if (editContext.Validate()) + { + // do something + // submit the form + Console.WriteLine("Form submitted successfully"); + } + } + + private void ResetForm() + { + product = new(); + editContext = new EditContext(product); + } + + public class Product + { + [Required(ErrorMessage = "Product name required.")] + public string? Name { get; set; } + + [Required(ErrorMessage = "Product description required.")] + public string? Description { get; set; } + } +} diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/TextAreaInput/TextAreaInput_Demo_06_Events_ValueChanged.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/TextAreaInput/TextAreaInput_Demo_06_Events_ValueChanged.razor new file mode 100644 index 000000000..34a9fe2bf --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/TextAreaInput/TextAreaInput_Demo_06_Events_ValueChanged.razor @@ -0,0 +1,15 @@ +
    + +
    +
    Entered text: @enteredText
    + +@code { + private string? enteredText = null; + + private void TextChanged(string? value) + { + enteredText = value; + + // do something + } +} diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/TextInput/TextInputDocumentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/TextInput/TextInputDocumentation.razor new file mode 100644 index 000000000..8f1f257ca --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/TextInput/TextInputDocumentation.razor @@ -0,0 +1,60 @@ +@page "/text-input" + +@attribute [Route(pageUrl)] +@layout DemosMainLayout + + + + + +
    + +
    + +
    +
    You can change the text alignment according to your need. Use the TextAlignment parameter to set the alignment. In the below example, alignment is set to center and end.
    + +
    + +
    +
    Use the Disabled parameter to disable the TextInput.
    + +
    Also, use Enable() and Disable() methods to enable and disable the TextInput.
    + + Do not use both the Disabled parameter and Enable() & Disable() methods. + + +
    + +
    +
    Use the MaxLength parameter to set the maximum length of the TextInput.
    + +
    + +
    +
    + Like any other blazor input component, TextInput supports validations. + Add the DataAnnotations on the TextInput component to validate the user input before submitting the form. + In the below example, we used Required attribute. +
    + +
    + +
    +
    This event fires when the TextInput value changes, but not on every keystroke.
    + +
    + +@code { + private const string pageUrl = DemoRouteConstants.Demos_URL_TextInput; + private const string pageTitle = "Blazor TextInput"; + private const string pageDescription = "The Blazor Bootstrap TextInput component is constructed using an HTML input of type 'text'."; + private const string metaTitle = "Blazor TextInput Component"; + private const string metaDescription = "The Blazor Bootstrap TextInput component is constructed using an HTML input of type 'text'."; + private const string imageUrl = "https://i.imgur.com/N2VUHIn.png"; +} diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/TextInput/TextInput_Demo_01_Basic_Usage.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/TextInput/TextInput_Demo_01_Basic_Usage.razor new file mode 100644 index 000000000..7153b870c --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/TextInput/TextInput_Demo_01_Basic_Usage.razor @@ -0,0 +1,8 @@ +
    + +
    +
    Entered text: @enteredText
    + +@code { + private string? enteredText = null; +} diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/TextInput/TextInput_Demo_02_Text_Alignment.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/TextInput/TextInput_Demo_02_Text_Alignment.razor new file mode 100644 index 000000000..3c0b5b535 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/TextInput/TextInput_Demo_02_Text_Alignment.razor @@ -0,0 +1,13 @@ +
    + +
    +
    Entered text: @enteredText
    +
    + +
    +
    Entered text: @enteredText2
    + +@code { + private string? enteredText = "sample text"; + private string? enteredText2 = "sample text 2"; +} diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/TextInput/TextInput_Demo_03_Disable_A.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/TextInput/TextInput_Demo_03_Disable_A.razor new file mode 100644 index 000000000..456b47d32 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/TextInput/TextInput_Demo_03_Disable_A.razor @@ -0,0 +1,20 @@ +
    + +
    +
    Entered text: @enteredText
    + + + + + +@code { + private string? enteredText = null; + + private bool disabled = true; + + private void Enable() => disabled = false; + + private void Disable() => disabled = true; + + private void Toggle() => disabled = !disabled; +} diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/TextInput/TextInput_Demo_03_Disable_B.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/TextInput/TextInput_Demo_03_Disable_B.razor new file mode 100644 index 000000000..17f0e35f3 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/TextInput/TextInput_Demo_03_Disable_B.razor @@ -0,0 +1,17 @@ +
    + +
    +
    Entered text: @enteredText
    + + + + +@code { + private TextInput? textInputRef; + + private string? enteredText = null; + + private void Disable() => textInputRef.Disable(); + + private void Enable() => textInputRef.Enable(); +} diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/TextInput/TextInput_Demo_04_MaxLength.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/TextInput/TextInput_Demo_04_MaxLength.razor new file mode 100644 index 000000000..118d5d557 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/TextInput/TextInput_Demo_04_MaxLength.razor @@ -0,0 +1,8 @@ +
    + +
    +
    Entered text: @enteredText
    + +@code { + private string? enteredText = null; +} diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/TextInput/TextInput_Demo_05_Validations.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/TextInput/TextInput_Demo_05_Validations.razor new file mode 100644 index 000000000..ca2e58cf1 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/TextInput/TextInput_Demo_05_Validations.razor @@ -0,0 +1,66 @@ +@using System.ComponentModel.DataAnnotations + + + + +
    + +
    + + +
    +
    + +
    + +
    + + +
    +
    + +
    +
    + + +
    +
    + +
    + +@code { + private Employee employee = new(); + private EditContext? editContext; + + protected override void OnInitialized() + { + editContext = new EditContext(employee); + base.OnInitialized(); + } + + public void HandleOnValidSubmit() + { + // additional check + if (editContext.Validate()) + { + // do something + // submit the form + Console.WriteLine("Form submitted successfully"); + } + } + + private void ResetForm() + { + employee = new(); + editContext = new EditContext(employee); + } + + public class Employee + { + [Required(ErrorMessage = "First name required.")] + public string? FirstName { get; set; } + + [Required(ErrorMessage = "Last name required.")] + public string? LastName { get; set; } + } +} diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/TextInput/TextInput_Demo_06_Events_ValueChanged.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/TextInput/TextInput_Demo_06_Events_ValueChanged.razor new file mode 100644 index 000000000..32832d708 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/TextInput/TextInput_Demo_06_Events_ValueChanged.razor @@ -0,0 +1,15 @@ +
    + +
    +
    Entered employee name: @employeeName
    + +@code { + private string? employeeName = null; + + private void EmployeeNameChanged(string? value) + { + employeeName = value; + + // do something + } +} diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Form/TimeInput/TimeInputDocumentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/TimeInput/TimeInputDocumentation.razor similarity index 90% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Form/TimeInput/TimeInputDocumentation.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/TimeInput/TimeInputDocumentation.razor index ca30dd5e3..8333d851c 100644 --- a/BlazorBootstrap.Demo.RCL/Components/Pages/Form/TimeInput/TimeInputDocumentation.razor +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/TimeInput/TimeInputDocumentation.razor @@ -1,17 +1,16 @@ @page "/time-input" @attribute [Route(pageUrl)] +@layout DemosMainLayout - + - - @pageDescription - - - +
    @@ -76,7 +75,7 @@
    @code { - private const string pageUrl = RouteConstants.Demos_TimeInput_Documentation; + private const string pageUrl = DemoRouteConstants.Demos_URL_TimeInput; private const string pageTitle = "Blazor TimeInput"; private const string pageDescription = "The Blazor Bootstrap TimeInput component is constructed using an HTML input of type 'time' which limits user input based on pre-defined parameters. This component enables users to input a time using a text box with validation or a special time picker interface."; private const string metaTitle = "Blazor TimeInput Component"; diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Form/TimeInput/TimeInput_Demo_01_Basic_Usage.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/TimeInput/TimeInput_Demo_01_Basic_Usage.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Form/TimeInput/TimeInput_Demo_01_Basic_Usage.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/TimeInput/TimeInput_Demo_01_Basic_Usage.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Form/TimeInput/TimeInput_Demo_02_Generic_Type.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/TimeInput/TimeInput_Demo_02_Generic_Type.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Form/TimeInput/TimeInput_Demo_02_Generic_Type.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/TimeInput/TimeInput_Demo_02_Generic_Type.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Form/TimeInput/TimeInput_Demo_03_Max_Min.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/TimeInput/TimeInput_Demo_03_Max_Min.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Form/TimeInput/TimeInput_Demo_03_Max_Min.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/TimeInput/TimeInput_Demo_03_Max_Min.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Form/TimeInput/TimeInput_Demo_04_A_Disable.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/TimeInput/TimeInput_Demo_04_A_Disable.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Form/TimeInput/TimeInput_Demo_04_A_Disable.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/TimeInput/TimeInput_Demo_04_A_Disable.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Form/TimeInput/TimeInput_Demo_04_B_Disable.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/TimeInput/TimeInput_Demo_04_B_Disable.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Form/TimeInput/TimeInput_Demo_04_B_Disable.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/TimeInput/TimeInput_Demo_04_B_Disable.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Form/TimeInput/TimeInput_Demo_05_Validations.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/TimeInput/TimeInput_Demo_05_Validations.razor similarity index 94% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Form/TimeInput/TimeInput_Demo_05_Validations.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/TimeInput/TimeInput_Demo_05_Validations.razor index d5f0b6901..3f72576f9 100644 --- a/BlazorBootstrap.Demo.RCL/Components/Pages/Form/TimeInput/TimeInput_Demo_05_Validations.razor +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/TimeInput/TimeInput_Demo_05_Validations.razor @@ -1,19 +1,5 @@ @using System.ComponentModel.DataAnnotations - - diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Form/TimeInput/TimeInput_Demo_06_Events_Value_Changed.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/TimeInput/TimeInput_Demo_06_Events_Value_Changed.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Form/TimeInput/TimeInput_Demo_06_Events_Value_Changed.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/TimeInput/TimeInput_Demo_06_Events_Value_Changed.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Form/TimeInput/TimeInput_Demo_07_Restrict_The_Time_Field_Based_On_The_Entry_In_Another_Time_Field.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/TimeInput/TimeInput_Demo_07_Restrict_The_Time_Field_Based_On_The_Entry_In_Another_Time_Field.razor similarity index 94% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Form/TimeInput/TimeInput_Demo_07_Restrict_The_Time_Field_Based_On_The_Entry_In_Another_Time_Field.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/TimeInput/TimeInput_Demo_07_Restrict_The_Time_Field_Based_On_The_Entry_In_Another_Time_Field.razor index 9a97fff3f..24f51cd3a 100644 --- a/BlazorBootstrap.Demo.RCL/Components/Pages/Form/TimeInput/TimeInput_Demo_07_Restrict_The_Time_Field_Based_On_The_Entry_In_Another_Time_Field.razor +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Form/TimeInput/TimeInput_Demo_07_Restrict_The_Time_Field_Based_On_The_Entry_In_Another_Time_Field.razor @@ -1,19 +1,5 @@ @using System.ComponentModel.DataAnnotations - - diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/GettingStarted/GettingStartedDocumentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/GettingStarted/GettingStartedDocumentation.razor new file mode 100644 index 000000000..1aa03ba73 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/GettingStarted/GettingStartedDocumentation.razor @@ -0,0 +1,35 @@ +@page "/demos" +@page "/getting-started/blazor-webassembly" +@page "/getting-started/blazor-server" +@page "/getting-started/maui-blazor" +@attribute [Route(pageUrl)] +@layout DemosMainLayout + + + +
    + +
    + +@code { + private const string pageUrl = DemoRouteConstants.Demos_URL_GettingStarted; + private const string pageTitle = "Getting started with Blazor Bootstrap - Blazor Project Setup"; + private const string pageDescription = "High-performance, lightweight, and responsive blazor bootstrap components in a single package from the developers for the developers."; + private const string metaTitle = "Getting started with Blazor Bootstrap - Blazor Project Setup"; + private const string metaDescription = "High-performance, lightweight, and responsive blazor bootstrap components in a single package from the developers for the developers."; + private const string imageUrl = "https://i.imgur.com/SCbZVd4.jpg"; // TODO: Update image URL + + private string? version; + [Inject] public IConfiguration Configuration { get; set; } = default!; + + protected override void OnInitialized() + { + version = Configuration["version"]; // example: v3.5.0 + base.OnInitialized(); + } +} diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Grid/01-Overview/Grid_Demo_01_Client_Side_Filtering_Paging_And_Sorting.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/01-Overview/Grid_Demo_01_Client_Side_Filtering_Paging_And_Sorting.razor similarity index 93% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Grid/01-Overview/Grid_Demo_01_Client_Side_Filtering_Paging_And_Sorting.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/01-Overview/Grid_Demo_01_Client_Side_Filtering_Paging_And_Sorting.razor index 1cd6dcb42..4bd565772 100644 --- a/BlazorBootstrap.Demo.RCL/Components/Pages/Grid/01-Overview/Grid_Demo_01_Client_Side_Filtering_Paging_And_Sorting.razor +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/01-Overview/Grid_Demo_01_Client_Side_Filtering_Paging_And_Sorting.razor @@ -1,20 +1,21 @@ - + SelectionMode="GridSelectionMode.Multiple"> @context.Id - + @context.Name diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Grid/01-Overview/Grid_Demo_02_Server_Side_Filtering_Paging_And_Sorting.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/01-Overview/Grid_Demo_02_Server_Side_Filtering_Paging_And_Sorting.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Grid/01-Overview/Grid_Demo_02_Server_Side_Filtering_Paging_And_Sorting.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/01-Overview/Grid_Demo_02_Server_Side_Filtering_Paging_And_Sorting.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Grid/01-Overview/Grid_Overview_Documentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/01-Overview/Grid_Overview_Documentation.razor similarity index 72% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Grid/01-Overview/Grid_Overview_Documentation.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/01-Overview/Grid_Overview_Documentation.razor index adf4edaa6..b44a816b3 100644 --- a/BlazorBootstrap.Demo.RCL/Components/Pages/Grid/01-Overview/Grid_Overview_Documentation.razor +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/01-Overview/Grid_Overview_Documentation.razor @@ -1,17 +1,16 @@ @page "/grid" @attribute [Route(pageUrl)] +@layout DemosMainLayout - + - - @pageDescription - - - +
    @@ -22,7 +21,7 @@
    @code { - private const string pageUrl = RouteConstants.Demos_Grid_Overview_Documentation; + private const string pageUrl = DemoRouteConstants.Demos_URL_Grid_Overview; private const string pageTitle = "Blazor Grid"; private const string pageDescription = "Use Blazor Bootstrap grid component to display tabular data from the data source. And it supports client-side and server-side filtering, paging, and sorting."; private const string metaTitle = "Blazor Grid Component"; diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Grid/02-data-binding/Grid_DataBinding_Documentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/02-data-binding/Grid_DataBinding_Documentation.razor similarity index 82% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Grid/02-data-binding/Grid_DataBinding_Documentation.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/02-data-binding/Grid_DataBinding_Documentation.razor index 238af3097..0db50c978 100644 --- a/BlazorBootstrap.Demo.RCL/Components/Pages/Grid/02-data-binding/Grid_DataBinding_Documentation.razor +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/02-data-binding/Grid_DataBinding_Documentation.razor @@ -1,15 +1,14 @@ @attribute [Route(pageUrl)] +@layout DemosMainLayout - + - - @pageDescription - - - +
    Assign a collection to the Data parameter to render the grid dynamically. The example below will render different department employees in the individual grid.
    @@ -31,7 +30,7 @@
    @code { - private const string pageUrl = RouteConstants.Demos_Grid_DataBinding_Documentation; + private const string pageUrl = DemoRouteConstants.Demos_URL_Grid_DataBinding; private const string pageTitle = "Blazor Grid - Data binding"; private const string pageDescription = "Use Blazor Bootstrap grid component to display tabular data from the data source. And it supports client-side and server-side filtering, paging, and sorting."; private const string metaTitle = "Blazor Grid Component - Data binding"; diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Grid/02-data-binding/Grid_Demo_01_Data_Parameter_Assign_Collection.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/02-data-binding/Grid_Demo_01_Data_Parameter_Assign_Collection.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Grid/02-data-binding/Grid_Demo_01_Data_Parameter_Assign_Collection.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/02-data-binding/Grid_Demo_01_Data_Parameter_Assign_Collection.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Grid/02-data-binding/Grid_Demo_02_Data_Parameter_Update_Collection.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/02-data-binding/Grid_Demo_02_Data_Parameter_Update_Collection.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Grid/02-data-binding/Grid_Demo_02_Data_Parameter_Update_Collection.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/02-data-binding/Grid_Demo_02_Data_Parameter_Update_Collection.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Grid/03-filters/Grid_Demo_01_A_Client_Side_Filtering.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/03-filters/Grid_Demo_01_A_Client_Side_Filtering.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Grid/03-filters/Grid_Demo_01_A_Client_Side_Filtering.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/03-filters/Grid_Demo_01_A_Client_Side_Filtering.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Grid/03-filters/Grid_Demo_01_B_Client_Side_Filtering_With_StringComparision.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/03-filters/Grid_Demo_01_B_Client_Side_Filtering_With_StringComparision.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Grid/03-filters/Grid_Demo_01_B_Client_Side_Filtering_With_StringComparision.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/03-filters/Grid_Demo_01_B_Client_Side_Filtering_With_StringComparision.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Grid/03-filters/Grid_Demo_02_Set_Default_Filter.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/03-filters/Grid_Demo_02_Set_Default_Filter.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Grid/03-filters/Grid_Demo_02_Set_Default_Filter.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/03-filters/Grid_Demo_02_Set_Default_Filter.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Grid/03-filters/Grid_Demo_03_Disable_Specific_Column_Filter.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/03-filters/Grid_Demo_03_Disable_Specific_Column_Filter.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Grid/03-filters/Grid_Demo_03_Disable_Specific_Column_Filter.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/03-filters/Grid_Demo_03_Disable_Specific_Column_Filter.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Grid/03-filters/Grid_Demo_04_Increase_Filter_Textbox_Width.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/03-filters/Grid_Demo_04_Increase_Filter_Textbox_Width.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Grid/03-filters/Grid_Demo_04_Increase_Filter_Textbox_Width.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/03-filters/Grid_Demo_04_Increase_Filter_Textbox_Width.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Grid/03-filters/Grid_Demo_05_Enum_Filters.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/03-filters/Grid_Demo_05_Enum_Filters.razor similarity index 87% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Grid/03-filters/Grid_Demo_05_Enum_Filters.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/03-filters/Grid_Demo_05_Enum_Filters.razor index f642a5b1d..ba0ae61ba 100644 --- a/BlazorBootstrap.Demo.RCL/Components/Pages/Grid/03-filters/Grid_Demo_05_Enum_Filters.razor +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/03-filters/Grid_Demo_05_Enum_Filters.razor @@ -1,4 +1,6 @@ - - @context.Status + @(typeof(UserStatus).GetDisplayName(context.Status.ToString()))
    @@ -60,7 +62,15 @@ public enum UserStatus { Registered, + + [Display(Name = nameof(UserStatusLabels.VerificationPending), ResourceType = typeof(UserStatusLabels))] VerificationPending, + Verified } -} \ No newline at end of file + + public static class UserStatusLabels + { + public static string VerificationPending => "Pending Verification"; + } +} diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Grid/03-filters/Grid_Demo_06_Guid_Filters.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/03-filters/Grid_Demo_06_Guid_Filters.razor similarity index 93% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Grid/03-filters/Grid_Demo_06_Guid_Filters.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/03-filters/Grid_Demo_06_Guid_Filters.razor index 9d226d025..16c622a18 100644 --- a/BlazorBootstrap.Demo.RCL/Components/Pages/Grid/03-filters/Grid_Demo_06_Guid_Filters.razor +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/03-filters/Grid_Demo_06_Guid_Filters.razor @@ -1,4 +1,6 @@ - - @context.Status + @(typeof(UserStatus).GetDisplayName(context.Status.ToString())) @@ -64,6 +66,7 @@ public enum UserStatus { Registered, + [Display(Name = "Pending Verification")] VerificationPending, Verified } diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Grid/03-filters/Grid_Filters_Documentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/03-filters/Grid_Filters_Documentation.razor similarity index 86% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Grid/03-filters/Grid_Filters_Documentation.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/03-filters/Grid_Filters_Documentation.razor index 5b2854421..64823563a 100644 --- a/BlazorBootstrap.Demo.RCL/Components/Pages/Grid/03-filters/Grid_Filters_Documentation.razor +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/03-filters/Grid_Filters_Documentation.razor @@ -1,15 +1,14 @@ @attribute [Route(pageUrl)] +@layout DemosMainLayout - + - - @pageDescription - - - +
    For filtering, AllowFiltering and PropertyName parameters are required.
    @@ -58,6 +57,7 @@
    +
    Enum filter labels use DisplayAttribute.GetName() when a DisplayAttribute is present, including resource-backed names, and fall back to the enum member name.
    @@ -66,7 +66,7 @@ @code { - private const string pageUrl = RouteConstants.Demos_Grid_Filters_Documentation; + private const string pageUrl = DemoRouteConstants.Demos_URL_Grid_Filters; private const string pageTitle = "Blazor Grid - Filters"; private const string pageDescription = "Use Blazor Bootstrap grid component to display tabular data from the data source. And it supports client-side and server-side filtering, paging, and sorting."; private const string metaTitle = "Blazor Grid Component - Filters"; diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Grid/04-paging/Grid_Demo_02_Client_Side_Paging.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/04-paging/Grid_Demo_01_Client_Side_Paging.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Grid/04-paging/Grid_Demo_02_Client_Side_Paging.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/04-paging/Grid_Demo_01_Client_Side_Paging.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Grid/04-paging/Grid_Demo_25_Dynamic_Page_Size.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/04-paging/Grid_Demo_02_Dynamic_Page_Size.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Grid/04-paging/Grid_Demo_25_Dynamic_Page_Size.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/04-paging/Grid_Demo_02_Dynamic_Page_Size.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Grid/04-paging/Grid_Demo_26_Page_Size_Selection.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/04-paging/Grid_Demo_03_Page_Size_Selection.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Grid/04-paging/Grid_Demo_26_Page_Size_Selection.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/04-paging/Grid_Demo_03_Page_Size_Selection.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Grid/04-paging/Grid_Demo_34_AutoHide_Paging.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/04-paging/Grid_Demo_04_AutoHide_Paging.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Grid/04-paging/Grid_Demo_34_AutoHide_Paging.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/04-paging/Grid_Demo_04_AutoHide_Paging.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/04-paging/Grid_Demo_05_Dynamic_Pagination.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/04-paging/Grid_Demo_05_Dynamic_Pagination.razor new file mode 100644 index 000000000..212c780a7 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/04-paging/Grid_Demo_05_Dynamic_Pagination.razor @@ -0,0 +1,96 @@ +
    + + +
    + + + + + + @context.Id + + + @context.Name + + + @context.Designation + + + @context.DOJ + + + @context.IsActive + + + + + +@code { + Grid grid = default!; + private List? employees = default!; + + private async Task> EmployeesDataProvider(GridDataProviderRequest request) + { + if (employees is null) // pull employees only one time for client-side filtering, sorting, and paging + employees = GetEmployees(); // call a service or an API to pull the employees + + return await Task.FromResult(request.ApplyTo(employees)); + } + + private List GetEmployees() + { + return new List + { + new Employee1 { Id = 107, Name = "Alice", Designation = "AI Engineer", DOJ = new DateOnly(1998, 11, 17), IsActive = true }, + new Employee1 { Id = 103, Name = "Bob", Designation = "Senior DevOps Engineer", DOJ = new DateOnly(1985, 1, 5), IsActive = true }, + new Employee1 { Id = 106, Name = "John", Designation = "Data Engineer", DOJ = new DateOnly(1995, 4, 17), IsActive = true }, + new Employee1 { Id = 104, Name = "Pop", Designation = "Associate Architect", DOJ = new DateOnly(1985, 6, 8), IsActive = false }, + new Employee1 { Id = 105, Name = "Ronald", Designation = "Senior Data Engineer", DOJ = new DateOnly(1991, 8, 23), IsActive = true }, + new Employee1 { Id = 102, Name = "Line", Designation = "Architect", DOJ = new DateOnly(1977, 1, 12), IsActive = true }, + new Employee1 { Id = 101, Name = "Daniel", Designation = "Architect", DOJ = new DateOnly(1977, 1, 12), IsActive = true }, + new Employee1 { Id = 113, Name = "Merlin", Designation = "Senior Consultant", DOJ = new DateOnly(1989, 10, 2), IsActive = true }, + new Employee1 { Id = 117, Name = "Sharna", Designation = "Data Analyst", DOJ = new DateOnly(1994, 5, 12), IsActive = true }, + new Employee1 { Id = 108, Name = "Zayne", Designation = "Data Analyst", DOJ = new DateOnly(1991, 1, 1), IsActive = true }, + new Employee1 { Id = 109, Name = "Isha", Designation = "App Maker", DOJ = new DateOnly(1996, 7, 1), IsActive = true }, + new Employee1 { Id = 111, Name = "Glenda", Designation = "Data Engineer", DOJ = new DateOnly(1994, 1, 12), IsActive = true }, + }; + } + + private async Task AddEmployee() + { + if(employees is null) + employees = new(); + + // for the same employees collection, we are adding an object + // explicit grid refresh required + employees.Add(CreateEmployee()); + await grid.RefreshDataAsync(); + } + + private Employee1 CreateEmployee() + { + var emp = new Employee1(); + emp.Id = (employees?.Any() ?? false) ? employees.Max(x => x.Id) + 1 : 1; + emp.Name = $"Employee {emp.Id}"; + emp.Designation = $"QA Engineer {emp.Id}"; + emp.DOJ = new DateOnly(new Random().Next(1970, 2000), new Random().Next(1, 12), new Random().Next(1, 25)); + emp.IsActive = true; + return emp; + } + + private async Task RemoveEmployee() + { + if (employees!.Count > 0) + employees!.Remove(employees.Last()); + + await grid.RefreshDataAsync(); + } +} \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Grid/04-paging/Grid_Paging_Documentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/04-paging/Grid_Paging_Documentation.razor similarity index 63% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Grid/04-paging/Grid_Paging_Documentation.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/04-paging/Grid_Paging_Documentation.razor index 959fe0faf..f70e02312 100644 --- a/BlazorBootstrap.Demo.RCL/Components/Pages/Grid/04-paging/Grid_Paging_Documentation.razor +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/04-paging/Grid_Paging_Documentation.razor @@ -1,39 +1,42 @@ @attribute [Route(pageUrl)] +@layout DemosMainLayout - + - - @pageDescription - - - +
    For paging, AllowPaging and PageSize parameters are required.
    Add AllowPaging="true" and PageSize="20" parameters to the Grid. PageSize parameter is optional.
    The default page size is 10. - +
    - +
    - +
    - + +
    + +
    +
    @code { - private const string pageUrl = RouteConstants.Demos_Grid_Paging_Documentation; + private const string pageUrl = DemoRouteConstants.Demos_URL_Grid_Paging; private const string pageTitle = "Blazor Grid - Paging"; private const string pageDescription = "Use Blazor Bootstrap grid component to display tabular data from the data source. And it supports client-side and server-side filtering, paging, and sorting."; private const string metaTitle = "Blazor Grid Component - Paging"; diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Grid/05-sorting/Grid_Demo_03_Client_Side_Sorting.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/05-sorting/Grid_Demo_03_Client_Side_Sorting.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Grid/05-sorting/Grid_Demo_03_Client_Side_Sorting.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/05-sorting/Grid_Demo_03_Client_Side_Sorting.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Grid/05-sorting/Grid_Demo_08_Default_Sorting.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/05-sorting/Grid_Demo_08_Default_Sorting.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Grid/05-sorting/Grid_Demo_08_Default_Sorting.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/05-sorting/Grid_Demo_08_Default_Sorting.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Grid/05-sorting/Grid_Demo_09_Disable_Specific_Column_Sorting.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/05-sorting/Grid_Demo_09_Disable_Specific_Column_Sorting.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Grid/05-sorting/Grid_Demo_09_Disable_Specific_Column_Sorting.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/05-sorting/Grid_Demo_09_Disable_Specific_Column_Sorting.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Grid/05-sorting/Grid_Sorting_Documentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/05-sorting/Grid_Sorting_Documentation.razor similarity index 84% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Grid/05-sorting/Grid_Sorting_Documentation.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/05-sorting/Grid_Sorting_Documentation.razor index 256ed0b4d..ce108676c 100644 --- a/BlazorBootstrap.Demo.RCL/Components/Pages/Grid/05-sorting/Grid_Sorting_Documentation.razor +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/05-sorting/Grid_Sorting_Documentation.razor @@ -1,15 +1,14 @@ @attribute [Route(pageUrl)] +@layout DemosMainLayout - + - - @pageDescription - - - +
    For sorting, AllowSorting and SortKeySelector parameters are required.
    @@ -31,7 +30,7 @@
    @code { - private const string pageUrl = RouteConstants.Demos_Grid_Sorting_Documentation; + private const string pageUrl = DemoRouteConstants.Demos_URL_Grid_Sorting; private const string pageTitle = "Blazor Grid - Sorting"; private const string pageDescription = "Use Blazor Bootstrap grid component to display tabular data from the data source. And it supports client-side and server-side filtering, paging, and sorting."; private const string metaTitle = "Blazor Grid Component - Sorting"; diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Grid/06-selection/Grid_Demo_01_Selection.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/06-selection/Grid_Demo_01_A_Selection.razor similarity index 92% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Grid/06-selection/Grid_Demo_01_Selection.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/06-selection/Grid_Demo_01_A_Selection.razor index 35b337d05..85bd2d09c 100644 --- a/BlazorBootstrap.Demo.RCL/Components/Pages/Grid/06-selection/Grid_Demo_01_Selection.razor +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/06-selection/Grid_Demo_01_A_Selection.razor @@ -2,7 +2,7 @@ Class="table table-hover table-bordered" DataProvider="EmployeesDataProvider" AllowSelection="true" - SelectedItemsChanged="OnSelectedItemsChanged" + @bind-SelectedItems="@selectedEmployees" Responsive="true"> @@ -69,10 +69,4 @@ new Employee1 { Id = 109, Name = "Isha", Designation = "App Maker", DOJ = new DateOnly(1996, 7, 1), IsActive = true }, }; } - - private Task OnSelectedItemsChanged(HashSet employees) - { - selectedEmployees = employees is not null && employees.Any() ? employees : new(); - return Task.CompletedTask; - } } \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/06-selection/Grid_Demo_01_B_Default_Selection.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/06-selection/Grid_Demo_01_B_Default_Selection.razor new file mode 100644 index 000000000..95275229c --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/06-selection/Grid_Demo_01_B_Default_Selection.razor @@ -0,0 +1,74 @@ + + + + + @context.Id + + + @context.Name + + + @context.Designation + + + @context.DOJ + + + @context.IsActive + + + + + +
    + Selected Items Count: @selectedEmployees.Count +
    + +
    + Selected Employees: +
      + @foreach (var emp in selectedEmployees) + { +
    • @emp.Name
    • + } +
    +
    + +@code { + private IEnumerable employees = default!; + + private HashSet selectedEmployees = new(){ + new Employee1 { Id = 102, Name = "Line", Designation = "Architect", DOJ = new DateOnly(1977, 1, 12), IsActive = true } + }; + + private async Task> EmployeesDataProvider(GridDataProviderRequest request) + { + Console.WriteLine("EmployeesDataProvider called..."); + + if (employees is null) // pull employees only one time for client-side filtering, sorting, and paging + employees = GetEmployees(); // call a service or an API to pull the employees + + return await Task.FromResult(request.ApplyTo(employees)); + } + + private IEnumerable GetEmployees() + { + return new List + { + new Employee1 { Id = 107, Name = "Alice", Designation = "AI Engineer", DOJ = new DateOnly(1998, 11, 17), IsActive = true }, + new Employee1 { Id = 103, Name = "Bob", Designation = "Senior DevOps Engineer", DOJ = new DateOnly(1985, 1, 5), IsActive = true }, + new Employee1 { Id = 106, Name = "John", Designation = "Data Engineer", DOJ = new DateOnly(1995, 4, 17), IsActive = true }, + new Employee1 { Id = 104, Name = "Pop", Designation = "Associate Architect", DOJ = new DateOnly(1985, 6, 8), IsActive = false }, + new Employee1 { Id = 105, Name = "Ronald", Designation = "Senior Data Engineer", DOJ = new DateOnly(1991, 8, 23), IsActive = true }, + new Employee1 { Id = 102, Name = "Line", Designation = "Architect", DOJ = new DateOnly(1977, 1, 12), IsActive = true }, + new Employee1 { Id = 101, Name = "Daniel", Designation = "Architect", DOJ = new DateOnly(1977, 1, 12), IsActive = true }, + new Employee1 { Id = 108, Name = "Zayne", Designation = "Data Analyst", DOJ = new DateOnly(1991, 1, 1), IsActive = true }, + new Employee1 { Id = 109, Name = "Isha", Designation = "App Maker", DOJ = new DateOnly(1996, 7, 1), IsActive = true }, + }; + } +} \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Grid/06-selection/Grid_Demo_02_Multiple_Selection.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/06-selection/Grid_Demo_02_A_Multiple_Selection.razor similarity index 89% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Grid/06-selection/Grid_Demo_02_Multiple_Selection.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/06-selection/Grid_Demo_02_A_Multiple_Selection.razor index caf8cab3b..503717be0 100644 --- a/BlazorBootstrap.Demo.RCL/Components/Pages/Grid/06-selection/Grid_Demo_02_Multiple_Selection.razor +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/06-selection/Grid_Demo_02_A_Multiple_Selection.razor @@ -4,7 +4,7 @@ AllowFiltering="true" AllowSelection="true" SelectionMode="GridSelectionMode.Multiple" - SelectedItemsChanged="OnSelectedItemsChanged" + @bind-SelectedItems="@selectedEmployees" Responsive="true"> @@ -44,7 +44,10 @@ @code { private IEnumerable employees = default!; - private HashSet selectedEmployees = new(); + private HashSet selectedEmployees = new(){ + new Employee1 { Id = 102, Name = "Line", Designation = "Architect", DOJ = new DateOnly(1977, 1, 12), IsActive = true }, + new Employee1 { Id = 101, Name = "Daniel", Designation = "Architect", DOJ = new DateOnly(1977, 1, 12), IsActive = true }, + }; private async Task> EmployeesDataProvider(GridDataProviderRequest request) { @@ -71,10 +74,4 @@ new Employee1 { Id = 109, Name = "Isha", Designation = "App Maker", DOJ = new DateOnly(1996, 7, 1), IsActive = true }, }; } - - private Task OnSelectedItemsChanged(HashSet employees) - { - selectedEmployees = employees is not null && employees.Any() ? employees : new(); - return Task.CompletedTask; - } } \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/06-selection/Grid_Demo_02_B_Multiple_Selection_Programmatically.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/06-selection/Grid_Demo_02_B_Multiple_Selection_Programmatically.razor new file mode 100644 index 000000000..8183601f0 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/06-selection/Grid_Demo_02_B_Multiple_Selection_Programmatically.razor @@ -0,0 +1,90 @@ +
    + + +
    + + + + + + @context.Id + + + @context.Name + + + @context.Designation + + + @context.DOJ + + + @context.IsActive + + + + + +
    + Selected Items Count: @selectedEmployees.Count +
    + +
    + Selected Employees: +
      + @foreach (var emp in selectedEmployees) + { +
    • @emp.Name
    • + } +
    +
    + +@code { + private Grid gridRef; + private IEnumerable employees = default!; + + private HashSet selectedEmployees = new(); + + private async Task> EmployeesDataProvider(GridDataProviderRequest request) + { + Console.WriteLine("EmployeesDataProvider called..."); + + if (employees is null) // pull employees only one time for client-side filtering, sorting, and paging + employees = GetEmployees(); // call a service or an API to pull the employees + + return await Task.FromResult(request.ApplyTo(employees)); + } + + private IEnumerable GetEmployees() + { + return new List + { + new Employee1 { Id = 107, Name = "Alice", Designation = "AI Engineer", DOJ = new DateOnly(1998, 11, 17), IsActive = true }, + new Employee1 { Id = 103, Name = "Bob", Designation = "Senior DevOps Engineer", DOJ = new DateOnly(1985, 1, 5), IsActive = true }, + new Employee1 { Id = 106, Name = "John", Designation = "Data Engineer", DOJ = new DateOnly(1995, 4, 17), IsActive = true }, + new Employee1 { Id = 104, Name = "Pop", Designation = "Associate Architect", DOJ = new DateOnly(1985, 6, 8), IsActive = false }, + new Employee1 { Id = 105, Name = "Ronald", Designation = "Senior Data Engineer", DOJ = new DateOnly(1991, 8, 23), IsActive = true }, + new Employee1 { Id = 102, Name = "Line", Designation = "Architect", DOJ = new DateOnly(1977, 1, 12), IsActive = true }, + new Employee1 { Id = 101, Name = "Daniel", Designation = "Architect", DOJ = new DateOnly(1977, 1, 12), IsActive = true }, + new Employee1 { Id = 108, Name = "Zayne", Designation = "Data Analyst", DOJ = new DateOnly(1991, 1, 1), IsActive = true }, + new Employee1 { Id = 109, Name = "Isha", Designation = "App Maker", DOJ = new DateOnly(1996, 7, 1), IsActive = true }, + }; + } + + private Task OnSelectedItemsChanged(HashSet employees) + { + selectedEmployees = employees is not null && employees.Any() ? employees : new(); + return Task.CompletedTask; + } + + private Task SelectAllEmployees() => gridRef.SelectAllItemsAsync(); + + private Task UnselectAllEmployees() => gridRef.UnSelectAllItemsAsync(); +} \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/06-selection/Grid_Demo_02_C_Multiple_Selection_Default_Programmatically.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/06-selection/Grid_Demo_02_C_Multiple_Selection_Default_Programmatically.razor new file mode 100644 index 000000000..8183601f0 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/06-selection/Grid_Demo_02_C_Multiple_Selection_Default_Programmatically.razor @@ -0,0 +1,90 @@ +
    + + +
    + + + + + + @context.Id + + + @context.Name + + + @context.Designation + + + @context.DOJ + + + @context.IsActive + + + + + +
    + Selected Items Count: @selectedEmployees.Count +
    + +
    + Selected Employees: +
      + @foreach (var emp in selectedEmployees) + { +
    • @emp.Name
    • + } +
    +
    + +@code { + private Grid gridRef; + private IEnumerable employees = default!; + + private HashSet selectedEmployees = new(); + + private async Task> EmployeesDataProvider(GridDataProviderRequest request) + { + Console.WriteLine("EmployeesDataProvider called..."); + + if (employees is null) // pull employees only one time for client-side filtering, sorting, and paging + employees = GetEmployees(); // call a service or an API to pull the employees + + return await Task.FromResult(request.ApplyTo(employees)); + } + + private IEnumerable GetEmployees() + { + return new List + { + new Employee1 { Id = 107, Name = "Alice", Designation = "AI Engineer", DOJ = new DateOnly(1998, 11, 17), IsActive = true }, + new Employee1 { Id = 103, Name = "Bob", Designation = "Senior DevOps Engineer", DOJ = new DateOnly(1985, 1, 5), IsActive = true }, + new Employee1 { Id = 106, Name = "John", Designation = "Data Engineer", DOJ = new DateOnly(1995, 4, 17), IsActive = true }, + new Employee1 { Id = 104, Name = "Pop", Designation = "Associate Architect", DOJ = new DateOnly(1985, 6, 8), IsActive = false }, + new Employee1 { Id = 105, Name = "Ronald", Designation = "Senior Data Engineer", DOJ = new DateOnly(1991, 8, 23), IsActive = true }, + new Employee1 { Id = 102, Name = "Line", Designation = "Architect", DOJ = new DateOnly(1977, 1, 12), IsActive = true }, + new Employee1 { Id = 101, Name = "Daniel", Designation = "Architect", DOJ = new DateOnly(1977, 1, 12), IsActive = true }, + new Employee1 { Id = 108, Name = "Zayne", Designation = "Data Analyst", DOJ = new DateOnly(1991, 1, 1), IsActive = true }, + new Employee1 { Id = 109, Name = "Isha", Designation = "App Maker", DOJ = new DateOnly(1996, 7, 1), IsActive = true }, + }; + } + + private Task OnSelectedItemsChanged(HashSet employees) + { + selectedEmployees = employees is not null && employees.Any() ? employees : new(); + return Task.CompletedTask; + } + + private Task SelectAllEmployees() => gridRef.SelectAllItemsAsync(); + + private Task UnselectAllEmployees() => gridRef.UnSelectAllItemsAsync(); +} \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Grid/06-selection/Grid_Demo_03_Disable_Selection.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/06-selection/Grid_Demo_03_Disable_Selection.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Grid/06-selection/Grid_Demo_03_Disable_Selection.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/06-selection/Grid_Demo_03_Disable_Selection.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Grid/06-selection/Grid_Demo_04_A_Change_Selected_Row_Background_Color.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/06-selection/Grid_Demo_04_A_Change_Selected_Row_Background_Color.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Grid/06-selection/Grid_Demo_04_A_Change_Selected_Row_Background_Color.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/06-selection/Grid_Demo_04_A_Change_Selected_Row_Background_Color.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Grid/06-selection/Grid_Demo_04_B_Selected_Row_CSS_Variables.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/06-selection/Grid_Demo_04_B_Selected_Row_CSS_Variables.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Grid/06-selection/Grid_Demo_04_B_Selected_Row_CSS_Variables.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/06-selection/Grid_Demo_04_B_Selected_Row_CSS_Variables.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Grid/06-selection/Grid_Selection_Documentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/06-selection/Grid_Selection_Documentation.razor similarity index 62% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Grid/06-selection/Grid_Selection_Documentation.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/06-selection/Grid_Selection_Documentation.razor index a2c2fc9a2..0e36415a6 100644 --- a/BlazorBootstrap.Demo.RCL/Components/Pages/Grid/06-selection/Grid_Selection_Documentation.razor +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/06-selection/Grid_Selection_Documentation.razor @@ -1,29 +1,46 @@ @attribute [Route(pageUrl)] +@layout DemosMainLayout - + - - @pageDescription - - - +
    Set AllowSelection="true" to enable the selection on the Grid. By default, SelectionMode is Single.
    - + +
    + +
    +
    + Set AllowSelection="true" to enable the selection on the Grid. + By default, SelectionMode is Single. +
    +
    -
    +
    To select multiple rows, set SelectionMode="GridSelectionMode.Multiple".
    - + + +

    Selected items are removed from the selection if they are not rendered after paging, sorting, filtering, etc.

    +
    +
    + +
    +
    + Select or unselect all the items programatically by calling the SelectAllItemsAsync() and UnSelectAllItemsAsync() methods. Also, set SelectionMode="GridSelectionMode.Multiple". +
    +

    Selected items are removed from the selection if they are not rendered after paging, sorting, filtering, etc.

    @@ -48,7 +65,7 @@
    @code { - private const string pageUrl = RouteConstants.Demos_Grid_Selection_Documentation; + private const string pageUrl = DemoRouteConstants.Demos_URL_Grid_Selection; private const string pageTitle = "Blazor Grid - Selection"; private const string pageDescription = "Use Blazor Bootstrap grid component to display tabular data from the data source. And it supports client-side and server-side filtering, paging, and sorting."; private const string metaTitle = "Blazor Grid Component - Selection"; diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Grid/07-alignment/Grid_Alignment_Documentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/07-alignment/Grid_Alignment_Documentation.razor similarity index 78% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Grid/07-alignment/Grid_Alignment_Documentation.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/07-alignment/Grid_Alignment_Documentation.razor index 491475b2b..b46ca9472 100644 --- a/BlazorBootstrap.Demo.RCL/Components/Pages/Grid/07-alignment/Grid_Alignment_Documentation.razor +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/07-alignment/Grid_Alignment_Documentation.razor @@ -1,15 +1,14 @@ @attribute [Route(pageUrl)] +@layout DemosMainLayout - + - - @pageDescription - - - +
    Use the HeaderTextAlignment parameter to change the header column alignment. By default, HeaderTextAlignment is set to Alignment.Start. Other options you can use are Alignment.Center and Alignment.End.
    @@ -22,7 +21,7 @@
    @code { - private const string pageUrl = RouteConstants.Demos_Grid_Alignment_Documentation; + private const string pageUrl = DemoRouteConstants.Demos_URL_Grid_Alignment; private const string pageTitle = "Blazor Grid - Alignment"; private const string pageDescription = "Use Blazor Bootstrap grid component to display tabular data from the data source. And it supports client-side and server-side filtering, paging, and sorting."; private const string metaTitle = "Blazor Grid Component - Alignment"; diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Grid/07-alignment/Grid_Demo_10_Header_Text_Alignment.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/07-alignment/Grid_Demo_10_Header_Text_Alignment.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Grid/07-alignment/Grid_Demo_10_Header_Text_Alignment.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/07-alignment/Grid_Demo_10_Header_Text_Alignment.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Grid/07-alignment/Grid_Demo_11_Grid_Cell_Alignment.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/07-alignment/Grid_Demo_11_Grid_Cell_Alignment.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Grid/07-alignment/Grid_Demo_11_Grid_Cell_Alignment.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/07-alignment/Grid_Demo_11_Grid_Cell_Alignment.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Grid/08-grid-settings/Grid_Demo_16_Save_And_Load_Grid_Settings.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/08-grid-settings/Grid_Demo_16_Save_And_Load_Grid_Settings.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Grid/08-grid-settings/Grid_Demo_16_Save_And_Load_Grid_Settings.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/08-grid-settings/Grid_Demo_16_Save_And_Load_Grid_Settings.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Grid/08-grid-settings/Grid_GridSettings_Documentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/08-grid-settings/Grid_GridSettings_Documentation.razor similarity index 77% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Grid/08-grid-settings/Grid_GridSettings_Documentation.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/08-grid-settings/Grid_GridSettings_Documentation.razor index 9769c0440..b5baffa7c 100644 --- a/BlazorBootstrap.Demo.RCL/Components/Pages/Grid/08-grid-settings/Grid_GridSettings_Documentation.razor +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/08-grid-settings/Grid_GridSettings_Documentation.razor @@ -1,15 +1,14 @@ @attribute [Route(pageUrl)] +@layout DemosMainLayout - + - - @pageDescription - - - +
    This example shows how to save/load the Grid state. The state includes the page number, page size, and filters.
    @@ -19,7 +18,7 @@
    @code { - private const string pageUrl = RouteConstants.Demos_Grid_Settings_Documentation; + private const string pageUrl = DemoRouteConstants.Demos_URL_Grid_Settings; private const string pageTitle = "Blazor Grid - Settings"; private const string pageDescription = "Use Blazor Bootstrap grid component to display tabular data from the data source. And it supports client-side and server-side filtering, paging, and sorting."; private const string metaTitle = "Blazor Grid Component - Settings"; diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Grid/09-custom-css-class/Grid_CustomCSSClass_Documentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/09-custom-css-class/Grid_CustomCSSClass_Documentation.razor similarity index 84% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Grid/09-custom-css-class/Grid_CustomCSSClass_Documentation.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/09-custom-css-class/Grid_CustomCSSClass_Documentation.razor index 5665dd992..d6e32dc92 100644 --- a/BlazorBootstrap.Demo.RCL/Components/Pages/Grid/09-custom-css-class/Grid_CustomCSSClass_Documentation.razor +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/09-custom-css-class/Grid_CustomCSSClass_Documentation.razor @@ -1,15 +1,14 @@ @attribute [Route(pageUrl)] +@layout DemosMainLayout - + - - @pageDescription - - - +
    In the below example, we applied table-danger CSS class to the row where the employee is inactive and the table-success CSS class to the row where the employee designation is Architect.
    @@ -37,7 +36,7 @@
    @code { - private const string pageUrl = RouteConstants.Demos_Grid_CustomCSSClass_Documentation; + private const string pageUrl = DemoRouteConstants.Demos_URL_Grid_CustomCSSClass; private const string pageTitle = "Blazor Grid - Custom CSS Class"; private const string pageDescription = "Use Blazor Bootstrap grid component to display tabular data from the data source. And it supports client-side and server-side filtering, paging, and sorting."; private const string metaTitle = "Blazor Grid Component - Custom CSS Class"; diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Grid/09-custom-css-class/Grid_Demo_18_Specify_Custom_Row_Class.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/09-custom-css-class/Grid_Demo_18_Specify_Custom_Row_Class.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Grid/09-custom-css-class/Grid_Demo_18_Specify_Custom_Row_Class.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/09-custom-css-class/Grid_Demo_18_Specify_Custom_Row_Class.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Grid/09-custom-css-class/Grid_Demo_19_Specify_Custom_Column_Class.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/09-custom-css-class/Grid_Demo_19_Specify_Custom_Column_Class.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Grid/09-custom-css-class/Grid_Demo_19_Specify_Custom_Column_Class.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/09-custom-css-class/Grid_Demo_19_Specify_Custom_Column_Class.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Grid/09-custom-css-class/Grid_Demo_20_Column_Css_Class.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/09-custom-css-class/Grid_Demo_20_Column_Css_Class.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Grid/09-custom-css-class/Grid_Demo_20_Column_Css_Class.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/09-custom-css-class/Grid_Demo_20_Column_Css_Class.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Grid/09-custom-css-class/Grid_Demo_27_Header_Row_CSS_Class.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/09-custom-css-class/Grid_Demo_27_Header_Row_CSS_Class.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Grid/09-custom-css-class/Grid_Demo_27_Header_Row_CSS_Class.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/09-custom-css-class/Grid_Demo_27_Header_Row_CSS_Class.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Grid/09-custom-css-class/Grid_Demo_28_Filters_Row_CSS_Class.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/09-custom-css-class/Grid_Demo_28_Filters_Row_CSS_Class.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Grid/09-custom-css-class/Grid_Demo_28_Filters_Row_CSS_Class.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/09-custom-css-class/Grid_Demo_28_Filters_Row_CSS_Class.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Grid/10-events/Grid_Demo_29_Row_Click.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/10-events/Grid_Demo_29_Row_Click.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Grid/10-events/Grid_Demo_29_Row_Click.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/10-events/Grid_Demo_29_Row_Click.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Grid/10-events/Grid_Demo_30_Row_Double_Click.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/10-events/Grid_Demo_30_Row_Double_Click.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Grid/10-events/Grid_Demo_30_Row_Double_Click.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/10-events/Grid_Demo_30_Row_Double_Click.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Grid/10-events/Grid_Events_Documentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/10-events/Grid_Events_Documentation.razor similarity index 70% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Grid/10-events/Grid_Events_Documentation.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/10-events/Grid_Events_Documentation.razor index 3da3389f2..2cb459283 100644 --- a/BlazorBootstrap.Demo.RCL/Components/Pages/Grid/10-events/Grid_Events_Documentation.razor +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/10-events/Grid_Events_Documentation.razor @@ -1,15 +1,14 @@ @attribute [Route(pageUrl)] +@layout DemosMainLayout - + - - @pageDescription - - - +
    @@ -22,7 +21,7 @@
    @code { - private const string pageUrl = RouteConstants.Demos_Grid_Events_Documentation; + private const string pageUrl = DemoRouteConstants.Demos_URL_Grid_Events; private const string pageTitle = "Blazor Grid - Events"; private const string pageDescription = "Use Blazor Bootstrap grid component to display tabular data from the data source. And it supports client-side and server-side filtering, paging, and sorting."; private const string metaTitle = "Blazor Grid Component - Events"; diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Grid/11-translations/Grid_Demo_01_Translations.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/11-translations/Grid_Demo_01_Translations.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Grid/11-translations/Grid_Demo_01_Translations.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/11-translations/Grid_Demo_01_Translations.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Grid/11-translations/Grid_Translations_Documentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/11-translations/Grid_Translations_Documentation.razor similarity index 68% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Grid/11-translations/Grid_Translations_Documentation.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/11-translations/Grid_Translations_Documentation.razor index 7fae7fe21..b355d39c8 100644 --- a/BlazorBootstrap.Demo.RCL/Components/Pages/Grid/11-translations/Grid_Translations_Documentation.razor +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/11-translations/Grid_Translations_Documentation.razor @@ -1,15 +1,14 @@ @attribute [Route(pageUrl)] +@layout DemosMainLayout - + - - @pageDescription - - - +
    In the example below, you will see translations related to pagination and filters in Dutch.
    @@ -17,7 +16,7 @@
    @code { - private const string pageUrl = RouteConstants.Demos_Grid_Translations_Documentation; + private const string pageUrl = DemoRouteConstants.Demos_URL_Grid_Translations; private const string pageTitle = "Blazor Grid - Translations"; private const string pageDescription = "Use Blazor Bootstrap grid component to display tabular data from the data source. And it supports client-side and server-side filtering, paging, and sorting."; private const string metaTitle = "Blazor Grid Component - Translations"; diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Grid/12-fixed-header/Grid_Demo_32_Fixed_Header_A.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/12-fixed-header/Grid_Demo_32_Fixed_Header_A.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Grid/12-fixed-header/Grid_Demo_32_Fixed_Header_A.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/12-fixed-header/Grid_Demo_32_Fixed_Header_A.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Grid/12-fixed-header/Grid_Demo_32_Fixed_Header_B_With_Filters.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/12-fixed-header/Grid_Demo_32_Fixed_Header_B_With_Filters.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Grid/12-fixed-header/Grid_Demo_32_Fixed_Header_B_With_Filters.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/12-fixed-header/Grid_Demo_32_Fixed_Header_B_With_Filters.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Grid/12-fixed-header/Grid_FixedHeader_Documentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/12-fixed-header/Grid_FixedHeader_Documentation.razor similarity index 74% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Grid/12-fixed-header/Grid_FixedHeader_Documentation.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/12-fixed-header/Grid_FixedHeader_Documentation.razor index 7ba88932c..d6b82cbf2 100644 --- a/BlazorBootstrap.Demo.RCL/Components/Pages/Grid/12-fixed-header/Grid_FixedHeader_Documentation.razor +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/12-fixed-header/Grid_FixedHeader_Documentation.razor @@ -1,15 +1,14 @@ @attribute [Route(pageUrl)] +@layout DemosMainLayout - + - - @pageDescription - - - +
    @@ -24,7 +23,7 @@
    @code { - private const string pageUrl = RouteConstants.Demos_Grid_FixedHeader_Documentation; + private const string pageUrl = DemoRouteConstants.Demos_URL_Grid_FixedHeader; private const string pageTitle = "Blazor Grid - Fixed header"; private const string pageDescription = "Use Blazor Bootstrap grid component to display tabular data from the data source. And it supports client-side and server-side filtering, paging, and sorting."; private const string metaTitle = "Blazor Grid Component - Fixed header"; diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Grid/13-freeze-columns/Grid_Demo_33_Freeze_Column_A_Text_Nowrap.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/13-freeze-columns/Grid_Demo_33_Freeze_Column_A_Text_Nowrap.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Grid/13-freeze-columns/Grid_Demo_33_Freeze_Column_A_Text_Nowrap.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/13-freeze-columns/Grid_Demo_33_Freeze_Column_A_Text_Nowrap.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Grid/13-freeze-columns/Grid_Demo_33_Freeze_Column_B_Fixed_Header.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/13-freeze-columns/Grid_Demo_33_Freeze_Column_B_Fixed_Header.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Grid/13-freeze-columns/Grid_Demo_33_Freeze_Column_B_Fixed_Header.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/13-freeze-columns/Grid_Demo_33_Freeze_Column_B_Fixed_Header.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Grid/13-freeze-columns/Grid_Demo_33_Freeze_Column_C_Fixed_Header_With_Filters.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/13-freeze-columns/Grid_Demo_33_Freeze_Column_C_Fixed_Header_With_Filters.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Grid/13-freeze-columns/Grid_Demo_33_Freeze_Column_C_Fixed_Header_With_Filters.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/13-freeze-columns/Grid_Demo_33_Freeze_Column_C_Fixed_Header_With_Filters.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Grid/13-freeze-columns/Grid_FreezeColumns_Documentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/13-freeze-columns/Grid_FreezeColumns_Documentation.razor similarity index 75% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Grid/13-freeze-columns/Grid_FreezeColumns_Documentation.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/13-freeze-columns/Grid_FreezeColumns_Documentation.razor index bc3007bfa..0ec67ee61 100644 --- a/BlazorBootstrap.Demo.RCL/Components/Pages/Grid/13-freeze-columns/Grid_FreezeColumns_Documentation.razor +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/13-freeze-columns/Grid_FreezeColumns_Documentation.razor @@ -1,15 +1,14 @@ @attribute [Route(pageUrl)] +@layout DemosMainLayout - + - - @pageDescription - - - +
    @@ -25,7 +24,7 @@
    @code { - private const string pageUrl = RouteConstants.Demos_Grid_FreezeColumns_Documentation; + private const string pageUrl = DemoRouteConstants.Demos_URL_Grid_FreezeColumns; private const string pageTitle = "Blazor Grid - Freeze columns"; private const string pageDescription = "Use Blazor Bootstrap grid component to display tabular data from the data source. And it supports client-side and server-side filtering, paging, and sorting."; private const string metaTitle = "Blazor Grid Component - Freeze columns"; diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Grid/14-detail-view/Grid_Demo_14_A_DetailView.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/14-detail-view/Grid_Demo_14_A_DetailView.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Grid/14-detail-view/Grid_Demo_14_A_DetailView.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/14-detail-view/Grid_Demo_14_A_DetailView.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Grid/14-detail-view/Grid_Demo_14_B_DetailView_Dynamic_Data.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/14-detail-view/Grid_Demo_14_B_DetailView_Dynamic_Data.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Grid/14-detail-view/Grid_Demo_14_B_DetailView_Dynamic_Data.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/14-detail-view/Grid_Demo_14_B_DetailView_Dynamic_Data.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Grid/14-detail-view/Grid_DetailView_Documentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/14-detail-view/Grid_DetailView_Documentation.razor similarity index 74% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Grid/14-detail-view/Grid_DetailView_Documentation.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/14-detail-view/Grid_DetailView_Documentation.razor index c7d78be9f..059c2807c 100644 --- a/BlazorBootstrap.Demo.RCL/Components/Pages/Grid/14-detail-view/Grid_DetailView_Documentation.razor +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/14-detail-view/Grid_DetailView_Documentation.razor @@ -1,15 +1,14 @@ @attribute [Route(pageUrl)] +@layout DemosMainLayout - + - - @pageDescription - - - +
    To enable detail view, set the AllowDetailView parameter to true. In the following example, existing <GridColumn> tags are nested under <GridColumns> tag to distinguish them from <GridDetailView>.
    @@ -22,7 +21,7 @@
    @code { - private const string pageUrl = RouteConstants.Demos_Grid_DetailView_Documentation; + private const string pageUrl = DemoRouteConstants.Demos_URL_Grid_DetailView; private const string pageTitle = "Blazor Grid - Detail View"; private const string pageDescription = "Use Blazor Bootstrap grid component to display tabular data from the data source. And it supports client-side and server-side filtering, paging, and sorting."; private const string metaTitle = "Blazor Grid Component - Detail View"; diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Grid/15-nested-grid/Grid_Demo_15_A_DetialView_Nested_Grid.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/15-nested-grid/Grid_Demo_15_A_DetialView_Nested_Grid.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Grid/15-nested-grid/Grid_Demo_15_A_DetialView_Nested_Grid.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/15-nested-grid/Grid_Demo_15_A_DetialView_Nested_Grid.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Grid/15-nested-grid/Grid_Nested_Documentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/15-nested-grid/Grid_Nested_Documentation.razor similarity index 72% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Grid/15-nested-grid/Grid_Nested_Documentation.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/15-nested-grid/Grid_Nested_Documentation.razor index 061072d92..1192c8c7b 100644 --- a/BlazorBootstrap.Demo.RCL/Components/Pages/Grid/15-nested-grid/Grid_Nested_Documentation.razor +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/15-nested-grid/Grid_Nested_Documentation.razor @@ -1,15 +1,14 @@ @attribute [Route(pageUrl)] +@layout DemosMainLayout - + - - @pageDescription - - - +
    To create a nested grid, we first need to enable the detail view. To enable the detail view, set the AllowDetailView parameter to true. In the following example, existing <GridColumn> tags are nested under <GridColumns> tag to distinguish them from <GridDetailView>.
    @@ -17,7 +16,7 @@
    @code { - private const string pageUrl = RouteConstants.Demos_Grid_NestedGrid_Documentation; + private const string pageUrl = DemoRouteConstants.Demos_URL_Grid_NestedGrid; private const string pageTitle = "Blazor Grid - Nested Grid"; private const string pageDescription = "Use Blazor Bootstrap grid component to display tabular data from the data source. And it supports client-side and server-side filtering, paging, and sorting."; private const string metaTitle = "Blazor Grid Component - Nested Grid"; diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/16-summary/Grid_Demo_01_Summary_Example.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/16-summary/Grid_Demo_01_Summary_Example.razor new file mode 100644 index 000000000..a98ce4b5b --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/16-summary/Grid_Demo_01_Summary_Example.razor @@ -0,0 +1,68 @@ + + + + + @context.Id + + + @context.Name + + + @context.Designation + + + @context.DOJ + + + @context.Salary.ToString("C") + + + @context.IsActive + + + + +@code { + private IEnumerable employees = default!; + + private async Task> EmployeesDataProvider(GridDataProviderRequest request) + { + if (employees is null) // pull employees only one time for client-side filtering, sorting, and paging + employees = GetEmployees(); // call a service or an API to pull the employees + + return await Task.FromResult(request.ApplyTo(employees)); + } + + private IEnumerable GetEmployees() + { + return new List + { + new Employee { Id = 107, Name = "Alice", Designation = "AI Engineer", DOJ = new DateOnly(1998, 11, 17), Salary = 7700, IsActive = true }, + new Employee { Id = 103, Name = "Bob", Designation = "Senior DevOps Engineer", DOJ = new DateOnly(1985, 1, 5), Salary = 19000, IsActive = true }, + new Employee { Id = 106, Name = "John", Designation = "Data Engineer", DOJ = new DateOnly(1995, 4, 17), Salary = 12000, IsActive = true }, + new Employee { Id = 104, Name = "Pop", Designation = "Associate Architect", DOJ = new DateOnly(1985, 6, 8), Salary = 19000, IsActive = false }, + new Employee { Id = 105, Name = "Ronald", Designation = "Senior Data Engineer", DOJ = new DateOnly(1991, 8, 23), Salary = 16500.50f, IsActive = true }, + new Employee { Id = 102, Name = "Line", Designation = "Architect", DOJ = new DateOnly(1977, 1, 12), Salary = 24000, IsActive = true }, + new Employee { Id = 101, Name = "Daniel", Designation = "Architect", DOJ = new DateOnly(1977, 1, 12), Salary = 21000, IsActive = true }, + new Employee { Id = 113, Name = "Merlin", Designation = "Senior Consultant", DOJ = new DateOnly(1989, 10, 2), Salary = 13500, IsActive = true }, + new Employee { Id = 117, Name = "Sharna", Designation = "Data Analyst", DOJ = new DateOnly(1994, 5, 12), Salary = 15800.10f, IsActive = true }, + new Employee { Id = 108, Name = "Zayne", Designation = "Data Analyst", DOJ = new DateOnly(1991, 1, 1), Salary = 14000, IsActive = true }, + new Employee { Id = 109, Name = "Isha", Designation = "App Maker", DOJ = new DateOnly(1996, 7, 1), Salary = 8000, IsActive = true }, + new Employee { Id = 111, Name = "Glenda", Designation = "Data Engineer", DOJ = new DateOnly(1994, 1, 12), Salary = 17850, IsActive = true }, + }; + } + + public record class Employee + { + public int Id { get; set; } + public string? Name { get; set; } + public string? Designation { get; set; } + public DateOnly DOJ { get; set; } + public float Salary { get; set; } + public bool IsActive { get; set; } + } +} \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/16-summary/Grid_Demo_02_Summary_with_Filters_Paging.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/16-summary/Grid_Demo_02_Summary_with_Filters_Paging.razor new file mode 100644 index 000000000..103638ed1 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/16-summary/Grid_Demo_02_Summary_with_Filters_Paging.razor @@ -0,0 +1,83 @@ + + + + + @context.Id + + + @context.Name + + + @context.Designation + + + @context.DOJ + + + @context.Salary.ToString("C") + + + @context.IsActive + + + + +@code { + private IEnumerable employees = default!; + + private HashSet selectedEmployees = new(); + + private async Task> EmployeesDataProvider(GridDataProviderRequest request) + { + if (employees is null) // pull employees only one time for client-side filtering, sorting, and paging + employees = GetEmployees(); // call a service or an API to pull the employees + + return await Task.FromResult(request.ApplyTo(employees)); + } + + private IEnumerable GetEmployees() + { + return new List + { + new Employee { Id = 107, Name = "Alice", Designation = "AI Engineer", DOJ = new DateOnly(1998, 11, 17), Salary = 7700, IsActive = true }, + new Employee { Id = 103, Name = "Bob", Designation = "Senior DevOps Engineer", DOJ = new DateOnly(1985, 1, 5), Salary = 19000, IsActive = true }, + new Employee { Id = 106, Name = "John", Designation = "Data Engineer", DOJ = new DateOnly(1995, 4, 17), Salary = 12000, IsActive = true }, + new Employee { Id = 104, Name = "Pop", Designation = "Associate Architect", DOJ = new DateOnly(1985, 6, 8), Salary = 19000, IsActive = false }, + new Employee { Id = 105, Name = "Ronald", Designation = "Senior Data Engineer", DOJ = new DateOnly(1991, 8, 23), Salary = 16500.50f, IsActive = true }, + new Employee { Id = 102, Name = "Line", Designation = "Architect", DOJ = new DateOnly(1977, 1, 12), Salary = 24000, IsActive = true }, + new Employee { Id = 101, Name = "Daniel", Designation = "Architect", DOJ = new DateOnly(1977, 1, 12), Salary = 21000, IsActive = true }, + new Employee { Id = 113, Name = "Merlin", Designation = "Senior Consultant", DOJ = new DateOnly(1989, 10, 2), Salary = 13500, IsActive = true }, + new Employee { Id = 117, Name = "Sharna", Designation = "Data Analyst", DOJ = new DateOnly(1994, 5, 12), Salary = 15800.10f, IsActive = true }, + new Employee { Id = 108, Name = "Zayne", Designation = "Data Analyst", DOJ = new DateOnly(1991, 1, 1), Salary = 14000, IsActive = true }, + new Employee { Id = 109, Name = "Isha", Designation = "App Maker", DOJ = new DateOnly(1996, 7, 1), Salary = 8000, IsActive = true }, + new Employee { Id = 111, Name = "Glenda", Designation = "Data Engineer", DOJ = new DateOnly(1994, 1, 12), Salary = 17850, IsActive = true }, + }; + } + + private Task OnSelectedItemsChanged(HashSet employees) + { + selectedEmployees = employees is not null && employees.Any() ? employees : new(); + return Task.CompletedTask; + } + + public record class Employee + { + public int Id { get; set; } + public string? Name { get; set; } + public string? Designation { get; set; } + public DateOnly DOJ { get; set; } + public float Salary { get; set; } + public bool IsActive { get; set; } + } +} \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/16-summary/Grid_Demo_03_Change_Prefix.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/16-summary/Grid_Demo_03_Change_Prefix.razor new file mode 100644 index 000000000..5635a7ebb --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/16-summary/Grid_Demo_03_Change_Prefix.razor @@ -0,0 +1,68 @@ + + + + + @context.Id + + + @context.Name + + + @context.Designation + + + @context.DOJ + + + @context.Salary.ToString("C") + + + @context.IsActive + + + + +@code { + private IEnumerable employees = default!; + + private async Task> EmployeesDataProvider(GridDataProviderRequest request) + { + if (employees is null) // pull employees only one time for client-side filtering, sorting, and paging + employees = GetEmployees(); // call a service or an API to pull the employees + + return await Task.FromResult(request.ApplyTo(employees)); + } + + private IEnumerable GetEmployees() + { + return new List + { + new Employee { Id = 107, Name = "Alice", Designation = "AI Engineer", DOJ = new DateOnly(1998, 11, 17), Salary = 7700, IsActive = true }, + new Employee { Id = 103, Name = "Bob", Designation = "Senior DevOps Engineer", DOJ = new DateOnly(1985, 1, 5), Salary = 19000, IsActive = true }, + new Employee { Id = 106, Name = "John", Designation = "Data Engineer", DOJ = new DateOnly(1995, 4, 17), Salary = 12000, IsActive = true }, + new Employee { Id = 104, Name = "Pop", Designation = "Associate Architect", DOJ = new DateOnly(1985, 6, 8), Salary = 19000, IsActive = false }, + new Employee { Id = 105, Name = "Ronald", Designation = "Senior Data Engineer", DOJ = new DateOnly(1991, 8, 23), Salary = 16500.50f, IsActive = true }, + new Employee { Id = 102, Name = "Line", Designation = "Architect", DOJ = new DateOnly(1977, 1, 12), Salary = 24000, IsActive = true }, + new Employee { Id = 101, Name = "Daniel", Designation = "Architect", DOJ = new DateOnly(1977, 1, 12), Salary = 21000, IsActive = true }, + new Employee { Id = 113, Name = "Merlin", Designation = "Senior Consultant", DOJ = new DateOnly(1989, 10, 2), Salary = 13500, IsActive = true }, + new Employee { Id = 117, Name = "Sharna", Designation = "Data Analyst", DOJ = new DateOnly(1994, 5, 12), Salary = 15800.10f, IsActive = true }, + new Employee { Id = 108, Name = "Zayne", Designation = "Data Analyst", DOJ = new DateOnly(1991, 1, 1), Salary = 14000, IsActive = true }, + new Employee { Id = 109, Name = "Isha", Designation = "App Maker", DOJ = new DateOnly(1996, 7, 1), Salary = 8000, IsActive = true }, + new Employee { Id = 111, Name = "Glenda", Designation = "Data Engineer", DOJ = new DateOnly(1994, 1, 12), Salary = 17850, IsActive = true }, + }; + } + + public record class Employee + { + public int Id { get; set; } + public string? Name { get; set; } + public string? Designation { get; set; } + public DateOnly DOJ { get; set; } + public float Salary { get; set; } + public bool IsActive { get; set; } + } +} \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/16-summary/Grid_Demo_04_Remove_Prefix.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/16-summary/Grid_Demo_04_Remove_Prefix.razor new file mode 100644 index 000000000..9c8a1039c --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/16-summary/Grid_Demo_04_Remove_Prefix.razor @@ -0,0 +1,68 @@ + + + + + @context.Id + + + @context.Name + + + @context.Designation + + + @context.DOJ + + + @context.Salary.ToString("C") + + + @context.IsActive + + + + +@code { + private IEnumerable employees = default!; + + private async Task> EmployeesDataProvider(GridDataProviderRequest request) + { + if (employees is null) // pull employees only one time for client-side filtering, sorting, and paging + employees = GetEmployees(); // call a service or an API to pull the employees + + return await Task.FromResult(request.ApplyTo(employees)); + } + + private IEnumerable GetEmployees() + { + return new List + { + new Employee { Id = 107, Name = "Alice", Designation = "AI Engineer", DOJ = new DateOnly(1998, 11, 17), Salary = 7700, IsActive = true }, + new Employee { Id = 103, Name = "Bob", Designation = "Senior DevOps Engineer", DOJ = new DateOnly(1985, 1, 5), Salary = 19000, IsActive = true }, + new Employee { Id = 106, Name = "John", Designation = "Data Engineer", DOJ = new DateOnly(1995, 4, 17), Salary = 12000, IsActive = true }, + new Employee { Id = 104, Name = "Pop", Designation = "Associate Architect", DOJ = new DateOnly(1985, 6, 8), Salary = 19000, IsActive = false }, + new Employee { Id = 105, Name = "Ronald", Designation = "Senior Data Engineer", DOJ = new DateOnly(1991, 8, 23), Salary = 16500.50f, IsActive = true }, + new Employee { Id = 102, Name = "Line", Designation = "Architect", DOJ = new DateOnly(1977, 1, 12), Salary = 24000, IsActive = true }, + new Employee { Id = 101, Name = "Daniel", Designation = "Architect", DOJ = new DateOnly(1977, 1, 12), Salary = 21000, IsActive = true }, + new Employee { Id = 113, Name = "Merlin", Designation = "Senior Consultant", DOJ = new DateOnly(1989, 10, 2), Salary = 13500, IsActive = true }, + new Employee { Id = 117, Name = "Sharna", Designation = "Data Analyst", DOJ = new DateOnly(1994, 5, 12), Salary = 15800.10f, IsActive = true }, + new Employee { Id = 108, Name = "Zayne", Designation = "Data Analyst", DOJ = new DateOnly(1991, 1, 1), Salary = 14000, IsActive = true }, + new Employee { Id = 109, Name = "Isha", Designation = "App Maker", DOJ = new DateOnly(1996, 7, 1), Salary = 8000, IsActive = true }, + new Employee { Id = 111, Name = "Glenda", Designation = "Data Engineer", DOJ = new DateOnly(1994, 1, 12), Salary = 17850, IsActive = true }, + }; + } + + public record class Employee + { + public int Id { get; set; } + public string? Name { get; set; } + public string? Designation { get; set; } + public DateOnly DOJ { get; set; } + public float Salary { get; set; } + public bool IsActive { get; set; } + } +} \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/16-summary/Grid_Demo_05_Locale.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/16-summary/Grid_Demo_05_Locale.razor new file mode 100644 index 000000000..eae7c5bb3 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/16-summary/Grid_Demo_05_Locale.razor @@ -0,0 +1,69 @@ + + + + + @context.Id + + + @context.Name + + + @context.Designation + + + @context.DOJ + + + @context.Salary.ToString("C", System.Globalization.CultureInfo.GetCultureInfo("en-IN")) + + + @context.IsActive + + + + +@code { + private IEnumerable employees = default!; + + private async Task> EmployeesDataProvider(GridDataProviderRequest request) + { + if (employees is null) // pull employees only one time for client-side filtering, sorting, and paging + employees = GetEmployees(); // call a service or an API to pull the employees + + return await Task.FromResult(request.ApplyTo(employees)); + } + + private IEnumerable GetEmployees() + { + return new List + { + new Employee { Id = 107, Name = "Alice", Designation = "AI Engineer", DOJ = new DateOnly(1998, 11, 17), Salary = 7700, IsActive = true }, + new Employee { Id = 103, Name = "Bob", Designation = "Senior DevOps Engineer", DOJ = new DateOnly(1985, 1, 5), Salary = 19000, IsActive = true }, + new Employee { Id = 106, Name = "John", Designation = "Data Engineer", DOJ = new DateOnly(1995, 4, 17), Salary = 12000, IsActive = true }, + new Employee { Id = 104, Name = "Pop", Designation = "Associate Architect", DOJ = new DateOnly(1985, 6, 8), Salary = 19000, IsActive = false }, + new Employee { Id = 105, Name = "Ronald", Designation = "Senior Data Engineer", DOJ = new DateOnly(1991, 8, 23), Salary = 16500.50f, IsActive = true }, + new Employee { Id = 102, Name = "Line", Designation = "Architect", DOJ = new DateOnly(1977, 1, 12), Salary = 24000, IsActive = true }, + new Employee { Id = 101, Name = "Daniel", Designation = "Architect", DOJ = new DateOnly(1977, 1, 12), Salary = 21000, IsActive = true }, + new Employee { Id = 113, Name = "Merlin", Designation = "Senior Consultant", DOJ = new DateOnly(1989, 10, 2), Salary = 13500, IsActive = true }, + new Employee { Id = 117, Name = "Sharna", Designation = "Data Analyst", DOJ = new DateOnly(1994, 5, 12), Salary = 15800.10f, IsActive = true }, + new Employee { Id = 108, Name = "Zayne", Designation = "Data Analyst", DOJ = new DateOnly(1991, 1, 1), Salary = 14000, IsActive = true }, + new Employee { Id = 109, Name = "Isha", Designation = "App Maker", DOJ = new DateOnly(1996, 7, 1), Salary = 8000, IsActive = true }, + new Employee { Id = 111, Name = "Glenda", Designation = "Data Engineer", DOJ = new DateOnly(1994, 1, 12), Salary = 17850, IsActive = true }, + }; + } + + public record class Employee + { + public int Id { get; set; } + public string? Name { get; set; } + public string? Designation { get; set; } + public DateOnly DOJ { get; set; } + public float Salary { get; set; } + public bool IsActive { get; set; } + } +} \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/16-summary/Grid_Summary_Documentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/16-summary/Grid_Summary_Documentation.razor new file mode 100644 index 000000000..0ee023f73 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/16-summary/Grid_Summary_Documentation.razor @@ -0,0 +1,62 @@ +@attribute [Route(pageUrl)] +@layout DemosMainLayout + + + + + +
    +
    + To enable summaries on columns, set the AllowSummary parameter to true at the Grid level. Additionally, set the SummaryType parameter on each GridColumn. +
    + In the following example, the Employee Name column has SummaryType set to GridSummaryColumnType.Count, and the Salary column has SummaryType set to GridSummaryColumnType.Sum and SummaryValueDisplayFormat set to C to display the sum of salaries in currency format. +
    + +
    + GridSummaryColumnType: Average, Count, Max, Min, Sum. Default value is GridSummaryColumnType.None. +
    +
    + +
    + +
    +
    + Summaries will be calculated based on the current page data. +
    + +
    + +
    +
    + Set the SummaryValuePrefix parameter to custom string to change the prefix from the summary value. +
    + +
    + +
    +
    + Set the SummaryValuePrefix parameter to empty string to remove the prefix from the summary value. +
    + +
    + +
    +
    + Set the Locale parameter on the Grid to change the CultureInfo of the summary. +
    + +
    + +@code { + private const string pageUrl = DemoRouteConstants.Demos_URL_Grid_Summary; + private const string pageTitle = "Blazor Grid - Summary"; + private const string pageDescription = "Use Blazor Bootstrap grid component to display tabular data from the data source. And it supports client-side and server-side filtering, paging, and sorting."; + private const string metaTitle = "Blazor Grid Component - Summary"; + private const string metaDescription = "Use Blazor Bootstrap grid component to display tabular data from the data source. And it supports client-side and server-side filtering, paging, and sorting."; + private const string imageUrl = "https://i.imgur.com/eetvhBB.png"; +} diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Grid/99-other/Grid_Demo_01_Grid_Cell_Formating.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/99-other/Grid_Demo_01_Grid_Cell_Formating.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Grid/99-other/Grid_Demo_01_Grid_Cell_Formating.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/99-other/Grid_Demo_01_Grid_Cell_Formating.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Grid/99-other/Grid_Demo_02_Grid_Cell_Nowrap.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/99-other/Grid_Demo_02_Grid_Cell_Nowrap.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Grid/99-other/Grid_Demo_02_Grid_Cell_Nowrap.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/99-other/Grid_Demo_02_Grid_Cell_Nowrap.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Grid/99-other/Grid_Demo_03_Empty_Data.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/99-other/Grid_Demo_03_Empty_Data.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Grid/99-other/Grid_Demo_03_Empty_Data.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/99-other/Grid_Demo_03_Empty_Data.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Grid/99-other/Grid_Demo_04_Empty_Data_Template.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/99-other/Grid_Demo_04_Empty_Data_Template.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Grid/99-other/Grid_Demo_04_Empty_Data_Template.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/99-other/Grid_Demo_04_Empty_Data_Template.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Grid/99-other/Grid_Demo_05_Specify_Custom_Column_Header.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/99-other/Grid_Demo_05_Specify_Custom_Column_Header.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Grid/99-other/Grid_Demo_05_Specify_Custom_Column_Header.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/99-other/Grid_Demo_05_Specify_Custom_Column_Header.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/99-other/Grid_Demo_06_Hide_Columns_Dynamically.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/99-other/Grid_Demo_06_Hide_Columns_Dynamically.razor new file mode 100644 index 000000000..9d1258c8b --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/99-other/Grid_Demo_06_Hide_Columns_Dynamically.razor @@ -0,0 +1,95 @@ + + + + + + + @context.Id + + + @context.Name + + + @context.Designation + + + @context.DOJ + + + @context.IsActive + + + + + +
    + Selected Items Count: @selectedEmployees.Count +
    + +
    + Selected Employees: +
      + @foreach (var emp in selectedEmployees) + { +
    • @emp.Name
    • + } +
    +
    + +@code { + private IEnumerable employees = default!; + + private HashSet selectedEmployees = new(); + + public bool isActiveColumnVisible = true; + + private async Task> EmployeesDataProvider(GridDataProviderRequest request) + { + if (employees is null) // pull employees only one time for client-side filtering, sorting, and paging + employees = GetEmployees(); // call a service or an API to pull the employees + + return await Task.FromResult(request.ApplyTo(employees)); + } + + private async Task ToggleActiveColumnVisibility() + { + isActiveColumnVisible = !isActiveColumnVisible; + } + + private IEnumerable GetEmployees() + { + return new List + { + new Employee1 { Id = 107, Name = "Alice", Designation = "AI Engineer", DOJ = new DateOnly(1998, 11, 17), IsActive = true }, + new Employee1 { Id = 103, Name = "Bob", Designation = "Senior DevOps Engineer", DOJ = new DateOnly(1985, 1, 5), IsActive = true }, + new Employee1 { Id = 106, Name = "John", Designation = "Data Engineer", DOJ = new DateOnly(1995, 4, 17), IsActive = true }, + new Employee1 { Id = 104, Name = "Pop", Designation = "Associate Architect", DOJ = new DateOnly(1985, 6, 8), IsActive = false }, + new Employee1 { Id = 105, Name = "Ronald", Designation = "Senior Data Engineer", DOJ = new DateOnly(1991, 8, 23), IsActive = true }, + new Employee1 { Id = 102, Name = "Line", Designation = "Architect", DOJ = new DateOnly(1977, 1, 12), IsActive = true }, + new Employee1 { Id = 101, Name = "Daniel", Designation = "Architect", DOJ = new DateOnly(1977, 1, 12), IsActive = true }, + new Employee1 { Id = 113, Name = "Merlin", Designation = "Senior Consultant", DOJ = new DateOnly(1989, 10, 2), IsActive = true }, + new Employee1 { Id = 117, Name = "Sharna", Designation = "Data Analyst", DOJ = new DateOnly(1994, 5, 12), IsActive = true }, + new Employee1 { Id = 108, Name = "Zayne", Designation = "Data Analyst", DOJ = new DateOnly(1991, 1, 1), IsActive = true }, + new Employee1 { Id = 109, Name = "Isha", Designation = "App Maker", DOJ = new DateOnly(1996, 7, 1), IsActive = true }, + new Employee1 { Id = 111, Name = "Glenda", Designation = "Data Engineer", DOJ = new DateOnly(1994, 1, 12), IsActive = true }, + }; + } + + private Task OnSelectedItemsChanged(HashSet employees) + { + selectedEmployees = employees is not null && employees.Any() ? employees : new(); + return Task.CompletedTask; + } +} \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/99-other/Grid_Demo_07_Increase_TextBox_Width.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/99-other/Grid_Demo_07_Increase_TextBox_Width.razor new file mode 100644 index 000000000..2a6f7d4d5 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/99-other/Grid_Demo_07_Increase_TextBox_Width.razor @@ -0,0 +1,65 @@ + + + + + @context.Id + + + @context.FirstName + + + @context.LastName + + + + + + @context.Email + + + @context.Company + + + @context.Designation + + + @context.DOJ + + + @context.IsActive + + + + + +@code { + private IEnumerable? employees; + + private async Task> EmployeesDataProvider(GridDataProviderRequest request) + { + if (employees is null) // pull employees only one time for client-side filtering, sorting, and paging + employees = GetEmployees(); // call a service or an API to pull the employees + + return await Task.FromResult(request.ApplyTo(employees)); + } + + private IEnumerable GetEmployees() + { + return new List + { + new Employee3 { Id = 107, FirstName = "Alice", LastName = "Reddy", Email = "alice@blazorbootstrap.com", Company = "BlazorBootstrap Company", Designation = "AI Engineer", DOJ = new DateOnly(1998, 11, 17), Salary = 7700, IsActive = true }, + new Employee3 { Id = 103, FirstName = "Bob", LastName = "Roy", Email = "bob@blazorbootstrap.com", Company = "BlazorBootstrap Company", Designation = "Senior DevOps Engineer", DOJ = new DateOnly(1985, 1, 5), Salary = 19000, IsActive = true }, + new Employee3 { Id = 106, FirstName = "John", LastName = "P", Email = "john@blazorbootstrap.com", Company = "BlazorBootstrap Company", Designation = "Data Engineer", DOJ = new DateOnly(1995, 4, 17), Salary = 12000, IsActive = true }, + new Employee3 { Id = 104, FirstName = "Pop", LastName = "Two", Email = "pop@blazorbootstrap.com", Company = "BlazorBootstrap Company", Designation = "Associate Architect", DOJ = new DateOnly(1985, 6, 8), Salary = 19000, IsActive = false }, + new Employee3 { Id = 105, FirstName = "Ronald", LastName = "Dire", Email = "ronald@blazorbootstrap.com", Company = "BlazorBootstrap Company", Designation = "Senior Data Engineer", DOJ = new DateOnly(1991, 8, 23), Salary = 16500, IsActive = true }, + new Employee3 { Id = 102, FirstName = "Line", LastName = "K", Email = "line@blazorbootstrap.com", Company = "BlazorBootstrap Company", Designation = "Architect", DOJ = new DateOnly(1977, 1, 12), Salary = 24000, IsActive = true }, + new Employee3 { Id = 101, FirstName = "Daniel", LastName = "Potter", Email = "daniel@blazorbootstrap.com", Company = "BlazorBootstrap Company", Designation = "Architect", DOJ = new DateOnly(1977, 1, 12), Salary = 21000, IsActive = true }, + new Employee3 { Id = 108, FirstName = "Zayne", LastName = "Simmons", Email = "zayne@blazorbootstrap.com", Company = "BlazorBootstrap Company", Designation = "Data Analyst", DOJ = new DateOnly(1991, 1, 1), Salary = 17850, IsActive = true }, + new Employee3 { Id = 109, FirstName = "Isha", LastName = "Davison", Email = "isha@blazorbootstrap.com", Company = "BlazorBootstrap Company", Designation = "App Maker", DOJ = new DateOnly(1996, 7, 1), Salary = 8000, IsActive = true }, + }; + } +} \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Grid/99-other/Grid_Other_Documentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/99-other/Grid_Other_Documentation.razor similarity index 74% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Grid/99-other/Grid_Other_Documentation.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/99-other/Grid_Other_Documentation.razor index df13ae1b4..f61178aca 100644 --- a/BlazorBootstrap.Demo.RCL/Components/Pages/Grid/99-other/Grid_Other_Documentation.razor +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Grid/99-other/Grid_Other_Documentation.razor @@ -1,15 +1,14 @@ @attribute [Route(pageUrl)] +@layout DemosMainLayout - + - - @pageDescription - - - +
    To format the cell data, use ToString method and format strings. Refer: How to format numbers, dates, enums, and other types in .NET
    @@ -37,8 +36,17 @@
    +
    +
    Set the IsVisible parameter to false to hide the column.
    + +
    + +
    + +
    + @code { - private const string pageUrl = RouteConstants.Demos_Grid_OtherExamples_Documentation; + private const string pageUrl = DemoRouteConstants.Demos_URL_Grid_OtherExamples; private const string pageTitle = "Blazor Grid - Other examples"; private const string pageDescription = "Use Blazor Bootstrap grid component to display tabular data from the data source. And it supports client-side and server-side filtering, paging, and sorting."; private const string metaTitle = "Blazor Grid Component - Other examples"; diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Icons/IconDocumentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Icons/IconDocumentation.razor similarity index 86% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Icons/IconDocumentation.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Icons/IconDocumentation.razor index 4248bc0c2..abf4e2140 100644 --- a/BlazorBootstrap.Demo.RCL/Components/Pages/Icons/IconDocumentation.razor +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Icons/IconDocumentation.razor @@ -1,15 +1,14 @@ @attribute [Route(pageUrl)] +@layout DemosMainLayout - + - - @pageDescription - - - +
    @@ -66,7 +65,7 @@
    @code{ - private const string pageUrl = RouteConstants.Demos_Icons_Documentation; + private const string pageUrl = DemoRouteConstants.Demos_URL_Icons; private const string pageTitle = "Blazor Icon"; private const string pageDescription = "Blazor Bootstrap icon component will display an icon from any icon font."; private const string metaTitle = "Blazor Icon Component"; diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Icons/Icon_Demo_01_Examples.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Icons/Icon_Demo_01_Examples.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Icons/Icon_Demo_01_Examples.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Icons/Icon_Demo_01_Examples.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Icons/Icon_Demo_02_Sizes.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Icons/Icon_Demo_02_Sizes.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Icons/Icon_Demo_02_Sizes.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Icons/Icon_Demo_02_Sizes.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Icons/Icon_Demo_03_Font_Awesome_Icons.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Icons/Icon_Demo_03_Font_Awesome_Icons.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Icons/Icon_Demo_03_Font_Awesome_Icons.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Icons/Icon_Demo_03_Font_Awesome_Icons.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Icons/Icon_Demo_04_Colors.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Icons/Icon_Demo_04_Colors.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Icons/Icon_Demo_04_Colors.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Icons/Icon_Demo_04_Colors.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Icons/Icon_Demo_05_Inline_Text_With_Icon.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Icons/Icon_Demo_05_Inline_Text_With_Icon.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Icons/Icon_Demo_05_Inline_Text_With_Icon.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Icons/Icon_Demo_05_Inline_Text_With_Icon.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Icons/Icon_Demo_06_A_Link_With_Icon.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Icons/Icon_Demo_06_A_Link_With_Icon.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Icons/Icon_Demo_06_A_Link_With_Icon.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Icons/Icon_Demo_06_A_Link_With_Icon.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Icons/Icon_Demo_06_B_Link_With_Custom_Icon.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Icons/Icon_Demo_06_B_Link_With_Custom_Icon.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Icons/Icon_Demo_06_B_Link_With_Custom_Icon.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Icons/Icon_Demo_06_B_Link_With_Custom_Icon.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Icons/Icon_Demo_07_A_Button_With_Icon_And_Text.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Icons/Icon_Demo_07_A_Button_With_Icon_And_Text.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Icons/Icon_Demo_07_A_Button_With_Icon_And_Text.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Icons/Icon_Demo_07_A_Button_With_Icon_And_Text.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Icons/Icon_Demo_07_B_Button_With_Icon_Only.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Icons/Icon_Demo_07_B_Button_With_Icon_Only.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Icons/Icon_Demo_07_B_Button_With_Icon_Only.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Icons/Icon_Demo_07_B_Button_With_Icon_Only.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Icons/Icon_Demo_07_C_Button_With_Font_Awesome_Icon.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Icons/Icon_Demo_07_C_Button_With_Font_Awesome_Icon.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Icons/Icon_Demo_07_C_Button_With_Font_Awesome_Icon.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Icons/Icon_Demo_07_C_Button_With_Font_Awesome_Icon.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Icons/Icon_Demo_09_Tooltip.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Icons/Icon_Demo_09_Tooltip.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Icons/Icon_Demo_09_Tooltip.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Icons/Icon_Demo_09_Tooltip.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Icons/Icon_Demo_10_Bootstrap_Icons.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Icons/Icon_Demo_10_Bootstrap_Icons.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Icons/Icon_Demo_10_Bootstrap_Icons.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Icons/Icon_Demo_10_Bootstrap_Icons.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Images/ImageDocumentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Images/ImageDocumentation.razor similarity index 78% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Images/ImageDocumentation.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Images/ImageDocumentation.razor index afbd46df7..626888d77 100644 --- a/BlazorBootstrap.Demo.RCL/Components/Pages/Images/ImageDocumentation.razor +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Images/ImageDocumentation.razor @@ -1,15 +1,14 @@ @attribute [Route(pageUrl)] +@layout DemosMainLayout - + - - @pageDescription - - - +
    @@ -32,7 +31,7 @@
    @code { - private const string pageUrl = RouteConstants.Demos_Images_Documentation; + private const string pageUrl = DemoRouteConstants.Demos_URL_Images; private const string pageTitle = "Blazor Image"; private const string pageDescription = "Documentation and examples for opting images into responsive behavior (so they never become wider than their parent) and add lightweight styles to them."; private const string metaTitle = "Blazor Image Component"; diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Images/Image_Demo_01_Examples.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Images/Image_Demo_01_Examples.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Images/Image_Demo_01_Examples.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Images/Image_Demo_01_Examples.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Images/Image_Demo_02_Thumbnail.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Images/Image_Demo_02_Thumbnail.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Images/Image_Demo_02_Thumbnail.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Images/Image_Demo_02_Thumbnail.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Images/Image_Demo_03_Aligning_Images_A.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Images/Image_Demo_03_Aligning_Images_A.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Images/Image_Demo_03_Aligning_Images_A.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Images/Image_Demo_03_Aligning_Images_A.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Images/Image_Demo_03_Aligning_Images_B.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Images/Image_Demo_03_Aligning_Images_B.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Images/Image_Demo_03_Aligning_Images_B.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Images/Image_Demo_03_Aligning_Images_B.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Images/Image_Demo_03_Aligning_Images_C.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Images/Image_Demo_03_Aligning_Images_C.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Images/Image_Demo_03_Aligning_Images_C.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Images/Image_Demo_03_Aligning_Images_C.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Layout/server/LayoutServerDocumentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Layout/server/LayoutServerDocumentation.razor similarity index 62% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Layout/server/LayoutServerDocumentation.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Layout/server/LayoutServerDocumentation.razor index 6676c5df0..c5d8a638c 100644 --- a/BlazorBootstrap.Demo.RCL/Components/Pages/Layout/server/LayoutServerDocumentation.razor +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Layout/server/LayoutServerDocumentation.razor @@ -1,15 +1,14 @@ @attribute [Route(pageUrl)] +@layout DemosMainLayout - + - - @pageDescription - - - +
    @@ -29,11 +28,20 @@ Remove all the CSS content from the Shared/MainLayout.razor.css file. - + +
    + +
    +
    + When StickyHeader="true" is used, the layout header defaults to Bootstrap's sticky-navigation stacking level. + To change that level, set the following variable in a global stylesheet loaded after blazor.bootstrap.css: +
    + +
    @code { - private const string pageUrl = "/layout-setup/blazor-server"; + private const string pageUrl = DemoRouteConstants.Demos_URL_Layout_Blazor_Server; private const string pageTitle = "Blazor Bootstrap Layout Setup - Blazor Server"; private const string pageDescription = "High-performance, lightweight, and responsive blazor bootstrap components in a single package from the developers for the developers."; private const string metaTitle = "Blazor Bootstrap Layout Setup - Blazor Server"; diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Layout/server/Layout_Server_Demo_01.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Layout/server/Layout_Server_Demo_01.razor similarity index 97% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Layout/server/Layout_Server_Demo_01.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Layout/server/Layout_Server_Demo_01.razor index 4a3f063dc..77739758d 100644 --- a/BlazorBootstrap.Demo.RCL/Components/Pages/Layout/server/Layout_Server_Demo_01.razor +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Layout/server/Layout_Server_Demo_01.razor @@ -9,7 +9,7 @@ diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Layout/server/Layout_Server_Demo_02.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Layout/server/Layout_Server_Demo_02.razor new file mode 100644 index 000000000..2e9b991a7 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Layout/server/Layout_Server_Demo_02.razor @@ -0,0 +1,3 @@ +:root { + --bb-layout-sticky-header-z-index: 1030; +} diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Layout/webassembly/LayoutWebAssemblyDocumentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Layout/webassembly/LayoutWebAssemblyDocumentation.razor similarity index 62% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Layout/webassembly/LayoutWebAssemblyDocumentation.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Layout/webassembly/LayoutWebAssemblyDocumentation.razor index a1b64fcbb..f2422216c 100644 --- a/BlazorBootstrap.Demo.RCL/Components/Pages/Layout/webassembly/LayoutWebAssemblyDocumentation.razor +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Layout/webassembly/LayoutWebAssemblyDocumentation.razor @@ -1,15 +1,14 @@ @attribute [Route(pageUrl)] +@layout DemosMainLayout - + - - @pageDescription - - - +
    @@ -29,11 +28,20 @@ Remove all the CSS content from the Shared/MainLayout.razor.css file. - + +
    + +
    +
    + When StickyHeader="true" is used, the layout header defaults to Bootstrap's sticky-navigation stacking level. + To change that level, set the following variable in a global stylesheet loaded after blazor.bootstrap.css: +
    + +
    @code { - private const string pageUrl = "/layout-setup/blazor-webassembly"; + private const string pageUrl = DemoRouteConstants.Demos_URL_Layout_BlazorWebAssembly; private const string pageTitle = "Blazor Bootstrap Layout Setup - Blazor WebAssembly"; private const string pageDescription = "High-performance, lightweight, and responsive blazor bootstrap components in a single package from the developers for the developers."; private const string metaTitle = "Blazor Bootstrap Layout Setup - Blazor WebAssembly"; diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Layout/webassembly/Layout_WebAssembly_Demo_01.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Layout/webassembly/Layout_WebAssembly_Demo_01.razor similarity index 97% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Layout/webassembly/Layout_WebAssembly_Demo_01.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Layout/webassembly/Layout_WebAssembly_Demo_01.razor index fbcfc9f07..590671c98 100644 --- a/BlazorBootstrap.Demo.RCL/Components/Pages/Layout/webassembly/Layout_WebAssembly_Demo_01.razor +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Layout/webassembly/Layout_WebAssembly_Demo_01.razor @@ -9,7 +9,7 @@ diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Layout/webassembly/Layout_WebAssembly_Demo_02.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Layout/webassembly/Layout_WebAssembly_Demo_02.razor new file mode 100644 index 000000000..2e9b991a7 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Layout/webassembly/Layout_WebAssembly_Demo_02.razor @@ -0,0 +1,3 @@ +:root { + --bb-layout-sticky-header-z-index: 1030; +} diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Maps/GoogleMapDemoComponentBase.cs b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Maps/GoogleMapDemoComponentBase.cs similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Maps/GoogleMapDemoComponentBase.cs rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Maps/GoogleMapDemoComponentBase.cs diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Maps/GoogleMapDocumentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Maps/GoogleMapDocumentation.razor similarity index 72% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Maps/GoogleMapDocumentation.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Maps/GoogleMapDocumentation.razor index ecc5f8e76..c3ee16df5 100644 --- a/BlazorBootstrap.Demo.RCL/Components/Pages/Maps/GoogleMapDocumentation.razor +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Maps/GoogleMapDocumentation.razor @@ -1,21 +1,20 @@ @attribute [Route(pageUrl)] +@layout DemosMainLayout - + - - @pageDescription - - - +
    Before you start using the GoogleMap component in your project, you need an API key. Please follow the link below for detailed steps. - Link: https://developers.google.com/maps/documentation/javascript/adding-a-google-map#key. + Link: https://developers.google.com/maps/documentation/javascript/get-api-key?setupProd=prerequisites.
    @@ -47,11 +46,19 @@
    -
    Set the PinElement.Glyph option to an empty string to hide a marker's glyph.
    +
    Set the PinElement.GlyphText option to an empty string to hide a marker's glyph.
    +
    +
    Use the PinElement.GlyphText option to show text in a marker pin.
    + +
    +
    +
    Use the PinElement.GlyphSrc option to show an image in a marker pin.
    + +
    -
    Use the PinElement.UseIconFonts and PinElement.Glyph options to use the icon fonts.
    +
    Existing PinElement.UseIconFonts and legacy PinElement.Glyph configurations remain supported while existing applications migrate.
    @@ -72,7 +79,7 @@ @code { - private const string pageUrl = RouteConstants.Demos_GoogleMap_Documentation; + private const string pageUrl = DemoRouteConstants.Demos_URL_GoogleMap; private const string pageTitle = "Blazor Google Map"; private const string pageDescription = "Blazor Bootstrap Google Map component will create maps to show locations anywhere in the world using the Google JavaScript API."; private const string metaTitle = "Blazor Google Map Component"; diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Maps/GoogleMap_Demo_01_Examples.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Maps/GoogleMap_Demo_01_Examples.razor new file mode 100644 index 000000000..dc41f940c --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Maps/GoogleMap_Demo_01_Examples.razor @@ -0,0 +1,18 @@ +@inherits GoogleMapDemoComponentBase + +
    +
    + +
    +
    + +
    +
    diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Maps/GoogleMap_Demo_02_Marker.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Maps/GoogleMap_Demo_02_Marker.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Maps/GoogleMap_Demo_02_Marker.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Maps/GoogleMap_Demo_02_Marker.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Maps/GoogleMap_Demo_03_Marker_Customization_A_Scale_the_marker.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Maps/GoogleMap_Demo_03_Marker_Customization_A_Scale_the_marker.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Maps/GoogleMap_Demo_03_Marker_Customization_A_Scale_the_marker.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Maps/GoogleMap_Demo_03_Marker_Customization_A_Scale_the_marker.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Maps/GoogleMap_Demo_03_Marker_Customization_B_Change_the_background_color.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Maps/GoogleMap_Demo_03_Marker_Customization_B_Change_the_background_color.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Maps/GoogleMap_Demo_03_Marker_Customization_B_Change_the_background_color.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Maps/GoogleMap_Demo_03_Marker_Customization_B_Change_the_background_color.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Maps/GoogleMap_Demo_03_Marker_Customization_C_Change_the_border_color.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Maps/GoogleMap_Demo_03_Marker_Customization_C_Change_the_border_color.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Maps/GoogleMap_Demo_03_Marker_Customization_C_Change_the_border_color.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Maps/GoogleMap_Demo_03_Marker_Customization_C_Change_the_border_color.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Maps/GoogleMap_Demo_03_Marker_Customization_D_Change_the_glyph_color.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Maps/GoogleMap_Demo_03_Marker_Customization_D_Change_the_glyph_color.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Maps/GoogleMap_Demo_03_Marker_Customization_D_Change_the_glyph_color.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Maps/GoogleMap_Demo_03_Marker_Customization_D_Change_the_glyph_color.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Maps/GoogleMap_Demo_03_Marker_Customization_E_Hide_the_glyph.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Maps/GoogleMap_Demo_03_Marker_Customization_E_Hide_the_glyph.razor similarity index 85% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Maps/GoogleMap_Demo_03_Marker_Customization_E_Hide_the_glyph.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Maps/GoogleMap_Demo_03_Marker_Customization_E_Hide_the_glyph.razor index a80d26525..0735adb59 100644 --- a/BlazorBootstrap.Demo.RCL/Components/Pages/Maps/GoogleMap_Demo_03_Marker_Customization_E_Hide_the_glyph.razor +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Maps/GoogleMap_Demo_03_Marker_Customization_E_Hide_the_glyph.razor @@ -12,15 +12,15 @@ { new GoogleMapMarker() { - PinElement = new PinElement{ Glyph = "", }, + PinElement = new PinElement{ GlyphText = "", }, Position = new GoogleMapMarkerPosition(37.50024109655184, -122.28528451834352) , Title = "Single family house with modern design", }, new GoogleMapMarker() { - PinElement = new PinElement{ Glyph = "", }, + PinElement = new PinElement{ GlyphText = "", }, Position = new GoogleMapMarkerPosition(37.44440882321596, -122.2160620727) , Title = "Townhouse with friendly neighbors", } }; -} \ No newline at end of file +} diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Maps/GoogleMap_Demo_03_Marker_Customization_F_Use_icon_fonts.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Maps/GoogleMap_Demo_03_Marker_Customization_F_Use_icon_fonts.razor similarity index 97% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Maps/GoogleMap_Demo_03_Marker_Customization_F_Use_icon_fonts.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Maps/GoogleMap_Demo_03_Marker_Customization_F_Use_icon_fonts.razor index 8402fd1c3..6eb9f169f 100644 --- a/BlazorBootstrap.Demo.RCL/Components/Pages/Maps/GoogleMap_Demo_03_Marker_Customization_F_Use_icon_fonts.razor +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Maps/GoogleMap_Demo_03_Marker_Customization_F_Use_icon_fonts.razor @@ -8,6 +8,7 @@ Markers="markers" /> @code { +#pragma warning disable CS0618 // This demo intentionally exercises the legacy icon-font compatibility path. List markers = new() { new GoogleMapMarker() @@ -107,4 +108,5 @@ Title = "Heavy rain", } }; -} \ No newline at end of file +#pragma warning restore CS0618 +} diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Maps/GoogleMap_Demo_03_Marker_Customization_G_Use_text_glyphs.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Maps/GoogleMap_Demo_03_Marker_Customization_G_Use_text_glyphs.razor new file mode 100644 index 000000000..e214f8292 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Maps/GoogleMap_Demo_03_Marker_Customization_G_Use_text_glyphs.razor @@ -0,0 +1,26 @@ +@inherits GoogleMapDemoComponentBase + + + +@code { + List markers = new() + { + new GoogleMapMarker() + { + PinElement = new PinElement { Background = "#137333", GlyphColor = "white", GlyphText = "A" }, + Position = new GoogleMapMarkerPosition(37.50024109655184, -122.28528451834352), + Title = "Marker A", + }, + new GoogleMapMarker() + { + PinElement = new PinElement { Background = "#1A73E8", GlyphColor = "white", GlyphText = "B" }, + Position = new GoogleMapMarkerPosition(37.44440882321596, -122.2160620727), + Title = "Marker B", + } + }; +} diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Maps/GoogleMap_Demo_03_Marker_Customization_H_Use_image_glyphs.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Maps/GoogleMap_Demo_03_Marker_Customization_H_Use_image_glyphs.razor new file mode 100644 index 000000000..f659d820d --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Maps/GoogleMap_Demo_03_Marker_Customization_H_Use_image_glyphs.razor @@ -0,0 +1,28 @@ +@inherits GoogleMapDemoComponentBase + + + +@code { + private const string MarkerImageUrl = "https://developers.google.com/maps/documentation/javascript/examples/full/images/beachflag.png"; + + List markers = new() + { + new GoogleMapMarker() + { + PinElement = new PinElement { GlyphSrc = MarkerImageUrl }, + Position = new GoogleMapMarkerPosition(37.50024109655184, -122.28528451834352), + Title = "Image marker one", + }, + new GoogleMapMarker() + { + PinElement = new PinElement { GlyphSrc = MarkerImageUrl }, + Position = new GoogleMapMarkerPosition(37.44440882321596, -122.2160620727), + Title = "Image marker two", + } + }; +} diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Maps/GoogleMap_Demo_04_Markers_with_HTML_and_CSS.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Maps/GoogleMap_Demo_04_Markers_with_HTML_and_CSS.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Maps/GoogleMap_Demo_04_Markers_with_HTML_and_CSS.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Maps/GoogleMap_Demo_04_Markers_with_HTML_and_CSS.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Maps/GoogleMap_Demo_05_Make_a_marker_clickable.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Maps/GoogleMap_Demo_05_Make_a_marker_clickable.razor similarity index 97% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Maps/GoogleMap_Demo_05_Make_a_marker_clickable.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Maps/GoogleMap_Demo_05_Make_a_marker_clickable.razor index b6e5e6476..6f8ea8cfb 100644 --- a/BlazorBootstrap.Demo.RCL/Components/Pages/Maps/GoogleMap_Demo_05_Make_a_marker_clickable.razor +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Maps/GoogleMap_Demo_05_Make_a_marker_clickable.razor @@ -10,6 +10,7 @@ OnMarkerClick="OnGoogleMapMarkerClick" /> @code { +#pragma warning disable CS0618 // This demo intentionally exercises the legacy icon-font compatibility path. [Inject] public ToastService ToastService { get; set; } = default!; private void OnGoogleMapMarkerClick(GoogleMapMarker marker) @@ -116,4 +117,5 @@ Title = "Heavy rain", } }; -} \ No newline at end of file +#pragma warning restore CS0618 +} diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Maps/GoogleMap_Demo_06_Dynamic_markers.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Maps/GoogleMap_Demo_06_Dynamic_markers.razor similarity index 97% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Maps/GoogleMap_Demo_06_Dynamic_markers.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Maps/GoogleMap_Demo_06_Dynamic_markers.razor index 447efeeec..77b7bc072 100644 --- a/BlazorBootstrap.Demo.RCL/Components/Pages/Maps/GoogleMap_Demo_06_Dynamic_markers.razor +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Maps/GoogleMap_Demo_06_Dynamic_markers.razor @@ -22,6 +22,7 @@ OnMarkerClick="OnGoogleMapMarkerClick" /> @code { +#pragma warning disable CS0618 // This demo intentionally exercises the legacy icon-font compatibility path. Random random = new Random(2000000000); GoogleMap googleMapRef = default!; @@ -161,4 +162,5 @@ Title = "Heavy rain", }; } -} \ No newline at end of file +#pragma warning restore CS0618 +} diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Markdown/MarkdownDocumentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Markdown/MarkdownDocumentation.razor similarity index 92% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Markdown/MarkdownDocumentation.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Markdown/MarkdownDocumentation.razor index e27df3ec0..1545ea83b 100644 --- a/BlazorBootstrap.Demo.RCL/Components/Pages/Markdown/MarkdownDocumentation.razor +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Markdown/MarkdownDocumentation.razor @@ -1,15 +1,14 @@ @attribute [Route(pageUrl)] +@layout DemosMainLayout - + - - @pageDescription - - - +
    @@ -123,7 +122,7 @@
    @code{ - private const string pageUrl = RouteConstants.Demos_Markdown_Documentation; + private const string pageUrl = DemoRouteConstants.Demos_URL_Markdown; private const string pageTitle = "Blazor Markdown"; private const string pageDescription = "Use Blazor Bootstrap Markdown component to add formatting, tables, images, and more to your project pages."; private const string metaTitle = "Blazor Markdown Component"; diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Markdown/Markdown_Demo_01_Preview.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Markdown/Markdown_Demo_01_Preview.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Markdown/Markdown_Demo_01_Preview.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Markdown/Markdown_Demo_01_Preview.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Markdown/Markdown_Demo_02_Headers.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Markdown/Markdown_Demo_02_Headers.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Markdown/Markdown_Demo_02_Headers.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Markdown/Markdown_Demo_02_Headers.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Markdown/Markdown_Demo_03_Paragraphs_and_Line_Breaks.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Markdown/Markdown_Demo_03_Paragraphs_and_Line_Breaks.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Markdown/Markdown_Demo_03_Paragraphs_and_Line_Breaks.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Markdown/Markdown_Demo_03_Paragraphs_and_Line_Breaks.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Markdown/Markdown_Demo_04_Blockquotes.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Markdown/Markdown_Demo_04_Blockquotes.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Markdown/Markdown_Demo_04_Blockquotes.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Markdown/Markdown_Demo_04_Blockquotes.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Markdown/Markdown_Demo_05_Horizontal_Rules.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Markdown/Markdown_Demo_05_Horizontal_Rules.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Markdown/Markdown_Demo_05_Horizontal_Rules.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Markdown/Markdown_Demo_05_Horizontal_Rules.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Markdown/Markdown_Demo_06_Emphasis_bold_italics_strikethrough.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Markdown/Markdown_Demo_06_Emphasis_bold_italics_strikethrough.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Markdown/Markdown_Demo_06_Emphasis_bold_italics_strikethrough.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Markdown/Markdown_Demo_06_Emphasis_bold_italics_strikethrough.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Markdown/Markdown_Demo_07_Code_Highlighting.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Markdown/Markdown_Demo_07_Code_Highlighting.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Markdown/Markdown_Demo_07_Code_Highlighting.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Markdown/Markdown_Demo_07_Code_Highlighting.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Markdown/Markdown_Demo_08_Tables_A_Example.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Markdown/Markdown_Demo_08_Tables_A_Example.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Markdown/Markdown_Demo_08_Tables_A_Example.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Markdown/Markdown_Demo_08_Tables_A_Example.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Markdown/Markdown_Demo_08_Tables_B_Custom_CssClass.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Markdown/Markdown_Demo_08_Tables_B_Custom_CssClass.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Markdown/Markdown_Demo_08_Tables_B_Custom_CssClass.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Markdown/Markdown_Demo_08_Tables_B_Custom_CssClass.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Markdown/Markdown_Demo_09_Lists_A_Ordered.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Markdown/Markdown_Demo_09_Lists_A_Ordered.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Markdown/Markdown_Demo_09_Lists_A_Ordered.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Markdown/Markdown_Demo_09_Lists_A_Ordered.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Markdown/Markdown_Demo_09_Lists_B_Unordered.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Markdown/Markdown_Demo_09_Lists_B_Unordered.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Markdown/Markdown_Demo_09_Lists_B_Unordered.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Markdown/Markdown_Demo_09_Lists_B_Unordered.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Markdown/Markdown_Demo_09_Lists_C_Nested.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Markdown/Markdown_Demo_09_Lists_C_Nested.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Markdown/Markdown_Demo_09_Lists_C_Nested.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Markdown/Markdown_Demo_09_Lists_C_Nested.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Markdown/Markdown_Demo_09_Lists_D_Nested.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Markdown/Markdown_Demo_09_Lists_D_Nested.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Markdown/Markdown_Demo_09_Lists_D_Nested.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Markdown/Markdown_Demo_09_Lists_D_Nested.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Markdown/Markdown_Demo_09_Lists_E_Nested.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Markdown/Markdown_Demo_09_Lists_E_Nested.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Markdown/Markdown_Demo_09_Lists_E_Nested.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Markdown/Markdown_Demo_09_Lists_E_Nested.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Markdown/Markdown_Demo_10_Links.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Markdown/Markdown_Demo_10_Links.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Markdown/Markdown_Demo_10_Links.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Markdown/Markdown_Demo_10_Links.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Markdown/Markdown_Demo_11_Images.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Markdown/Markdown_Demo_11_Images.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Markdown/Markdown_Demo_11_Images.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Markdown/Markdown_Demo_11_Images.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Markdown/Markdown_Demo_12_Checklist_or_Task_List.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Markdown/Markdown_Demo_12_Checklist_or_Task_List.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Markdown/Markdown_Demo_12_Checklist_or_Task_List.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Markdown/Markdown_Demo_12_Checklist_or_Task_List.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Markdown/Markdown_Demo_13_Emoji.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Markdown/Markdown_Demo_13_Emoji.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Markdown/Markdown_Demo_13_Emoji.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Markdown/Markdown_Demo_13_Emoji.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Markdown/Markdown_Demo_14_Attachments.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Markdown/Markdown_Demo_14_Attachments.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Markdown/Markdown_Demo_14_Attachments.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Markdown/Markdown_Demo_14_Attachments.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Markdown/Markdown_Demo_15_Mathematical_Notations_and_Characters.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Markdown/Markdown_Demo_15_Mathematical_Notations_and_Characters.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Markdown/Markdown_Demo_15_Mathematical_Notations_and_Characters.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Markdown/Markdown_Demo_15_Mathematical_Notations_and_Characters.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Markdown/Markdown_Demo_99_Examples.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Markdown/Markdown_Demo_99_Examples.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Markdown/Markdown_Demo_99_Examples.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Markdown/Markdown_Demo_99_Examples.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Modal/EmployeeDemoComponent1.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Modal/EmployeeDemoComponent1.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Modal/EmployeeDemoComponent1.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Modal/EmployeeDemoComponent1.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Modal/EmployeeDemoComponent2.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Modal/EmployeeDemoComponent2.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Modal/EmployeeDemoComponent2.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Modal/EmployeeDemoComponent2.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Modal/ModalDocumentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Modal/ModalDocumentation.razor similarity index 91% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Modal/ModalDocumentation.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Modal/ModalDocumentation.razor index dc325f92e..f6891508a 100644 --- a/BlazorBootstrap.Demo.RCL/Components/Pages/Modal/ModalDocumentation.razor +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Modal/ModalDocumentation.razor @@ -1,15 +1,14 @@ @attribute [Route(pageUrl)] +@layout DemosMainLayout - + - - @pageDescription - - - +
    @@ -74,7 +73,7 @@
    @code { - private const string pageUrl = RouteConstants.Demos_Modal_Documentation; + private const string pageUrl = DemoRouteConstants.Demos_URL_Modal; private const string pageTitle = "Blazor Modal"; private const string pageDescription = "Use Blazor Bootstrap modal component to add dialogs to your site for lightboxes, user notifications, or completely custom content."; private const string metaTitle = "Blazor Modal Component"; diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Modal/Modal_Demo_01_Examples.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Modal/Modal_Demo_01_Examples.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Modal/Modal_Demo_01_Examples.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Modal/Modal_Demo_01_Examples.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Modal/Modal_Demo_02_A_Show_Dynamic_Component.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Modal/Modal_Demo_02_A_Show_Dynamic_Component.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Modal/Modal_Demo_02_A_Show_Dynamic_Component.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Modal/Modal_Demo_02_A_Show_Dynamic_Component.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Modal/Modal_Demo_02_B_Pass_Event_Callback_to_a_Dynamic_Component.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Modal/Modal_Demo_02_B_Pass_Event_Callback_to_a_Dynamic_Component.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Modal/Modal_Demo_02_B_Pass_Event_Callback_to_a_Dynamic_Component.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Modal/Modal_Demo_02_B_Pass_Event_Callback_to_a_Dynamic_Component.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Modal/Modal_Demo_02_Static_Backdrop.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Modal/Modal_Demo_02_Static_Backdrop.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Modal/Modal_Demo_02_Static_Backdrop.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Modal/Modal_Demo_02_Static_Backdrop.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Modal/Modal_Demo_03_Scrolling_Long_Content_A.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Modal/Modal_Demo_03_Scrolling_Long_Content_A.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Modal/Modal_Demo_03_Scrolling_Long_Content_A.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Modal/Modal_Demo_03_Scrolling_Long_Content_A.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Modal/Modal_Demo_03_Scrolling_Long_Content_B.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Modal/Modal_Demo_03_Scrolling_Long_Content_B.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Modal/Modal_Demo_03_Scrolling_Long_Content_B.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Modal/Modal_Demo_03_Scrolling_Long_Content_B.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Modal/Modal_Demo_04_Vertically_Centered.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Modal/Modal_Demo_04_Vertically_Centered.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Modal/Modal_Demo_04_Vertically_Centered.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Modal/Modal_Demo_04_Vertically_Centered.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Modal/Modal_Demo_04_Vertically_Centered_And_Scrollable.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Modal/Modal_Demo_04_Vertically_Centered_And_Scrollable.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Modal/Modal_Demo_04_Vertically_Centered_And_Scrollable.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Modal/Modal_Demo_04_Vertically_Centered_And_Scrollable.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Modal/Modal_Demo_05_Optional_Sizes.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Modal/Modal_Demo_05_Optional_Sizes.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Modal/Modal_Demo_05_Optional_Sizes.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Modal/Modal_Demo_05_Optional_Sizes.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Modal/Modal_Demo_06_Fullscreen_Modal.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Modal/Modal_Demo_06_Fullscreen_Modal.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Modal/Modal_Demo_06_Fullscreen_Modal.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Modal/Modal_Demo_06_Fullscreen_Modal.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Modal/Modal_Demo_07_Events.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Modal/Modal_Demo_07_Events.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Modal/Modal_Demo_07_Events.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Modal/Modal_Demo_07_Events.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Offcanvas/EmployeeDemoComponent1.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Offcanvas/EmployeeDemoComponent1.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Offcanvas/EmployeeDemoComponent1.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Offcanvas/EmployeeDemoComponent1.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Offcanvas/EmployeeDemoComponent2.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Offcanvas/EmployeeDemoComponent2.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Offcanvas/EmployeeDemoComponent2.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Offcanvas/EmployeeDemoComponent2.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Offcanvas/OffcanvasDocumentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Offcanvas/OffcanvasDocumentation.razor similarity index 90% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Offcanvas/OffcanvasDocumentation.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Offcanvas/OffcanvasDocumentation.razor index b9f1dc6cc..2dcf7ec27 100644 --- a/BlazorBootstrap.Demo.RCL/Components/Pages/Offcanvas/OffcanvasDocumentation.razor +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Offcanvas/OffcanvasDocumentation.razor @@ -1,15 +1,14 @@ @attribute [Route(pageUrl)] +@layout DemosMainLayout - + - - @pageDescription - - - + Similar to modals, only one offcanvas can be shown at a time. @@ -66,7 +65,7 @@ @code { - private const string pageUrl = RouteConstants.Demos_Offcanvas_Documentation; + private const string pageUrl = DemoRouteConstants.Demos_URL_Offcanvas; private const string pageTitle = "Blazor Offcanvas"; private const string pageDescription = "Build hidden sidebars into your project for navigation, shopping carts, and more with Blazor Bootstrap offcanvas component."; private const string metaTitle = "Blazor Offcanvas Component"; diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Offcanvas/Offcanvas_Demo_01_Examples.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Offcanvas/Offcanvas_Demo_01_Examples.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Offcanvas/Offcanvas_Demo_01_Examples.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Offcanvas/Offcanvas_Demo_01_Examples.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Offcanvas/Offcanvas_Demo_02_A_Show_Dynamic_Component.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Offcanvas/Offcanvas_Demo_02_A_Show_Dynamic_Component.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Offcanvas/Offcanvas_Demo_02_A_Show_Dynamic_Component.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Offcanvas/Offcanvas_Demo_02_A_Show_Dynamic_Component.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Offcanvas/Offcanvas_Demo_02_B_Pass_Event_Callback_to_a_Dynamic_Component.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Offcanvas/Offcanvas_Demo_02_B_Pass_Event_Callback_to_a_Dynamic_Component.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Offcanvas/Offcanvas_Demo_02_B_Pass_Event_Callback_to_a_Dynamic_Component.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Offcanvas/Offcanvas_Demo_02_B_Pass_Event_Callback_to_a_Dynamic_Component.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Offcanvas/Offcanvas_Demo_03_Placement.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Offcanvas/Offcanvas_Demo_03_Placement.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Offcanvas/Offcanvas_Demo_03_Placement.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Offcanvas/Offcanvas_Demo_03_Placement.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Offcanvas/Offcanvas_Demo_04_Static_Backdrop.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Offcanvas/Offcanvas_Demo_04_Static_Backdrop.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Offcanvas/Offcanvas_Demo_04_Static_Backdrop.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Offcanvas/Offcanvas_Demo_04_Static_Backdrop.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Offcanvas/Offcanvas_Demo_05_Sizes_A_Small.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Offcanvas/Offcanvas_Demo_05_Sizes_A_Small.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Offcanvas/Offcanvas_Demo_05_Sizes_A_Small.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Offcanvas/Offcanvas_Demo_05_Sizes_A_Small.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Offcanvas/Offcanvas_Demo_05_Sizes_B_Large.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Offcanvas/Offcanvas_Demo_05_Sizes_B_Large.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Offcanvas/Offcanvas_Demo_05_Sizes_B_Large.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Offcanvas/Offcanvas_Demo_05_Sizes_B_Large.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Offcanvas/Offcanvas_Demo_06_Events.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Offcanvas/Offcanvas_Demo_06_Events.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Offcanvas/Offcanvas_Demo_06_Events.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Offcanvas/Offcanvas_Demo_06_Events.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Pagination/PaginationDocumentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Pagination/PaginationDocumentation.razor similarity index 81% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Pagination/PaginationDocumentation.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Pagination/PaginationDocumentation.razor index 9f2acba7b..028f12196 100644 --- a/BlazorBootstrap.Demo.RCL/Components/Pages/Pagination/PaginationDocumentation.razor +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Pagination/PaginationDocumentation.razor @@ -1,15 +1,14 @@ @attribute [Route(pageUrl)] +@layout DemosMainLayout - + - - @pageDescription - - - +
    We use a large block of connected links for our pagination, making links hard to miss and easily scalable—all while providing large hit areas. Pagination is built with list HTML elements so screen readers can announce the number of available links.
    @@ -38,7 +37,7 @@
    @code { - private const string pageUrl = RouteConstants.Demos_Pagination_Documentation; + private const string pageUrl = DemoRouteConstants.Demos_URL_Pagination; private const string pageTitle = "Blazor Pagination"; private const string pageDescription = "Use Blazor Bootstrap pagination component to indicate a series of related content exists across multiple pages."; private const string metaTitle = "Blazor Pagination Component"; diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Pagination/Pagination_Demo_01_Examples.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Pagination/Pagination_Demo_01_Examples.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Pagination/Pagination_Demo_01_Examples.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Pagination/Pagination_Demo_01_Examples.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Pagination/Pagination_Demo_02_Working_With_Icons.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Pagination/Pagination_Demo_02_Working_With_Icons.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Pagination/Pagination_Demo_02_Working_With_Icons.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Pagination/Pagination_Demo_02_Working_With_Icons.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Pagination/Pagination_Demo_03_Disabled_And_Active_States.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Pagination/Pagination_Demo_03_Disabled_And_Active_States.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Pagination/Pagination_Demo_03_Disabled_And_Active_States.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Pagination/Pagination_Demo_03_Disabled_And_Active_States.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Pagination/Pagination_Demo_04_Sizing.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Pagination/Pagination_Demo_04_Sizing.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Pagination/Pagination_Demo_04_Sizing.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Pagination/Pagination_Demo_04_Sizing.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Pagination/Pagination_Demo_05_Alignment.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Pagination/Pagination_Demo_05_Alignment.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Pagination/Pagination_Demo_05_Alignment.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Pagination/Pagination_Demo_05_Alignment.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Pagination/Pagination_Demo_06_Events.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Pagination/Pagination_Demo_06_Events.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Pagination/Pagination_Demo_06_Events.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Pagination/Pagination_Demo_06_Events.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/PdfViewer/PdfViewerDocumentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/PdfViewer/PdfViewerDocumentation.razor similarity index 59% rename from BlazorBootstrap.Demo.RCL/Components/Pages/PdfViewer/PdfViewerDocumentation.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/PdfViewer/PdfViewerDocumentation.razor index c959b8d54..d253e0664 100644 --- a/BlazorBootstrap.Demo.RCL/Components/Pages/PdfViewer/PdfViewerDocumentation.razor +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/PdfViewer/PdfViewerDocumentation.razor @@ -1,15 +1,14 @@ @attribute [Route(pageUrl)] +@layout DemosMainLayout - + - - @pageDescription - - - +
    @@ -35,8 +34,23 @@
    +
    +
    + To open a password-protected PDF document, set the Password parameter to the required password. +
    + +
    + +
    +
    + If the Password parameter is not set and the PDF document is password-protected, the PDF Viewer component will prompt the user to enter the password. + In the following example, the PDF Viewer prompts the user to enter the password for the protected PDF document. Enter 12345 as the password to view the document. +
    + +
    + @code { - private const string pageUrl = RouteConstants.Demos_PDFViewer_Documentation; + private const string pageUrl = DemoRouteConstants.Demos_URL_PDFViewer; private const string pageTitle = "Blazor PDF Viewer"; private const string pageDescription = "The Blazor PDF Viewer component allows users to view PDF files directly in the browser, without relying on third-party browser tools or extensions."; private const string metaTitle = "Blazor PDF Viewer Component"; diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/PdfViewer/PdfViewer_Demo_01_Examples.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/PdfViewer/PdfViewer_Demo_01_Examples.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/PdfViewer/PdfViewer_Demo_01_Examples.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/PdfViewer/PdfViewer_Demo_01_Examples.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/PdfViewer/PdfViewer_Demo_02_Orientation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/PdfViewer/PdfViewer_Demo_02_Orientation.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/PdfViewer/PdfViewer_Demo_02_Orientation.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/PdfViewer/PdfViewer_Demo_02_Orientation.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/PdfViewer/PdfViewer_Demo_03_Base64String.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/PdfViewer/PdfViewer_Demo_03_Base64String.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/PdfViewer/PdfViewer_Demo_03_Base64String.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/PdfViewer/PdfViewer_Demo_03_Base64String.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/PdfViewer/PdfViewer_Demo_04_RTL_Doc_Example.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/PdfViewer/PdfViewer_Demo_04_RTL_Doc_Example.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/PdfViewer/PdfViewer_Demo_04_RTL_Doc_Example.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/PdfViewer/PdfViewer_Demo_04_RTL_Doc_Example.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/PdfViewer/PdfViewer_Demo_05_Password_Protected_A.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/PdfViewer/PdfViewer_Demo_05_Password_Protected_A.razor new file mode 100644 index 000000000..106406c29 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/PdfViewer/PdfViewer_Demo_05_Password_Protected_A.razor @@ -0,0 +1,3 @@ + diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/PdfViewer/PdfViewer_Demo_05_Password_Protected_B_Prompt_For_Password.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/PdfViewer/PdfViewer_Demo_05_Password_Protected_B_Prompt_For_Password.razor new file mode 100644 index 000000000..f09dfbfc4 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/PdfViewer/PdfViewer_Demo_05_Password_Protected_B_Prompt_For_Password.razor @@ -0,0 +1,16 @@ +@if (showPdfViewer) +{ + +} +else +{ + +} + +@code { + private bool showPdfViewer = false; + + private void OnDocumentLoadError(string errorMessage) => showPdfViewer = false; +} \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Placeholders/PlaceholderDocumentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Placeholders/PlaceholderDocumentation.razor similarity index 82% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Placeholders/PlaceholderDocumentation.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Placeholders/PlaceholderDocumentation.razor index e8e9b4c86..5d1be4ab0 100644 --- a/BlazorBootstrap.Demo.RCL/Components/Pages/Placeholders/PlaceholderDocumentation.razor +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Placeholders/PlaceholderDocumentation.razor @@ -1,15 +1,14 @@ @attribute [Route(pageUrl)] +@layout DemosMainLayout - + - - @pageDescription - - - +
    @@ -42,7 +41,7 @@
    @code { - private const string pageUrl = RouteConstants.Demos_Placeholders_Documentation; + private const string pageUrl = DemoRouteConstants.Demos_URL_Placeholders; private const string pageTitle = "Blazor Placeholder"; private const string pageDescription = "Use Blazor Bootstrap loading placeholders for your components or pages to indicate something may still be loading."; private const string metaTitle = "Blazor Placeholder Component"; diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Placeholders/Placeholder_Demo_01_Examples.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Placeholders/Placeholder_Demo_01_Examples.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Placeholders/Placeholder_Demo_01_Examples.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Placeholders/Placeholder_Demo_01_Examples.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Placeholders/Placeholder_Demo_02_Width.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Placeholders/Placeholder_Demo_02_Width.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Placeholders/Placeholder_Demo_02_Width.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Placeholders/Placeholder_Demo_02_Width.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Placeholders/Placeholder_Demo_03_Color.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Placeholders/Placeholder_Demo_03_Color.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Placeholders/Placeholder_Demo_03_Color.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Placeholders/Placeholder_Demo_03_Color.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Placeholders/Placeholder_Demo_04_Sizing.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Placeholders/Placeholder_Demo_04_Sizing.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Placeholders/Placeholder_Demo_04_Sizing.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Placeholders/Placeholder_Demo_04_Sizing.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Placeholders/Placeholder_Demo_05_Animation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Placeholders/Placeholder_Demo_05_Animation.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Placeholders/Placeholder_Demo_05_Animation.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Placeholders/Placeholder_Demo_05_Animation.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Preload/PreloadDocumentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Preload/PreloadDocumentation.razor similarity index 86% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Preload/PreloadDocumentation.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Preload/PreloadDocumentation.razor index 46cddc921..9df788f1b 100644 --- a/BlazorBootstrap.Demo.RCL/Components/Pages/Preload/PreloadDocumentation.razor +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Preload/PreloadDocumentation.razor @@ -1,15 +1,14 @@ @attribute [Route(pageUrl)] +@layout DemosMainLayout - + - - @pageDescription - - - +
    @@ -43,7 +42,7 @@
    @code { - private const string pageUrl = RouteConstants.Demos_Preload_Documentation; + private const string pageUrl = DemoRouteConstants.Demos_URL_Preload; private const string pageTitle = "Blazor Preload"; private const string pageDescription = "Indicate the loading state of a page with Blazor Bootstrap preload component."; private const string metaTitle = "Blazor Preload Component"; diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Preload/Preload_Demo_01_Global_Preload_For_Application_A.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Preload/Preload_Demo_01_Global_Preload_For_Application_A.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Preload/Preload_Demo_01_Global_Preload_For_Application_A.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Preload/Preload_Demo_01_Global_Preload_For_Application_A.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Preload/Preload_Demo_01_Global_Preload_For_Application_B.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Preload/Preload_Demo_01_Global_Preload_For_Application_B.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Preload/Preload_Demo_01_Global_Preload_For_Application_B.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Preload/Preload_Demo_01_Global_Preload_For_Application_B.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Preload/Preload_Demo_02_Loading_Text.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Preload/Preload_Demo_02_Loading_Text.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Preload/Preload_Demo_02_Loading_Text.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Preload/Preload_Demo_02_Loading_Text.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Preload/Preload_Demo_03_Change_Spinner_Color.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Preload/Preload_Demo_03_Change_Spinner_Color.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Preload/Preload_Demo_03_Change_Spinner_Color.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Preload/Preload_Demo_03_Change_Spinner_Color.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Progress/ProgressDocumentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Progress/ProgressDocumentation.razor similarity index 88% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Progress/ProgressDocumentation.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Progress/ProgressDocumentation.razor index 255329d78..6480693be 100644 --- a/BlazorBootstrap.Demo.RCL/Components/Pages/Progress/ProgressDocumentation.razor +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Progress/ProgressDocumentation.razor @@ -1,15 +1,14 @@ @attribute [Route(pageUrl)] +@layout DemosMainLayout - + - - @pageDescription - - - +
    @@ -60,7 +59,7 @@
    @code { - private const string pageUrl = RouteConstants.Demos_Progress_Documentation; + private const string pageUrl = DemoRouteConstants.Demos_URL_Progress; private const string pageTitle = "Blazor Progress"; private const string pageDescription = "Documentation and examples for using Blazor Bootstrap custom progress bars featuring support for stacked bars, animated backgrounds, and text labels."; private const string metaTitle = "Blazor Progress Component"; diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Progress/Progress_Demo_01_How_It_Works.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Progress/Progress_Demo_01_How_It_Works.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Progress/Progress_Demo_01_How_It_Works.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Progress/Progress_Demo_01_How_It_Works.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Progress/Progress_Demo_02_Labels.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Progress/Progress_Demo_02_Labels.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Progress/Progress_Demo_02_Labels.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Progress/Progress_Demo_02_Labels.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Progress/Progress_Demo_03_Set_Width_Programmatically.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Progress/Progress_Demo_03_Set_Width_Programmatically.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Progress/Progress_Demo_03_Set_Width_Programmatically.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Progress/Progress_Demo_03_Set_Width_Programmatically.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Progress/Progress_Demo_04_Height.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Progress/Progress_Demo_04_Height.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Progress/Progress_Demo_04_Height.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Progress/Progress_Demo_04_Height.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Progress/Progress_Demo_05_Backgrounds.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Progress/Progress_Demo_05_Backgrounds.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Progress/Progress_Demo_05_Backgrounds.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Progress/Progress_Demo_05_Backgrounds.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Progress/Progress_Demo_06_Set_Background_Programmatically.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Progress/Progress_Demo_06_Set_Background_Programmatically.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Progress/Progress_Demo_06_Set_Background_Programmatically.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Progress/Progress_Demo_06_Set_Background_Programmatically.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Progress/Progress_Demo_07_MultipleBars.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Progress/Progress_Demo_07_MultipleBars.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Progress/Progress_Demo_07_MultipleBars.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Progress/Progress_Demo_07_MultipleBars.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Progress/Progress_Demo_08_Striped.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Progress/Progress_Demo_08_Striped.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Progress/Progress_Demo_08_Striped.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Progress/Progress_Demo_08_Striped.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Progress/Progress_Demo_09_Animated_Stripes.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Progress/Progress_Demo_09_Animated_Stripes.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Progress/Progress_Demo_09_Animated_Stripes.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Progress/Progress_Demo_09_Animated_Stripes.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Progress/Progress_Demo_10_Dynamic_Progress.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Progress/Progress_Demo_10_Dynamic_Progress.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Progress/Progress_Demo_10_Dynamic_Progress.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Progress/Progress_Demo_10_Dynamic_Progress.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Ribbon/RibbonDocumentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Ribbon/RibbonDocumentation.razor similarity index 73% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Ribbon/RibbonDocumentation.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Ribbon/RibbonDocumentation.razor index 4f745b72b..005924ef3 100644 --- a/BlazorBootstrap.Demo.RCL/Components/Pages/Ribbon/RibbonDocumentation.razor +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Ribbon/RibbonDocumentation.razor @@ -1,15 +1,14 @@ @attribute [Route(pageUrl)] +@layout DemosMainLayout - + - - @pageDescription - - - +
    In the following example, you will see a ribbon similar to the one found in Outlook.
    @@ -26,7 +25,7 @@
    @code { - private const string pageUrl = RouteConstants.Demos_Ribbon_Documentation; + private const string pageUrl = DemoRouteConstants.Demos_URL_Ribbon; private const string pageTitle = "Blazor Ribbon"; private const string pageDescription = "Documentation and examples for using the Blazor Bootstrap Ribbon component."; private const string metaTitle = "Blazor Ribbon Component"; diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Ribbon/Ribbon_Demo_01_How_It_Works.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Ribbon/Ribbon_Demo_01_How_It_Works.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Ribbon/Ribbon_Demo_01_How_It_Works.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Ribbon/Ribbon_Demo_01_How_It_Works.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Ribbon/Ribbon_Demo_02_Images.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Ribbon/Ribbon_Demo_02_Images.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Ribbon/Ribbon_Demo_02_Images.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Ribbon/Ribbon_Demo_02_Images.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/ScriptLoader/ScriptLoaderDocumentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/ScriptLoader/ScriptLoaderDocumentation.razor similarity index 83% rename from BlazorBootstrap.Demo.RCL/Components/Pages/ScriptLoader/ScriptLoaderDocumentation.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/ScriptLoader/ScriptLoaderDocumentation.razor index c45a6e280..b205f6b9d 100644 --- a/BlazorBootstrap.Demo.RCL/Components/Pages/ScriptLoader/ScriptLoaderDocumentation.razor +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/ScriptLoader/ScriptLoaderDocumentation.razor @@ -1,15 +1,14 @@ @attribute [Route(pageUrl)] +@layout DemosMainLayout - + - - @pageDescription - - - +
    @@ -54,7 +53,7 @@
    @code { - private const string pageUrl = RouteConstants.Demos_ScriptLoader_Documentation; + private const string pageUrl = DemoRouteConstants.Demos_URL_ScriptLoader; private const string pageTitle = "Blazor ScriptLoader"; private const string pageDescription = "Documentation and examples for using the Blazor Bootstrap ScriptLoader component."; private const string metaTitle = "Blazor ScriptLoader Component"; diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/ScriptLoader/ScriptLoader_Demo_01_Examples.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/ScriptLoader/ScriptLoader_Demo_01_Examples.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/ScriptLoader/ScriptLoader_Demo_01_Examples.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/ScriptLoader/ScriptLoader_Demo_01_Examples.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/ScriptLoader/ScriptLoader_Demo_02_Events.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/ScriptLoader/ScriptLoader_Demo_02_Events.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/ScriptLoader/ScriptLoader_Demo_02_Events.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/ScriptLoader/ScriptLoader_Demo_02_Events.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Services/ModalService/ModalServiceDocumentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Services/ModalService/ModalServiceDocumentation.razor similarity index 83% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Services/ModalService/ModalServiceDocumentation.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Services/ModalService/ModalServiceDocumentation.razor index fa9cf45fb..e6c5b23a7 100644 --- a/BlazorBootstrap.Demo.RCL/Components/Pages/Services/ModalService/ModalServiceDocumentation.razor +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Services/ModalService/ModalServiceDocumentation.razor @@ -1,17 +1,16 @@ @page "/modal-service" @attribute [Route(pageUrl)] +@layout DemosMainLayout - + - - @pageDescription - - - +
    @@ -46,7 +45,7 @@
    @code { - private const string pageUrl = RouteConstants.Demos_ModalService_Documentation; + private const string pageUrl = DemoRouteConstants.Demos_URL_ModalService; private const string pageTitle = "Blazor Modal Service"; private const string pageDescription = "Use Blazor Bootstrap modal service to show quick dialogs to your site for lightboxes, user notifications, or completely custom content."; private const string metaTitle = "Blazor Modal Service"; diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Services/ModalService/ModalService_Demo_01_How_It_Works.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Services/ModalService/ModalService_Demo_01_How_It_Works.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Services/ModalService/ModalService_Demo_01_How_It_Works.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Services/ModalService/ModalService_Demo_01_How_It_Works.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Services/ModalService/ModalService_Demo_02_Vertically_Centered_Modal.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Services/ModalService/ModalService_Demo_02_Vertically_Centered_Modal.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Services/ModalService/ModalService_Demo_02_Vertically_Centered_Modal.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Services/ModalService/ModalService_Demo_02_Vertically_Centered_Modal.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Services/ModalService/ModalService_Demo_03_Size.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Services/ModalService/ModalService_Demo_03_Size.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Services/ModalService/ModalService_Demo_03_Size.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Services/ModalService/ModalService_Demo_03_Size.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Services/ModalService/ModalService_Demo_04_Change_Footer_Button_Color_and_Text.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Services/ModalService/ModalService_Demo_04_Change_Footer_Button_Color_and_Text.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Services/ModalService/ModalService_Demo_04_Change_Footer_Button_Color_and_Text.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Services/ModalService/ModalService_Demo_04_Change_Footer_Button_Color_and_Text.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Services/ModalService/ModalService_Demo_05_Hide_Footer_Button.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Services/ModalService/ModalService_Demo_05_Hide_Footer_Button.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Services/ModalService/ModalService_Demo_05_Hide_Footer_Button.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Services/ModalService/ModalService_Demo_05_Hide_Footer_Button.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Services/ModalService/ModalService_Demo_06_Callback.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Services/ModalService/ModalService_Demo_06_Callback.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Services/ModalService/ModalService_Demo_06_Callback.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Services/ModalService/ModalService_Demo_06_Callback.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Services/ModalService/ModalService_Demo_100_Global_Modal_Service_For_Application_01.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Services/ModalService/ModalService_Demo_100_Global_Modal_Service_For_Application_01.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Services/ModalService/ModalService_Demo_100_Global_Modal_Service_For_Application_01.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Services/ModalService/ModalService_Demo_100_Global_Modal_Service_For_Application_01.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Services/ModalService/ModalService_Demo_100_Global_Modal_Service_For_Application_02.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Services/ModalService/ModalService_Demo_100_Global_Modal_Service_For_Application_02.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Services/ModalService/ModalService_Demo_100_Global_Modal_Service_For_Application_02.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Services/ModalService/ModalService_Demo_100_Global_Modal_Service_For_Application_02.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Services/ToastService/ToastServiceDocumentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Services/ToastService/ToastServiceDocumentation.razor new file mode 100644 index 000000000..4544fed0d --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Services/ToastService/ToastServiceDocumentation.razor @@ -0,0 +1,40 @@ +@page "/toast-service" +@using BlazorBootstrap.Demo.RCL.Components.Pages.Demos.Toasts + +@attribute [Route(pageUrl)] +@layout DemosMainLayout + + + + + +
    Use Blazor ToastService to publish application-level toast notifications from anywhere in your app.
    + +
    +
    1. Add the Toasts component in MainLayout.razor page as shown below.
    + + + + Set the Toasts component parameters as per your requirement. + + +
    2. Inject ToastService, then call Notify(...) for the common single Toasts host scenario.
    + + +
    3. Use await NotifyAsync(...) when multiple toast subscribers may be registered and the caller needs to await all handlers.
    + +
    + +@code { + private const string pageUrl = DemoRouteConstants.Demos_URL_ToastService; + private const string pageTitle = "Blazor Toast Service"; + private const string pageDescription = "Use Blazor Bootstrap toast service to publish application-level toast notifications from anywhere in your app."; + private const string metaTitle = "Blazor Toast Service"; + private const string metaDescription = "Use Blazor Bootstrap toast service to publish application-level toast notifications from anywhere in your app."; + private const string imageUrl = DemoScreenshotSrcConstants.Demos_URL_Toasts; +} \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Services/ToastService/ToastService_Demo_01_NotifyAsync_With_Multiple_Subscribers.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Services/ToastService/ToastService_Demo_01_NotifyAsync_With_Multiple_Subscribers.razor new file mode 100644 index 000000000..1837f3b3d --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Services/ToastService/ToastService_Demo_01_NotifyAsync_With_Multiple_Subscribers.razor @@ -0,0 +1,39 @@ +
    +
    This example registers two Toasts hosts on the same page. Clicking the button publishes one message to both hosts and awaits both subscribers.
    + +
    + +
    + +
    @statusMessage
    + + @* These local Toasts hosts intentionally add extra ToastService subscribers on this page + so NotifyAsync can demonstrate awaiting multiple handlers for a single published message. *@ + + +
    + +@code { + [Inject] + protected ToastService ToastService { get; set; } = default!; + + private bool isNotifying; + + private string statusMessage = "Click the button to publish the same toast to two hosts."; + + private async Task NotifyBothHostsAsync() + { + isNotifying = true; + statusMessage = "Publishing to both toast hosts..."; + + await ToastService.NotifyAsync(new ToastMessage( + ToastType.Info, + "Toast Service", + $"NotifyAsync delivered this message to both toast hosts at {DateTime.Now:T}.")); + + statusMessage = $"NotifyAsync completed after both toast hosts handled the message at {DateTime.Now:T}."; + isNotifying = false; + } +} \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Sidebar/SidebarDocumentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Sidebar/SidebarDocumentation.razor similarity index 86% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Sidebar/SidebarDocumentation.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Sidebar/SidebarDocumentation.razor index 285de70bf..a4bac4757 100644 --- a/BlazorBootstrap.Demo.RCL/Components/Pages/Sidebar/SidebarDocumentation.razor +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Sidebar/SidebarDocumentation.razor @@ -1,15 +1,14 @@ @attribute [Route(pageUrl)] +@layout DemosMainLayout - + - - @pageDescription - - - +
    @@ -66,8 +65,13 @@
    +
    +
    + +
    + @code { - private const string pageUrl = RouteConstants.Demos_Sidebar_Documentation; + private const string pageUrl = DemoRouteConstants.Demos_URL_Sidebar; private const string pageTitle = "Blazor Sidebar"; private const string pageDescription = "Use the Blazor Bootstrap Sidebar component to show consistent cross-browser, responsive and cross-device navigation links, additional information, or other content."; private const string metaTitle = "Blazor Sidebar Component"; diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Sidebar/Sidebar_Demo_01_Basic_Usage.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Sidebar/Sidebar_Demo_01_Basic_Usage.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Sidebar/Sidebar_Demo_01_Basic_Usage.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Sidebar/Sidebar_Demo_01_Basic_Usage.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Sidebar/Sidebar_Demo_02_Two_level_navigation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Sidebar/Sidebar_Demo_02_Two_level_navigation.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Sidebar/Sidebar_Demo_02_Two_level_navigation.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Sidebar/Sidebar_Demo_02_Two_level_navigation.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Sidebar/Sidebar_Demo_03_Change_Icons_Color.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Sidebar/Sidebar_Demo_03_Change_Icons_Color.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Sidebar/Sidebar_Demo_03_Change_Icons_Color.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Sidebar/Sidebar_Demo_03_Change_Icons_Color.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Sidebar/Sidebar_Demo_04_Full_layout_with_sidebar.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Sidebar/Sidebar_Demo_04_Full_layout_with_sidebar.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Sidebar/Sidebar_Demo_04_Full_layout_with_sidebar.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Sidebar/Sidebar_Demo_04_Full_layout_with_sidebar.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Sidebar/Sidebar_Demo_05_Toggle_Sidebar_to_Show_Icons_Only.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Sidebar/Sidebar_Demo_05_Toggle_Sidebar_to_Show_Icons_Only.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Sidebar/Sidebar_Demo_05_Toggle_Sidebar_to_Show_Icons_Only.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Sidebar/Sidebar_Demo_05_Toggle_Sidebar_to_Show_Icons_Only.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Sidebar/Sidebar_Demo_06_Show_Badge.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Sidebar/Sidebar_Demo_06_Show_Badge.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Sidebar/Sidebar_Demo_06_Show_Badge.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Sidebar/Sidebar_Demo_06_Show_Badge.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Sidebar/Sidebar_Demo_07_Custom_Brand_Icon.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Sidebar/Sidebar_Demo_07_Custom_Brand_Icon.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Sidebar/Sidebar_Demo_07_Custom_Brand_Icon.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Sidebar/Sidebar_Demo_07_Custom_Brand_Icon.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Sidebar/Sidebar_Demo_08_Show_Image_as_Brand_Logo.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Sidebar/Sidebar_Demo_08_Show_Image_as_Brand_Logo.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Sidebar/Sidebar_Demo_08_Show_Image_as_Brand_Logo.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Sidebar/Sidebar_Demo_08_Show_Image_as_Brand_Logo.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Sidebar/Sidebar_Demo_09_Customize_Sidebar.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Sidebar/Sidebar_Demo_09_Customize_Sidebar.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Sidebar/Sidebar_Demo_09_Customize_Sidebar.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Sidebar/Sidebar_Demo_09_Customize_Sidebar.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Sidebar/Sidebar_Demo_10_Apply_Custom_CSS_Class_to_NavItem.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Sidebar/Sidebar_Demo_10_Apply_Custom_CSS_Class_to_NavItem.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Sidebar/Sidebar_Demo_10_Apply_Custom_CSS_Class_to_NavItem.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Sidebar/Sidebar_Demo_10_Apply_Custom_CSS_Class_to_NavItem.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Sidebar/Sidebar_Demo_11_Width.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Sidebar/Sidebar_Demo_11_Width.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Sidebar/Sidebar_Demo_11_Width.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Sidebar/Sidebar_Demo_11_Width.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Sidebar/Sidebar_Demo_12_Company_Logo_FullWidth.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Sidebar/Sidebar_Demo_12_Company_Logo_FullWidth.razor new file mode 100644 index 000000000..739c3141d --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Sidebar/Sidebar_Demo_12_Company_Logo_FullWidth.razor @@ -0,0 +1,31 @@ + + +@code { + IEnumerable? navItems; + + private async Task SidebarDataProvider(SidebarDataProviderRequest request) + { + if (navItems is null) + navItems = GetNavItems(); + + return await Task.FromResult(request.ApplyTo(navItems)); + } + + private IEnumerable GetNavItems() + { + navItems = new List + { + new NavItem { Href = "/getting-started", IconName = IconName.HouseDoorFill, Text = "Getting Started"}, + new NavItem { Href = "/alerts", IconName = IconName.CheckCircleFill, Text = "Alerts"}, + new NavItem { Href = "/autocomplete", IconName = IconName.InputCursorText, Text = "Auto Complete"}, + new NavItem { Href = "/breadcrumb", IconName = IconName.SegmentedNav, Text = "Breadcrumb"}, + new NavItem { Href = "/sidebar", IconName = IconName.LayoutSidebarInset, Text = "Sidebar"}, + }; + return navItems; + } +} diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Sidebar2/Sidebar2Documentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Sidebar2/Sidebar2Documentation.razor similarity index 78% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Sidebar2/Sidebar2Documentation.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Sidebar2/Sidebar2Documentation.razor index 5c9f2ec1b..84c0a652d 100644 --- a/BlazorBootstrap.Demo.RCL/Components/Pages/Sidebar2/Sidebar2Documentation.razor +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Sidebar2/Sidebar2Documentation.razor @@ -1,15 +1,14 @@ @attribute [Route(pageUrl)] +@layout DemosMainLayout - + - - @pageDescription - - - +
    @@ -46,8 +45,13 @@
    +
    +
    + +
    + @code { - private const string pageUrl = RouteConstants.Demos_Sidebar2_Documentation; + private const string pageUrl = DemoRouteConstants.Demos_URL_Sidebar2; private const string pageTitle = "Blazor Sidebar2"; private const string pageDescription = "Use the Blazor Bootstrap Sidebar2 component to display consistent, cross-browser, and responsive navigation links that support more than two nested levels."; private const string metaTitle = "Blazor Sidebar2 Component"; diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Sidebar2/Sidebar2_Demo_01_Basic_Usage.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Sidebar2/Sidebar2_Demo_01_Basic_Usage.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Sidebar2/Sidebar2_Demo_01_Basic_Usage.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Sidebar2/Sidebar2_Demo_01_Basic_Usage.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Sidebar2/Sidebar2_Demo_02_More_Nested_Levels.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Sidebar2/Sidebar2_Demo_02_More_Nested_Levels.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Sidebar2/Sidebar2_Demo_02_More_Nested_Levels.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Sidebar2/Sidebar2_Demo_02_More_Nested_Levels.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Sidebar2/Sidebar2_Demo_03_Change_Icons_Color.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Sidebar2/Sidebar2_Demo_03_Change_Icons_Color.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Sidebar2/Sidebar2_Demo_03_Change_Icons_Color.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Sidebar2/Sidebar2_Demo_03_Change_Icons_Color.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Sidebar2/Sidebar2_Demo_04_Full_layout_with_sidebar.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Sidebar2/Sidebar2_Demo_04_Full_layout_with_sidebar.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Sidebar2/Sidebar2_Demo_04_Full_layout_with_sidebar.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Sidebar2/Sidebar2_Demo_04_Full_layout_with_sidebar.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Sidebar2/Sidebar2_Demo_07_Custom_Brand_Icon.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Sidebar2/Sidebar2_Demo_07_Custom_Brand_Icon.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Sidebar2/Sidebar2_Demo_07_Custom_Brand_Icon.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Sidebar2/Sidebar2_Demo_07_Custom_Brand_Icon.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Sidebar2/Sidebar2_Demo_08_Show_Image_as_Brand_Logo.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Sidebar2/Sidebar2_Demo_08_Show_Image_as_Brand_Logo.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Sidebar2/Sidebar2_Demo_08_Show_Image_as_Brand_Logo.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Sidebar2/Sidebar2_Demo_08_Show_Image_as_Brand_Logo.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Sidebar2/Sidebar2_Demo_09_Width.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Sidebar2/Sidebar2_Demo_09_Width.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Sidebar2/Sidebar2_Demo_09_Width.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Sidebar2/Sidebar2_Demo_09_Width.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Sidebar2/Sidebar2_Demo_10_Company_Logo_FullWidth.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Sidebar2/Sidebar2_Demo_10_Company_Logo_FullWidth.razor new file mode 100644 index 000000000..15989ce9b --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Sidebar2/Sidebar2_Demo_10_Company_Logo_FullWidth.razor @@ -0,0 +1,44 @@ + + +@code { + IEnumerable? navItems; + + private async Task Sidebar2DataProvider(Sidebar2DataProviderRequest request) + { + if (navItems is null) + navItems = GetNavItems(); + + return await Task.FromResult(request.ApplyTo(navItems)); + } + + private IEnumerable GetNavItems() + { + navItems = new List + { + new NavItem { Id = "1", Href = "/getting-started", IconName = IconName.HouseDoorFill, Text = "Getting Started"}, + + new NavItem { Id = "2", IconName = IconName.LayoutSidebarInset, Text = "Content" }, + new NavItem { Id = "3", Href = "/icons", IconName = IconName.PersonSquare, Text = "Icons", ParentId="2"}, + + new NavItem { Id = "4", IconName = IconName.ExclamationTriangleFill, Text = "Components" }, + new NavItem { Id = "5", Href = "/alerts", IconName = IconName.CheckCircleFill, Text = "Alerts", ParentId="4"}, + new NavItem { Id = "6", Href = "/breadcrumb", IconName = IconName.SegmentedNav, Text = "Breadcrumb", ParentId="4"}, + + new NavItem { Id = "7", IconName = IconName.ListNested, Text = "Sidebar 2", ParentId="4"}, + new NavItem { Id = "701", Href = "/sidebar2", IconName = IconName.Dash, Text = "How to use", ParentId="7"}, + new NavItem { Id = "702", Href = "/sidebar2-examples", IconName = IconName.Dash, Text = "Examples", ParentId="7"}, + + new NavItem { Id = "8", IconName = IconName.WindowPlus, Text = "Forms" }, + new NavItem { Id = "9", Href = "/autocomplete", IconName = IconName.InputCursorText, Text = "Auto Complete", ParentId="8"}, + new NavItem { Id = "10", Href = "/currency-input", IconName = IconName.CurrencyDollar, Text = "Currency Input", ParentId="8"}, + new NavItem { Id = "11", Href = "/number-input", IconName = IconName.InputCursor, Text = "Number Input", ParentId="8"}, + new NavItem { Id = "12", Href = "/switch", IconName = IconName.ToggleOn, Text = "Switch", ParentId="8"}, + }; + return navItems; + } +} diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/SortableList/SortableListDocumentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/SortableList/SortableListDocumentation.razor similarity index 87% rename from BlazorBootstrap.Demo.RCL/Components/Pages/SortableList/SortableListDocumentation.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/SortableList/SortableListDocumentation.razor index f1d6ae13c..182629d7c 100644 --- a/BlazorBootstrap.Demo.RCL/Components/Pages/SortableList/SortableListDocumentation.razor +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/SortableList/SortableListDocumentation.razor @@ -1,19 +1,18 @@ @attribute [Route(pageUrl)] +@layout DemosMainLayout - + - - @pageDescription - - - +
    Before using the SortableList component, include the SortableJS script reference in your index.html/_Host.cshtml file.
    - +
    @@ -81,7 +80,7 @@
    @code { - private const string pageUrl = RouteConstants.Demos_SortableList_Documentation; + private const string pageUrl = DemoRouteConstants.Demos_URL_SortableList; private const string pageTitle = "Blazor Sortable List"; private const string pageDescription = "The Blazor Bootstrap Sortable List component, built on top of SortableJS, enables drag-and-drop reordering of lists."; private const string metaTitle = "Blazor Sortable List Component"; diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/SortableList/SortableList_Demo_00_Setup.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/SortableList/SortableList_Demo_00_Setup.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/SortableList/SortableList_Demo_00_Setup.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/SortableList/SortableList_Demo_00_Setup.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/SortableList/SortableList_Demo_01_Examples.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/SortableList/SortableList_Demo_01_Examples.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/SortableList/SortableList_Demo_01_Examples.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/SortableList/SortableList_Demo_01_Examples.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/SortableList/SortableList_Demo_02_Shared_Lists_A.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/SortableList/SortableList_Demo_02_Shared_Lists_A.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/SortableList/SortableList_Demo_02_Shared_Lists_A.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/SortableList/SortableList_Demo_02_Shared_Lists_A.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/SortableList/SortableList_Demo_02_Shared_Lists_B_Three_Lists.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/SortableList/SortableList_Demo_02_Shared_Lists_B_Three_Lists.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/SortableList/SortableList_Demo_02_Shared_Lists_B_Three_Lists.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/SortableList/SortableList_Demo_02_Shared_Lists_B_Three_Lists.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/SortableList/SortableList_Demo_03_Cloning.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/SortableList/SortableList_Demo_03_Cloning.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/SortableList/SortableList_Demo_03_Cloning.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/SortableList/SortableList_Demo_03_Cloning.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/SortableList/SortableList_Demo_04_Disable_Sorting.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/SortableList/SortableList_Demo_04_Disable_Sorting.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/SortableList/SortableList_Demo_04_Disable_Sorting.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/SortableList/SortableList_Demo_04_Disable_Sorting.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/SortableList/SortableList_Demo_05_Handle.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/SortableList/SortableList_Demo_05_Handle.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/SortableList/SortableList_Demo_05_Handle.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/SortableList/SortableList_Demo_05_Handle.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/SortableList/SortableList_Demo_06_Disable_Item.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/SortableList/SortableList_Demo_06_Disable_Item.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/SortableList/SortableList_Demo_06_Disable_Item.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/SortableList/SortableList_Demo_06_Disable_Item.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/SortableList/SortableList_Demo_07_Nested_Sortables.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/SortableList/SortableList_Demo_07_Nested_Sortables.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/SortableList/SortableList_Demo_07_Nested_Sortables.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/SortableList/SortableList_Demo_07_Nested_Sortables.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/SortableList/SortableList_Demo_08_Dynamic_Data.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/SortableList/SortableList_Demo_08_Dynamic_Data.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/SortableList/SortableList_Demo_08_Dynamic_Data.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/SortableList/SortableList_Demo_08_Dynamic_Data.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/SortableList/SortableList_Demo_09_Empty_Data.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/SortableList/SortableList_Demo_09_Empty_Data.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/SortableList/SortableList_Demo_09_Empty_Data.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/SortableList/SortableList_Demo_09_Empty_Data.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Spinners/SpinnersDocumentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Spinners/SpinnersDocumentation.razor similarity index 87% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Spinners/SpinnersDocumentation.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Spinners/SpinnersDocumentation.razor index b9ad7ea1a..bbdb3bd45 100644 --- a/BlazorBootstrap.Demo.RCL/Components/Pages/Spinners/SpinnersDocumentation.razor +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Spinners/SpinnersDocumentation.razor @@ -1,15 +1,14 @@ @attribute [Route(pageUrl)] +@layout DemosMainLayout - + - - @pageDescription - - - +
    Use the border spinners for a lightweight loading indicator.
    @@ -67,7 +66,7 @@
    @code{ - private const string pageUrl = RouteConstants.Demos_Spinners_Documentation; + private const string pageUrl = DemoRouteConstants.Demos_URL_Spinners; private const string pageTitle = "Blazor Spinner"; private const string pageDescription = "Visualize the loading state of a component or page using the Blazor Bootstrap Spinner component."; private const string metaTitle = "Blazor Spinner Component"; diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Spinners/Spinners_Demo_01_Border_Spinner.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Spinners/Spinners_Demo_01_Border_Spinner.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Spinners/Spinners_Demo_01_Border_Spinner.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Spinners/Spinners_Demo_01_Border_Spinner.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Spinners/Spinners_Demo_02_Colors.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Spinners/Spinners_Demo_02_Colors.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Spinners/Spinners_Demo_02_Colors.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Spinners/Spinners_Demo_02_Colors.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Spinners/Spinners_Demo_03_Grow_spinner_A.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Spinners/Spinners_Demo_03_Grow_spinner_A.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Spinners/Spinners_Demo_03_Grow_spinner_A.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Spinners/Spinners_Demo_03_Grow_spinner_A.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Spinners/Spinners_Demo_03_Grow_spinner_B.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Spinners/Spinners_Demo_03_Grow_spinner_B.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Spinners/Spinners_Demo_03_Grow_spinner_B.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Spinners/Spinners_Demo_03_Grow_spinner_B.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Spinners/Spinners_Demo_04_Loading_dots_spinner_A.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Spinners/Spinners_Demo_04_Loading_dots_spinner_A.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Spinners/Spinners_Demo_04_Loading_dots_spinner_A.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Spinners/Spinners_Demo_04_Loading_dots_spinner_A.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Spinners/Spinners_Demo_04_Loading_dots_spinner_B.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Spinners/Spinners_Demo_04_Loading_dots_spinner_B.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Spinners/Spinners_Demo_04_Loading_dots_spinner_B.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Spinners/Spinners_Demo_04_Loading_dots_spinner_B.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Spinners/Spinners_Demo_05_Alignment_A_Margin.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Spinners/Spinners_Demo_05_Alignment_A_Margin.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Spinners/Spinners_Demo_05_Alignment_A_Margin.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Spinners/Spinners_Demo_05_Alignment_A_Margin.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Spinners/Spinners_Demo_05_Alignment_B_Palcement_Flex_01.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Spinners/Spinners_Demo_05_Alignment_B_Palcement_Flex_01.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Spinners/Spinners_Demo_05_Alignment_B_Palcement_Flex_01.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Spinners/Spinners_Demo_05_Alignment_B_Palcement_Flex_01.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Spinners/Spinners_Demo_05_Alignment_B_Palcement_Flex_02.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Spinners/Spinners_Demo_05_Alignment_B_Palcement_Flex_02.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Spinners/Spinners_Demo_05_Alignment_B_Palcement_Flex_02.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Spinners/Spinners_Demo_05_Alignment_B_Palcement_Flex_02.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Spinners/Spinners_Demo_05_Alignment_C_Palcement_Floats.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Spinners/Spinners_Demo_05_Alignment_C_Palcement_Floats.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Spinners/Spinners_Demo_05_Alignment_C_Palcement_Floats.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Spinners/Spinners_Demo_05_Alignment_C_Palcement_Floats.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Spinners/Spinners_Demo_05_Alignment_D_Palcement_Text_align.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Spinners/Spinners_Demo_05_Alignment_D_Palcement_Text_align.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Spinners/Spinners_Demo_05_Alignment_D_Palcement_Text_align.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Spinners/Spinners_Demo_05_Alignment_D_Palcement_Text_align.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Spinners/Spinners_Demo_06_Size_A_Border.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Spinners/Spinners_Demo_06_Size_A_Border.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Spinners/Spinners_Demo_06_Size_A_Border.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Spinners/Spinners_Demo_06_Size_A_Border.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Spinners/Spinners_Demo_06_Size_B_Grow.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Spinners/Spinners_Demo_06_Size_B_Grow.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Spinners/Spinners_Demo_06_Size_B_Grow.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Spinners/Spinners_Demo_06_Size_B_Grow.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Spinners/Spinners_Demo_06_Size_C_Dots.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Spinners/Spinners_Demo_06_Size_C_Dots.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Spinners/Spinners_Demo_06_Size_C_Dots.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Spinners/Spinners_Demo_06_Size_C_Dots.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Spinners/Spinners_Demo_07_Visible.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Spinners/Spinners_Demo_07_Visible.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Spinners/Spinners_Demo_07_Visible.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Spinners/Spinners_Demo_07_Visible.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/SplitView/SplitViewDocumentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/SplitView/SplitViewDocumentation.razor new file mode 100644 index 000000000..ee8e951e4 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/SplitView/SplitViewDocumentation.razor @@ -0,0 +1,104 @@ +@attribute [Route(pageUrl)] +@layout DemosMainLayout + + + + + +
    +
    + Pane1 and Pane2 are the required content regions for SplitView. +
    + +
    + +
    +
    + Set Orientation="SplitViewOrientation.Vertical" to stack panes top to bottom with a horizontal divider. +
    + +
    + +
    +
    + Use PrimaryPaneSize to set the initial percentage allocated to the primary pane. +
    + +
    + +
    +
    + Use @@bind-PrimaryPaneSize or PrimaryPaneSizeChanged to react to live divider movement. +
    + +
    + +
    +
    + MinimumPaneSize clamps both panes so one side cannot fully collapse while dragging. +
    + +
    + +
    +
    + Set IsDisabled="true" to keep the layout visible while preventing pointer-based resizing. +
    + +
    + +
    +
    + The Color parameter uses the SplitViewColor enum and maps to shared Bootstrap-backed CSS variables. +
    + +
    + +
    +
    + Use CustomColor when you want to pass a CSS color expression such as var(...) or rgba(...). +
    + +
    + +
    +
    + OnResizeStarted fires once when the pointer first captures the divider. +
    + +
    + +
    +
    + OnResized streams live primary and secondary pane percentages during drag. +
    + +
    + +
    +
    + OnResizeEnded is useful when you only want to persist the final pane sizes after dragging stops. +
    + +
    + +
    +
    + SplitView supports nested layouts for IDE-style, dashboard-style, and app-shell workspaces with navigation, content, and inspector panes. +
    + +
    + +@code { + private const string pageUrl = DemoRouteConstants.Demos_URL_SplitView; + private const string pageTitle = "Blazor Split View"; + private const string pageDescription = "The Blazor Split View component arranges two resizable panes horizontally or vertically with live drag updates, Bootstrap color theming, and focused parameter demos."; + private const string metaTitle = "Blazor Split View Component"; + private const string metaDescription = "The Blazor Split View component arranges two resizable panes horizontally or vertically with live drag updates, Bootstrap color theming, and focused parameter demos."; + private const string imageUrl = DemoScreenshotSrcConstants.Demos_URL_SplitView; +} \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/SplitView/SplitView_Demo_01_Pane_Content.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/SplitView/SplitView_Demo_01_Pane_Content.razor new file mode 100644 index 000000000..5be3fff26 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/SplitView/SplitView_Demo_01_Pane_Content.razor @@ -0,0 +1,22 @@ + + +
    +
    Pane1
    +
    Navigation
    +
    +
    Overview
    +
    Customers
    +
    Orders
    +
    Reports
    +
    +
    +
    + +
    +
    Pane2
    +

    Workspace

    +

    Use the two required pane templates to define the resizable primary and secondary regions.

    +
    +
    +
    \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/SplitView/SplitView_Demo_02_Orientation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/SplitView/SplitView_Demo_02_Orientation.razor new file mode 100644 index 000000000..504b646a7 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/SplitView/SplitView_Demo_02_Orientation.razor @@ -0,0 +1,48 @@ +
    Horizontal Orientation
    + + +
    +
    Left Pane
    +
    Navigation
    +

    The default horizontal orientation places panes side by side with a vertical divider.

    +
    +
    + +
    +
    Right Pane
    +
    Workspace
    +
      +
    • Dashboard widgets
    • +
    • Tables and forms
    • +
    • Contextual details
    • +
    +
    +
    +
    + +
    Vertical Orientation
    + + +
    +
    Top Pane
    +
    Summary
    +

    Vertical orientation stacks panes and changes the divider to horizontal dragging.

    +
    +
    + +
    +
    Bottom Pane
    +
    Details
    +
      +
    • Release notes
    • +
    • Deployment checklist
    • +
    • Preview output
    • +
    +
    +
    +
    \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/SplitView/SplitView_Demo_03_Primary_Pane_Size.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/SplitView/SplitView_Demo_03_Primary_Pane_Size.razor new file mode 100644 index 000000000..77ff83788 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/SplitView/SplitView_Demo_03_Primary_Pane_Size.razor @@ -0,0 +1,18 @@ + + +
    +
    Primary Pane
    +
    30%
    +

    Set PrimaryPaneSize when you want the initial layout to favor one pane.

    +
    +
    + +
    +
    Secondary Pane
    +
    70%
    +

    The remaining space is automatically assigned to the secondary pane.

    +
    +
    +
    \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/SplitView/SplitView_Demo_04_Primary_Pane_Size_Changed.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/SplitView/SplitView_Demo_04_Primary_Pane_Size_Changed.razor new file mode 100644 index 000000000..0a51510ff --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/SplitView/SplitView_Demo_04_Primary_Pane_Size_Changed.razor @@ -0,0 +1,30 @@ +
    + + + +
    Bound primary pane size: @primaryPaneSize.ToString("0.##")%
    +
    + + + +
    +
    Primary Pane
    +
    Two-way Binding
    +

    Drag the divider or use the buttons above to update the same bound value.

    +
    +
    + +
    +
    Secondary Pane
    +
    Live Value
    +

    The parent component stays synchronized through PrimaryPaneSizeChanged.

    +
    +
    +
    + +@code { + private double primaryPaneSize = 40; +} \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/SplitView/SplitView_Demo_05_Minimum_Pane_Size.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/SplitView/SplitView_Demo_05_Minimum_Pane_Size.razor new file mode 100644 index 000000000..b76b20c9a --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/SplitView/SplitView_Demo_05_Minimum_Pane_Size.razor @@ -0,0 +1,19 @@ + + +
    +
    MinimumPaneSize
    +
    25%
    +

    The divider cannot move past the 25% threshold, so the primary pane always remains usable.

    +
    +
    + +
    +
    Secondary Pane
    +
    Protected Layout
    +

    The same minimum is enforced from the opposite side, keeping both panes visible.

    +
    +
    +
    \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/SplitView/SplitView_Demo_06_Is_Disabled.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/SplitView/SplitView_Demo_06_Is_Disabled.razor new file mode 100644 index 000000000..02363f828 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/SplitView/SplitView_Demo_06_Is_Disabled.razor @@ -0,0 +1,20 @@ + + +
    +
    Disabled Divider
    +
    Pinned Pane
    +

    The layout remains visible, but pointer dragging and hover states are disabled.

    +
    +
    + +
    +
    Secondary Pane
    +
    Static Layout
    +

    Programmatic updates to PrimaryPaneSize still work even when interaction is disabled.

    +
    +
    +
    \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/SplitView/SplitView_Demo_07_Color.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/SplitView/SplitView_Demo_07_Color.razor new file mode 100644 index 000000000..b32416992 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/SplitView/SplitView_Demo_07_Color.razor @@ -0,0 +1,50 @@ +
    +
    + + +
    +
    Primary
    +
    Bootstrap semantic color
    +
    +
    + +
    Hover and dragging derive from the same base divider color.
    +
    +
    +
    +
    + + +
    +
    Success
    +
    Shared CSS variable mapping
    +
    +
    + +
    Use enum values when you want Bootstrap-aligned theming.
    +
    +
    +
    +
    + + +
    +
    Dark
    +
    Theme-aware shared CSS
    +
    +
    + +
    The divider color comes from the shared blazor.bootstrap.css token mapping.
    +
    +
    +
    +
    \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/SplitView/SplitView_Demo_08_Custom_Color.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/SplitView/SplitView_Demo_08_Custom_Color.razor new file mode 100644 index 000000000..bd377a07b --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/SplitView/SplitView_Demo_08_Custom_Color.razor @@ -0,0 +1,19 @@ + + +
    +
    CustomColor
    +
    CSS Expression Override
    +

    This example uses rgba(var(--bs-info-rgb), 0.85) instead of a semantic enum value.

    +
    +
    + +
    +
    Override Precedence
    +
    Inline Custom Value
    +

    When both are supplied, CustomColor overrides the shared default and semantic enum class.

    +
    +
    +
    \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/SplitView/SplitView_Demo_09_On_Resize_Started.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/SplitView/SplitView_Demo_09_On_Resize_Started.razor new file mode 100644 index 000000000..8debf5887 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/SplitView/SplitView_Demo_09_On_Resize_Started.razor @@ -0,0 +1,44 @@ +
    +
    + + +
    +
    OnResizeStarted
    +
    Drag To Start
    +

    Grab the divider to trigger the start event once per interaction.

    +
    +
    + +
    +
    Secondary Pane
    +
    Event Snapshot
    +

    The event args include both pane sizes as percentages.

    +
    +
    +
    +
    +
    +
    +
    Start Event
    +
    Count: @count
    +
    Primary pane: @primaryPaneSize.ToString("0.##")%
    +
    Secondary pane: @secondaryPaneSize.ToString("0.##")%
    +
    +
    +
    + +@code { + private int count; + private double primaryPaneSize = 38; + private double secondaryPaneSize = 62; + + private void HandleResizeStarted(SplitViewResizeEventArgs args) + { + count++; + primaryPaneSize = args.PrimaryPaneSize; + secondaryPaneSize = args.SecondaryPaneSize; + } +} \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/SplitView/SplitView_Demo_10_On_Resized.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/SplitView/SplitView_Demo_10_On_Resized.razor new file mode 100644 index 000000000..064c27b2c --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/SplitView/SplitView_Demo_10_On_Resized.razor @@ -0,0 +1,41 @@ +
    +
    + + +
    +
    OnResized
    +
    Live Resize Stream
    +

    Drag the divider and watch the event payload update continuously.

    +
    +
    + +
    +
    Live Metrics
    +
    Current Split
    +

    Primary pane: @primaryPaneSize.ToString("0.##")%

    +
    +
    +
    +
    +
    +
    +
    Resized Event
    +
    Primary pane: @primaryPaneSize.ToString("0.##")%
    +
    Secondary pane: @secondaryPaneSize.ToString("0.##")%
    +
    +
    +
    + +@code { + private double primaryPaneSize = 42; + private double secondaryPaneSize = 58; + + private void HandleResized(SplitViewResizeEventArgs args) + { + primaryPaneSize = args.PrimaryPaneSize; + secondaryPaneSize = args.SecondaryPaneSize; + } +} \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/SplitView/SplitView_Demo_11_On_Resize_Ended.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/SplitView/SplitView_Demo_11_On_Resize_Ended.razor new file mode 100644 index 000000000..ffab9c544 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/SplitView/SplitView_Demo_11_On_Resize_Ended.razor @@ -0,0 +1,41 @@ +
    +
    + + +
    +
    OnResizeEnded
    +
    Persist Final Size
    +

    This event fires once after dragging finishes, which is useful for saving layout preferences.

    +
    +
    + +
    +
    Secondary Pane
    +
    Release The Divider
    +

    Only the final percentages are recorded here.

    +
    +
    +
    +
    +
    +
    +
    Resize Ended
    +
    Primary pane: @primaryPaneSize.ToString("0.##")%
    +
    Secondary pane: @secondaryPaneSize.ToString("0.##")%
    +
    +
    +
    + +@code { + private double primaryPaneSize = 36; + private double secondaryPaneSize = 64; + + private void HandleResizeEnded(SplitViewResizeEventArgs args) + { + primaryPaneSize = args.PrimaryPaneSize; + secondaryPaneSize = args.SecondaryPaneSize; + } +} \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/SplitView/SplitView_Demo_12_Nested_Layouts.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/SplitView/SplitView_Demo_12_Nested_Layouts.razor new file mode 100644 index 000000000..9245a0c42 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/SplitView/SplitView_Demo_12_Nested_Layouts.razor @@ -0,0 +1,43 @@ + + +
    +
    Explorer
    +
    Files
    +
    +
    Pages
    +
    Components
    +
    Styles
    +
    Assets
    +
    +
    +
    + + + +
    +
    Editor
    +
    SplitView.razor
    +
    <SplitView @@bind-PrimaryPaneSize="paneSize">
    +    <Pane1>...</Pane1>
    +    <Pane2>...</Pane2>
    +</SplitView>
    +
    +
    + +
    +
    Preview
    +
    Live Preview
    +

    Nested SplitView layouts are useful for IDEs, dashboards, and administration portals.

    +
    +
    +
    +
    +
    \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Tabs/TabsDocumentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Tabs/TabsDocumentation.razor similarity index 75% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Tabs/TabsDocumentation.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Tabs/TabsDocumentation.razor index e1372d53d..61a061e0f 100644 --- a/BlazorBootstrap.Demo.RCL/Components/Pages/Tabs/TabsDocumentation.razor +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Tabs/TabsDocumentation.razor @@ -1,15 +1,14 @@ @attribute [Route(pageUrl)] +@layout DemosMainLayout - + - - @pageDescription - - - +
    @@ -69,28 +68,28 @@

    - - - - + + + + - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + +
    Event NameDescription
    Event NameDescription
    OnHidingThis event fires when a new tab is to be shown (and thus the previous active tab is to be hidden).
    OnHiddenThis event fires after a new tab is shown (and thus the previous active tab is hidden).
    OnShowingThis event fires on tab show, but before the new tab has been shown.
    OnShownThis event fires on tab show after a tab has been shown.
    OnHidingThis event fires when a new tab is to be shown (and thus the previous active tab is to be hidden).
    OnHiddenThis event fires after a new tab is shown (and thus the previous active tab is hidden).
    OnShowingThis event fires on tab show, but before the new tab has been shown.
    OnShownThis event fires on tab show after a tab has been shown.
    @@ -123,8 +122,15 @@
    +
    +
    + In the following example, we are removing the inactive tab by name. The focus will not be lost with this active tab. +
    + +
    + @code { - private const string pageUrl = RouteConstants.Demos_Tabs_Documentation; + private const string pageUrl = DemoRouteConstants.Demos_URL_Tabs; private const string pageTitle = "Blazor Tabs"; private const string pageDescription = "Documentation and examples for using Blazor Bootstrap Tabs components."; private const string metaTitle = "Blazor Tabs Component"; diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Tabs/Tabs_Demo_01_Examples.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Tabs/Tabs_Demo_01_Examples.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Tabs/Tabs_Demo_01_Examples.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Tabs/Tabs_Demo_01_Examples.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Tabs/Tabs_Demo_02_Enable_FadeEffect.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Tabs/Tabs_Demo_02_Enable_FadeEffect.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Tabs/Tabs_Demo_02_Enable_FadeEffect.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Tabs/Tabs_Demo_02_Enable_FadeEffect.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Tabs/Tabs_Demo_03_Title_with_Icon.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Tabs/Tabs_Demo_03_Title_with_Icon.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Tabs/Tabs_Demo_03_Title_with_Icon.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Tabs/Tabs_Demo_03_Title_with_Icon.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Tabs/Tabs_Demo_04_Disable_Tab.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Tabs/Tabs_Demo_04_Disable_Tab.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Tabs/Tabs_Demo_04_Disable_Tab.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Tabs/Tabs_Demo_04_Disable_Tab.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Tabs/Tabs_Demo_05_Nav_Style_Pills.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Tabs/Tabs_Demo_05_Nav_Style_Pills.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Tabs/Tabs_Demo_05_Nav_Style_Pills.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Tabs/Tabs_Demo_05_Nav_Style_Pills.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Tabs/Tabs_Demo_06_Nav_Style_Underline.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Tabs/Tabs_Demo_06_Nav_Style_Underline.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Tabs/Tabs_Demo_06_Nav_Style_Underline.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Tabs/Tabs_Demo_06_Nav_Style_Underline.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Tabs/Tabs_Demo_07_Vertical_A.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Tabs/Tabs_Demo_07_Vertical_A.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Tabs/Tabs_Demo_07_Vertical_A.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Tabs/Tabs_Demo_07_Vertical_A.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Tabs/Tabs_Demo_07_Vertical_B_Pills.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Tabs/Tabs_Demo_07_Vertical_B_Pills.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Tabs/Tabs_Demo_07_Vertical_B_Pills.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Tabs/Tabs_Demo_07_Vertical_B_Pills.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Tabs/Tabs_Demo_07_Vertical_C_Underline.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Tabs/Tabs_Demo_07_Vertical_C_Underline.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Tabs/Tabs_Demo_07_Vertical_C_Underline.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Tabs/Tabs_Demo_07_Vertical_C_Underline.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Tabs/Tabs_Demo_08_Activate_Individual_Tabs.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Tabs/Tabs_Demo_08_Activate_Individual_Tabs.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Tabs/Tabs_Demo_08_Activate_Individual_Tabs.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Tabs/Tabs_Demo_08_Activate_Individual_Tabs.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Tabs/Tabs_Demo_09_Events_Order.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Tabs/Tabs_Demo_09_Events_Order.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Tabs/Tabs_Demo_09_Events_Order.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Tabs/Tabs_Demo_09_Events_Order.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Tabs/Tabs_Demo_10_Events_Example.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Tabs/Tabs_Demo_10_Events_Example.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Tabs/Tabs_Demo_10_Events_Example.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Tabs/Tabs_Demo_10_Events_Example.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Tabs/Tabs_Demo_11_Methods_Set_Active_Tab_OnAfterRender.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Tabs/Tabs_Demo_11_Methods_Set_Active_Tab_OnAfterRender.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Tabs/Tabs_Demo_11_Methods_Set_Active_Tab_OnAfterRender.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Tabs/Tabs_Demo_11_Methods_Set_Active_Tab_OnAfterRender.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Tabs/Tabs_Demo_12_Tab_Callback_Event_OnClick.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Tabs/Tabs_Demo_12_Tab_Callback_Event_OnClick.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Tabs/Tabs_Demo_12_Tab_Callback_Event_OnClick.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Tabs/Tabs_Demo_12_Tab_Callback_Event_OnClick.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Tabs/Tabs_Demo_13_Dynamic_Tabs.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Tabs/Tabs_Demo_13_Dynamic_Tabs.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Tabs/Tabs_Demo_13_Dynamic_Tabs.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Tabs/Tabs_Demo_13_Dynamic_Tabs.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Tabs/Tabs_Demo_14_Remove_Dynamic_Tabs.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Tabs/Tabs_Demo_14_Remove_Dynamic_Tabs.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Tabs/Tabs_Demo_14_Remove_Dynamic_Tabs.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Tabs/Tabs_Demo_14_Remove_Dynamic_Tabs.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Tabs/Tabs_Demo_15_Remove_Inactive_Tab_by_Name.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Tabs/Tabs_Demo_15_Remove_Inactive_Tab_by_Name.razor new file mode 100644 index 000000000..e9fd91b4c --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Tabs/Tabs_Demo_15_Remove_Inactive_Tab_by_Name.razor @@ -0,0 +1,55 @@ +
    + + + + @foreach (var customer in customers) + { + + +
    +
    + This is the placeholder content for the @customer.CustomerName tab. +
    +
    +
    +
    + } +
    +
    +
    +
    +
    + +
    + +@code { + Tabs tabsRef = default!; + + int count = 1; + private List customers = default!; + + protected override void OnInitialized() + { + customers = new() { + new(1, "Marvin Klein"), + new(2, "Vikram Reddy"), + new(3, "Bandita PA"), + new(4, "Dan H"), + new(5, "Joe JJ"), + new(6, "Rose KK") + }; + count = customers.Count; + } + + private void RemoveCustomerVikram() + { + var customer = customers.FirstOrDefault(c => c.CustomerName == "Vikram Reddy"); + if (customer != null) + { + customers.Remove(customer); + tabsRef.RemoveTabByName(customer.CustomerId.ToString()); + } + } +} diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/ThemeSwitcher/ThemeSwitcherDocumentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/ThemeSwitcher/ThemeSwitcherDocumentation.razor similarity index 79% rename from BlazorBootstrap.Demo.RCL/Components/Pages/ThemeSwitcher/ThemeSwitcherDocumentation.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/ThemeSwitcher/ThemeSwitcherDocumentation.razor index f2d6128fb..fbce07295 100644 --- a/BlazorBootstrap.Demo.RCL/Components/Pages/ThemeSwitcher/ThemeSwitcherDocumentation.razor +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/ThemeSwitcher/ThemeSwitcherDocumentation.razor @@ -1,15 +1,14 @@ @attribute [Route(pageUrl)] +@layout DemosMainLayout - + - - @pageDescription - - - +
    @@ -38,7 +37,7 @@
    @code { - private const string pageUrl = RouteConstants.Demos_ThemeSwitcher_Documentation; + private const string pageUrl = DemoRouteConstants.Demos_URL_ThemeSwitcher; private const string pageTitle = "Blazor Theme Switcher"; private const string pageDescription = "Documentation and examples for using the Blazor Bootstrap Theme Switcher component."; private const string metaTitle = "Blazor Theme Switcher Component"; diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/ThemeSwitcher/ThemeSwitcher_Demo_01_How_It_Works.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/ThemeSwitcher/ThemeSwitcher_Demo_01_How_It_Works.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/ThemeSwitcher/ThemeSwitcher_Demo_01_How_It_Works.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/ThemeSwitcher/ThemeSwitcher_Demo_01_How_It_Works.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/ThemeSwitcher/ThemeSwitcher_Demo_02_Position_A.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/ThemeSwitcher/ThemeSwitcher_Demo_02_Position_A.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/ThemeSwitcher/ThemeSwitcher_Demo_02_Position_A.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/ThemeSwitcher/ThemeSwitcher_Demo_02_Position_A.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/ThemeSwitcher/ThemeSwitcher_Demo_02_Position_B.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/ThemeSwitcher/ThemeSwitcher_Demo_02_Position_B.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/ThemeSwitcher/ThemeSwitcher_Demo_02_Position_B.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/ThemeSwitcher/ThemeSwitcher_Demo_02_Position_B.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/ThemeSwitcher/ThemeSwitcher_Demo_03_Events.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/ThemeSwitcher/ThemeSwitcher_Demo_03_Events.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/ThemeSwitcher/ThemeSwitcher_Demo_03_Events.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/ThemeSwitcher/ThemeSwitcher_Demo_03_Events.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Toasts/ToastsDocumentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Toasts/ToastsDocumentation.razor similarity index 75% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Toasts/ToastsDocumentation.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Toasts/ToastsDocumentation.razor index 894921b87..1f7928a6d 100644 --- a/BlazorBootstrap.Demo.RCL/Components/Pages/Toasts/ToastsDocumentation.razor +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Toasts/ToastsDocumentation.razor @@ -1,15 +1,14 @@ @attribute [Route(pageUrl)] +@layout DemosMainLayout - + - - @pageDescription - - - +
    Blazor Toasts are lightweight notifications designed to mimic the push notifications that mobile and desktop operating systems have popularized. They're built with a flexbox, making it easy to align and position.
    @@ -28,6 +27,10 @@
    +
    + +
    +
    Add AutoHide="true" parameter to hide the Blazor Toasts after the delay. The default delay is 5000 milliseconds, be sure to update the delay timeout so that users have enough time to read the toast.
    @@ -45,8 +48,8 @@
    -
    Blazor Toasts component shows a maximum of 5 toasts by default. If you add a new toast to the existing list, the first toast gets deleted like FIFO (First In First Out). Change the maximum capacity according to your need by using the StackLength parameter.
    -
    In the below example, StackLength is set to 3. It shows a maximum of 3 toast messages at any time.
    +
    Blazor Toasts component shows a maximum of 5 toasts by default. If you add a new toast to the existing list, the oldest rendered toast is dismissed first in FIFO (First In First Out) order. Change the maximum capacity according to your need by using the StackLength parameter.
    +
    In the below example, StackLength is set to 3. It shows a maximum of 3 toast messages at any time, and older visible toasts finish their hide transition before they are removed from the stack.
    @@ -58,10 +61,13 @@
    2. Inject ToastService, then call the Notify(...) method as shown below.
    + + Use Notify(...) for the common single Toasts host scenario. Use await NotifyAsync(...) when multiple toast subscribers are registered and the caller needs to await all handlers. +
    @code { - private const string pageUrl = RouteConstants.Demos_Toasts_Documentation; + private const string pageUrl = DemoRouteConstants.Demos_URL_Toasts; private const string pageTitle = "Blazor Toasts"; private const string pageDescription = "Push notifications to your visitors with a toast, a lightweight and easily customizable Blazor Bootstrap alert message."; private const string metaTitle = "Blazor Toasts Component"; diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Toasts/Toasts_Demo_01_Toast_With_Title.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Toasts/Toasts_Demo_01_Toast_With_Title.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Toasts/Toasts_Demo_01_Toast_With_Title.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Toasts/Toasts_Demo_01_Toast_With_Title.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Toasts/Toasts_Demo_02_Toast_Without_Title.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Toasts/Toasts_Demo_02_Toast_Without_Title.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Toasts/Toasts_Demo_02_Toast_Without_Title.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Toasts/Toasts_Demo_02_Toast_Without_Title.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Toasts/Toasts_Demo_03_A_Auto_Hide.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Toasts/Toasts_Demo_03_A_Auto_Hide.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Toasts/Toasts_Demo_03_A_Auto_Hide.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Toasts/Toasts_Demo_03_A_Auto_Hide.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Toasts/Toasts_Demo_03_B_Auto_Hide_Individual_Messages.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Toasts/Toasts_Demo_03_B_Auto_Hide_Individual_Messages.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Toasts/Toasts_Demo_03_B_Auto_Hide_Individual_Messages.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Toasts/Toasts_Demo_03_B_Auto_Hide_Individual_Messages.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Toasts/Toasts_Demo_04_Placement.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Toasts/Toasts_Demo_04_Placement.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Toasts/Toasts_Demo_04_Placement.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Toasts/Toasts_Demo_04_Placement.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Toasts/Toasts_Demo_05_StackLength.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Toasts/Toasts_Demo_05_StackLength.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Toasts/Toasts_Demo_05_StackLength.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Toasts/Toasts_Demo_05_StackLength.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Toasts/Toasts_Demo_06_Global_Toasts_Service_For_Application_01.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Toasts/Toasts_Demo_06_Global_Toasts_Service_For_Application_01.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Toasts/Toasts_Demo_06_Global_Toasts_Service_For_Application_01.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Toasts/Toasts_Demo_06_Global_Toasts_Service_For_Application_01.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Toasts/Toasts_Demo_06_Global_Toasts_Service_For_Application_02.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Toasts/Toasts_Demo_06_Global_Toasts_Service_For_Application_02.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Toasts/Toasts_Demo_06_Global_Toasts_Service_For_Application_02.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Toasts/Toasts_Demo_06_Global_Toasts_Service_For_Application_02.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Toasts/Toasts_Demo_07_Toast_With_Content.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Toasts/Toasts_Demo_07_Toast_With_Content.razor new file mode 100644 index 000000000..5e0c3e1e4 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Toasts/Toasts_Demo_07_Toast_With_Content.razor @@ -0,0 +1,16 @@ + + + + +@code { + List messages = []; + + private void ShowToast() => + messages.Add( + new ToastMessage + { + Type = ToastType.Info, + Title = "Blazor Bootstrap", + Content = @
    Hello, world! This is a toast message.
    , + }); +} diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Tooltips/TooltipsDocumentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Tooltips/TooltipsDocumentation.razor similarity index 85% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Tooltips/TooltipsDocumentation.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Tooltips/TooltipsDocumentation.razor index 107f85a21..9e3f30577 100644 --- a/BlazorBootstrap.Demo.RCL/Components/Pages/Tooltips/TooltipsDocumentation.razor +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Tooltips/TooltipsDocumentation.razor @@ -1,15 +1,14 @@ @attribute [Route(pageUrl)] +@layout DemosMainLayout - + - - @pageDescription - - - +
    @@ -55,7 +54,7 @@
    @code { - private const string pageUrl = RouteConstants.Demos_Tooltips_Documentation; + private const string pageUrl = DemoRouteConstants.Demos_URL_Tooltips; private const string pageTitle = "Blazor Tooltip"; private const string pageDescription = "Use Blazor Bootstrap tooltip component to add custom tooltips to your web pages."; private const string metaTitle = "Blazor Tooltip Component"; diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Tooltips/Tooltips_Demo_01_Examples.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Tooltips/Tooltips_Demo_01_Examples.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Tooltips/Tooltips_Demo_01_Examples.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Tooltips/Tooltips_Demo_01_Examples.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Tooltips/Tooltips_Demo_02_Disabled_Button_With_Tooltip.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Tooltips/Tooltips_Demo_02_Disabled_Button_With_Tooltip.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Tooltips/Tooltips_Demo_02_Disabled_Button_With_Tooltip.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Tooltips/Tooltips_Demo_02_Disabled_Button_With_Tooltip.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Tooltips/Tooltips_Demo_03_Icon_With_Click_Event.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Tooltips/Tooltips_Demo_03_Icon_With_Click_Event.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Tooltips/Tooltips_Demo_03_Icon_With_Click_Event.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Tooltips/Tooltips_Demo_03_Icon_With_Click_Event.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Tooltips/Tooltips_Demo_04_Dynamically_Update_Tooltip_Text.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Tooltips/Tooltips_Demo_04_Dynamically_Update_Tooltip_Text.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Tooltips/Tooltips_Demo_04_Dynamically_Update_Tooltip_Text.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Tooltips/Tooltips_Demo_04_Dynamically_Update_Tooltip_Text.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Tooltips/Tooltips_Demo_05_Tooltip_With_Navigation_Link.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Tooltips/Tooltips_Demo_05_Tooltip_With_Navigation_Link.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Tooltips/Tooltips_Demo_05_Tooltip_With_Navigation_Link.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Tooltips/Tooltips_Demo_05_Tooltip_With_Navigation_Link.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Tooltips/Tooltips_Demo_06_Colors.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Tooltips/Tooltips_Demo_06_Colors.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Tooltips/Tooltips_Demo_06_Colors.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Tooltips/Tooltips_Demo_06_Colors.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Tooltips/Tooltips_Demo_07_Dynamically_Change_Color.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Tooltips/Tooltips_Demo_07_Dynamically_Change_Color.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Tooltips/Tooltips_Demo_07_Dynamically_Change_Color.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Tooltips/Tooltips_Demo_07_Dynamically_Change_Color.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Tooltips/Tooltips_Demo_08_HTML.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Tooltips/Tooltips_Demo_08_HTML.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Tooltips/Tooltips_Demo_08_HTML.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Tooltips/Tooltips_Demo_08_HTML.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Utils/ColorUtil/ColorUtilDocumentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Utils/ColorUtil/ColorUtilDocumentation.razor similarity index 76% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Utils/ColorUtil/ColorUtilDocumentation.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Utils/ColorUtil/ColorUtilDocumentation.razor index 4863b7427..117dcf386 100644 --- a/BlazorBootstrap.Demo.RCL/Components/Pages/Utils/ColorUtil/ColorUtilDocumentation.razor +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Utils/ColorUtil/ColorUtilDocumentation.razor @@ -1,15 +1,14 @@ @attribute [Route(pageUrl)] +@layout DemosMainLayout - + - - @pageDescription - - - +@* *@
    @@ -24,7 +23,7 @@
    @code { - private const string pageUrl = RouteConstants.Demos_ColorUtils_Documentation; + private const string pageUrl = DemoRouteConstants.Demos_URL_ColorUtils; private const string pageTitle = "Blazor Bootstrap Color Utils"; private const string pageDescription = "For data visualization, you can use the predefined palettes ColorBuilder.CategoricalTwelveColors for a 12-color palette and ColorBuilder.CategoricalSixColors for a 6-color palette. These palettes offer a range of distinct and visually appealing colors that can be applied to represent different categories or data elements in your visualizations."; private const string metaTitle = "Blazor Bootstrap Color Utils"; diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Utils/ColorUtil/ColorUtil_Demo_01_CategoricalSixColor.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Utils/ColorUtil/ColorUtil_Demo_01_CategoricalSixColor.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Utils/ColorUtil/ColorUtil_Demo_01_CategoricalSixColor.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Utils/ColorUtil/ColorUtil_Demo_01_CategoricalSixColor.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Utils/ColorUtil/ColorUtil_Demo_02_CategoricalTwelveColor.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Utils/ColorUtil/ColorUtil_Demo_02_CategoricalTwelveColor.razor similarity index 100% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Utils/ColorUtil/ColorUtil_Demo_02_CategoricalTwelveColor.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Demos/Utils/ColorUtil/ColorUtil_Demo_02_CategoricalTwelveColor.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Accordion/Accordion_Doc_01_Documentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Accordion/Accordion_Doc_01_Documentation.razor new file mode 100644 index 000000000..e8633014b --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Accordion/Accordion_Doc_01_Documentation.razor @@ -0,0 +1,45 @@ +@attribute [Route(pageUrl)] +@layout DocsMainLayout + + + + + +
    + @metaTitle +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    + +@code { + private const string componentName = nameof(Accordion); + private const string pageUrl = DemoRouteConstants.Docs_URL_Accordion; + private const string pageTitle = componentName; + private const string pageDescription = $"This documentation provides a comprehensive reference for the {componentName} component, guiding you through its configuration options."; + private const string metaTitle = $"Blazor {componentName} Component"; + private const string metaDescription = $"This documentation provides a comprehensive reference for the {componentName} component, guiding you through its configuration options."; + private const string imageUrl = DemoScreenshotSrcConstants.Demos_URL_Accordion; +} \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Alerts/Alert_Doc_01_Documentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Alerts/Alert_Doc_01_Documentation.razor new file mode 100644 index 000000000..83feb27d9 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Alerts/Alert_Doc_01_Documentation.razor @@ -0,0 +1,41 @@ +@attribute [Route(pageUrl)] +@layout DocsMainLayout + + + + + +
    + @metaTitle +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    + +@code { + private const string componentName = nameof(Alert); + private const string pageUrl = DemoRouteConstants.Docs_URL_Alerts; + private const string pageTitle = componentName; + private const string pageDescription = $"This documentation provides a comprehensive reference for the {componentName} component, guiding you through its configuration options."; + private const string metaTitle = $"Blazor {componentName} Component"; + private const string metaDescription = $"This documentation provides a comprehensive reference for the {componentName} component, guiding you through its configuration options."; + private const string imageUrl = DemoScreenshotSrcConstants.Demos_URL_Alerts; +} \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Badge/Badge_Doc_01_Documentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Badge/Badge_Doc_01_Documentation.razor new file mode 100644 index 000000000..6dc1f042c --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Badge/Badge_Doc_01_Documentation.razor @@ -0,0 +1,45 @@ +@attribute [Route(pageUrl)] +@layout DocsMainLayout + + + + + +
    + @metaTitle +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    + +@code { + private const string componentName = nameof(Badge); + private const string pageUrl = DemoRouteConstants.Docs_URL_Badge; + private const string pageTitle = componentName; + private const string pageDescription = $"This documentation provides a comprehensive reference for the {componentName} component, guiding you through its configuration options."; + private const string metaTitle = $"Blazor {componentName} Component"; + private const string metaDescription = $"This documentation provides a comprehensive reference for the {componentName} component, guiding you through its configuration options."; + private const string imageUrl = DemoScreenshotSrcConstants.Demos_URL_Badge; +} \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Breadcrumb/Breadcrumb_Doc_01_Documentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Breadcrumb/Breadcrumb_Doc_01_Documentation.razor new file mode 100644 index 000000000..f4f86b848 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Breadcrumb/Breadcrumb_Doc_01_Documentation.razor @@ -0,0 +1,37 @@ +@attribute [Route(pageUrl)] +@layout DocsMainLayout + + + + + +
    + @metaTitle +
    + +
    + +
    + +
    + +
    + +
    + +
    + +@code { + private const string componentName = nameof(Breadcrumb); + private const string pageUrl = DemoRouteConstants.Docs_URL_Breadcrumb; + private const string pageTitle = componentName; + private const string pageDescription = $"This documentation provides a comprehensive reference for the {componentName} component, guiding you through its configuration options."; + private const string metaTitle = $"Blazor {componentName} Component"; + private const string metaDescription = $"This documentation provides a comprehensive reference for the {componentName} component, guiding you through its configuration options."; + private const string imageUrl = DemoScreenshotSrcConstants.Demos_URL_Breadcrumb; +} \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Buttons/Buttons_Doc_01_Documentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Buttons/Buttons_Doc_01_Documentation.razor new file mode 100644 index 000000000..b7ca6cd92 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Buttons/Buttons_Doc_01_Documentation.razor @@ -0,0 +1,61 @@ +@attribute [Route(pageUrl)] +@layout DocsMainLayout + + + + + +
    + @metaTitle +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    + +@code { + private const string componentName = nameof(Button); + private const string pageUrl = DemoRouteConstants.Docs_URL_Buttons; + private const string pageTitle = componentName; + private const string pageDescription = $"This documentation provides a comprehensive reference for the {componentName} component, guiding you through its configuration options."; + private const string metaTitle = $"Blazor {componentName} Component"; + private const string metaDescription = $"This documentation provides a comprehensive reference for the {componentName} component, guiding you through its configuration options."; + private const string imageUrl = DemoScreenshotSrcConstants.Demos_URL_Buttons; +} \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Callout/Callout_Doc_01_Documentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Callout/Callout_Doc_01_Documentation.razor new file mode 100644 index 000000000..7f164a992 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Callout/Callout_Doc_01_Documentation.razor @@ -0,0 +1,33 @@ +@attribute [Route(pageUrl)] +@layout DocsMainLayout + + + + + +
    + @metaTitle +
    + +
    + +
    + +
    + +
    + +@code { + private const string componentName = nameof(Callout); + private const string pageUrl = DemoRouteConstants.Docs_URL_Callout; + private const string pageTitle = componentName; + private const string pageDescription = $"This documentation provides a comprehensive reference for the {componentName} component, guiding you through its configuration options."; + private const string metaTitle = $"Blazor {componentName} Component"; + private const string metaDescription = $"This documentation provides a comprehensive reference for the {componentName} component, guiding you through its configuration options."; + private const string imageUrl = DemoScreenshotSrcConstants.Demos_URL_Callout; +} \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Card/Card_Doc_01_Documentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Card/Card_Doc_01_Documentation.razor new file mode 100644 index 000000000..aa87cd457 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Card/Card_Doc_01_Documentation.razor @@ -0,0 +1,77 @@ +@attribute [Route(pageUrl)] +@layout DocsMainLayout + + + + + +
    + @metaTitle +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    + +@code { + private const string componentName = nameof(Card); + private const string pageUrl = DemoRouteConstants.Docs_URL_Card; + private const string pageTitle = componentName; + private const string pageDescription = $"This documentation provides a comprehensive reference for the {componentName} component, guiding you through its configuration options."; + private const string metaTitle = $"Blazor {componentName} Component"; + private const string metaDescription = $"This documentation provides a comprehensive reference for the {componentName} component, guiding you through its configuration options."; + private const string imageUrl = DemoScreenshotSrcConstants.Demos_URL_Card; +} \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Carousel/Carousel_Doc_01_Documentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Carousel/Carousel_Doc_01_Documentation.razor new file mode 100644 index 000000000..8430cc6c4 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Carousel/Carousel_Doc_01_Documentation.razor @@ -0,0 +1,41 @@ +@attribute [Route(pageUrl)] +@layout DocsMainLayout + + + + + +
    + @metaTitle +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    + +@code { + private const string componentName = nameof(Carousel); + private const string pageUrl = DemoRouteConstants.Docs_URL_Carousel; + private const string pageTitle = componentName; + private const string pageDescription = $"This documentation provides a comprehensive reference for the {componentName} component, guiding you through its configuration options."; + private const string metaTitle = $"Blazor {componentName} Component"; + private const string metaDescription = $"This documentation provides a comprehensive reference for the {componentName} component, guiding you through its configuration options."; + private const string imageUrl = DemoScreenshotSrcConstants.Demos_URL_Carousel; +} \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Collapse/Collapse_Doc_01_Documentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Collapse/Collapse_Doc_01_Documentation.razor new file mode 100644 index 000000000..7ed339eae --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Collapse/Collapse_Doc_01_Documentation.razor @@ -0,0 +1,37 @@ +@attribute [Route(pageUrl)] +@layout DocsMainLayout + + + + + +
    + @metaTitle +
    + +
    + +
    + +
    + +
    + +
    + +
    + +@code { + private const string componentName = nameof(Collapse); + private const string pageUrl = DemoRouteConstants.Docs_URL_Collapse; + private const string pageTitle = componentName; + private const string pageDescription = $"This documentation provides a comprehensive reference for the {componentName} component, guiding you through its configuration options."; + private const string metaTitle = $"Blazor {componentName} Component"; + private const string metaDescription = $"This documentation provides a comprehensive reference for the {componentName} component, guiding you through its configuration options."; + private const string imageUrl = DemoScreenshotSrcConstants.Demos_URL_Collapse; +} \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/ConfirmDialog/ConfirmDialog_Doc_01_Documentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/ConfirmDialog/ConfirmDialog_Doc_01_Documentation.razor new file mode 100644 index 000000000..367d3843c --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/ConfirmDialog/ConfirmDialog_Doc_01_Documentation.razor @@ -0,0 +1,37 @@ +@attribute [Route(pageUrl)] +@layout DocsMainLayout + + + + + +
    + @metaTitle +
    + +
    + +
    + +
    + +
    + +
    + +
    + +@code { + private const string componentName = nameof(ConfirmDialog); + private const string pageUrl = DemoRouteConstants.Docs_URL_ConfirmDialog; + private const string pageTitle = componentName; + private const string pageDescription = $"This documentation provides a comprehensive reference for the {componentName} component, guiding you through its configuration options."; + private const string metaTitle = $"Blazor {componentName} Component"; + private const string metaDescription = $"This documentation provides a comprehensive reference for the {componentName} component, guiding you through its configuration options."; + private const string imageUrl = DemoScreenshotSrcConstants.Demos_URL_ConfirmDialog; +} \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Dropdowns/Dropdown_Doc_01_Documentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Dropdowns/Dropdown_Doc_01_Documentation.razor new file mode 100644 index 000000000..53c216a7a --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Dropdowns/Dropdown_Doc_01_Documentation.razor @@ -0,0 +1,57 @@ +@attribute [Route(pageUrl)] +@layout DocsMainLayout + + + + + +
    + @metaTitle +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    + +@code { + private const string componentName = nameof(Dropdown); + private const string pageUrl = DemoRouteConstants.Docs_URL_Dropdown; + private const string pageTitle = componentName; + private const string pageDescription = $"This documentation provides a comprehensive reference for the {componentName} component, guiding you through its configuration options."; + private const string metaTitle = $"Blazor {componentName} Component"; + private const string metaDescription = $"This documentation provides a comprehensive reference for the {componentName} component, guiding you through its configuration options."; + private const string imageUrl = DemoScreenshotSrcConstants.Demos_URL_Dropdown; +} \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Form/AutoComplete/AutoComplete_Doc_01_Documentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Form/AutoComplete/AutoComplete_Doc_01_Documentation.razor new file mode 100644 index 000000000..4f86a9316 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Form/AutoComplete/AutoComplete_Doc_01_Documentation.razor @@ -0,0 +1,37 @@ +@attribute [Route(pageUrl)] +@layout DocsMainLayout + + + + + +
    + @metaTitle +
    + +
    + +
    + +
    + +
    + +
    + +
    + +@code { + private const string componentName = nameof(AutoComplete); + private const string pageUrl = DemoRouteConstants.Docs_URL_AutoComplete; + private const string pageTitle = componentName; + private const string pageDescription = $"This documentation provides a comprehensive reference for the {componentName} component, guiding you through its configuration options."; + private const string metaTitle = $"Blazor {componentName} Component"; + private const string metaDescription = $"This documentation provides a comprehensive reference for the {componentName} component, guiding you through its configuration options."; + private const string imageUrl = DemoScreenshotSrcConstants.Demos_URL_AutoComplete; +} \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Form/CheckboxInput/CheckboxInput_Doc_01_Documentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Form/CheckboxInput/CheckboxInput_Doc_01_Documentation.razor new file mode 100644 index 000000000..e6e9eaa62 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Form/CheckboxInput/CheckboxInput_Doc_01_Documentation.razor @@ -0,0 +1,37 @@ +@attribute [Route(pageUrl)] +@layout DocsMainLayout + + + + + +
    + @metaTitle +
    + +
    + +
    + +
    + +
    + +
    + +
    + +@code { + private const string componentName = nameof(CheckboxInput); + private const string pageUrl = DemoRouteConstants.Docs_URL_CheckboxInput; + private const string pageTitle = componentName; + private const string pageDescription = $"This documentation provides a comprehensive reference for the {componentName} component, guiding you through its configuration options."; + private const string metaTitle = $"Blazor {componentName} Component"; + private const string metaDescription = $"This documentation provides a comprehensive reference for the {componentName} component, guiding you through its configuration options."; + private const string imageUrl = DemoScreenshotSrcConstants.Demos_URL_CheckboxInput; +} \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Form/CurrencyInput/CurrencyInput_Doc_01_Documentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Form/CurrencyInput/CurrencyInput_Doc_01_Documentation.razor new file mode 100644 index 000000000..35004c913 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Form/CurrencyInput/CurrencyInput_Doc_01_Documentation.razor @@ -0,0 +1,37 @@ +@attribute [Route(pageUrl)] +@layout DocsMainLayout + + + + + +
    + @metaTitle +
    + +
    + +
    + +
    + +
    + +
    + +
    + +@code { + private const string componentName = nameof(CurrencyInput); + private const string pageUrl = DemoRouteConstants.Docs_URL_CurrencyInput; + private const string pageTitle = componentName; + private const string pageDescription = $"This documentation provides a comprehensive reference for the {componentName} component, guiding you through its configuration options."; + private const string metaTitle = $"Blazor {componentName} Component"; + private const string metaDescription = $"This documentation provides a comprehensive reference for the {componentName} component, guiding you through its configuration options."; + private const string imageUrl = DemoScreenshotSrcConstants.Demos_URL_CurrencyInput; +} \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Form/DateInput/DateInput_Doc_01_Documentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Form/DateInput/DateInput_Doc_01_Documentation.razor new file mode 100644 index 000000000..77a056e14 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Form/DateInput/DateInput_Doc_01_Documentation.razor @@ -0,0 +1,37 @@ +@attribute [Route(pageUrl)] +@layout DocsMainLayout + + + + + +
    + @metaTitle +
    + +
    + +
    + +
    + +
    + +
    + +
    + +@code { + private const string componentName = nameof(DateInput); + private const string pageUrl = DemoRouteConstants.Docs_URL_DateInput; + private const string pageTitle = componentName; + private const string pageDescription = $"This documentation provides a comprehensive reference for the {componentName} component, guiding you through its configuration options."; + private const string metaTitle = $"Blazor {componentName} Component"; + private const string metaDescription = $"This documentation provides a comprehensive reference for the {componentName} component, guiding you through its configuration options."; + private const string imageUrl = DemoScreenshotSrcConstants.Demos_URL_DateInput; +} \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Form/DragAndDropFileInput/DragAndDropFileInput_Doc_01_Documentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Form/DragAndDropFileInput/DragAndDropFileInput_Doc_01_Documentation.razor new file mode 100644 index 000000000..0a6a85ca7 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Form/DragAndDropFileInput/DragAndDropFileInput_Doc_01_Documentation.razor @@ -0,0 +1,29 @@ +@attribute [Route(pageUrl)] +@layout DocsMainLayout + + + + + +
    + +
    + +
    + +
    + +@code { + private const string componentName = nameof(DragAndDropFileInput); + private const string pageUrl = DemoRouteConstants.Docs_URL_DragAndDropFileInput; + private const string pageTitle = componentName; + private const string pageDescription = $"This documentation provides a comprehensive reference for the {componentName} component, guiding you through its configuration options."; + private const string metaTitle = $"Blazor {componentName} Component"; + private const string metaDescription = $"This documentation provides a comprehensive reference for the {componentName} component, guiding you through its configuration options."; + private const string imageUrl = DemoScreenshotSrcConstants.Demos_URL_DragAndDropFileInput; +} diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Form/EnumInput/EnumInput_Doc_01_Documentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Form/EnumInput/EnumInput_Doc_01_Documentation.razor new file mode 100644 index 000000000..c665daee2 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Form/EnumInput/EnumInput_Doc_01_Documentation.razor @@ -0,0 +1,39 @@ +@attribute [Route(pageUrl)] +@layout DocsMainLayout + + + + + +
    + @metaTitle +
    + +
    + +
    + +
    + +
    + +
    + +
    + +@code { + private const string componentName = nameof(EnumInput); + private const string pageUrl = DemoRouteConstants.Docs_URL_EnumInput; + private const string pageTitle = componentName; + private const string pageDescription = $"This documentation provides a comprehensive reference for the {componentName} component, guiding you through its configuration options."; + private const string metaTitle = $"Blazor {componentName} Component"; + private const string metaDescription = $"This documentation provides a comprehensive reference for the {componentName} component, guiding you through its configuration options."; + private const string imageUrl = DemoScreenshotSrcConstants.Demos_URL_DateInput; + + public enum TEnum {} +} \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Form/FileInput/FileInput_Doc_01_Documentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Form/FileInput/FileInput_Doc_01_Documentation.razor new file mode 100644 index 000000000..e98cca97f --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Form/FileInput/FileInput_Doc_01_Documentation.razor @@ -0,0 +1,29 @@ +@attribute [Route(pageUrl)] +@layout DocsMainLayout + + + + + +
    + +
    + +
    + +
    + +@code { + private const string componentName = nameof(FileInput); + private const string pageUrl = DemoRouteConstants.Docs_URL_FileInput; + private const string pageTitle = componentName; + private const string pageDescription = $"This documentation provides a comprehensive reference for the {componentName} component, guiding you through its configuration options."; + private const string metaTitle = $"Blazor {componentName} Component"; + private const string metaDescription = $"This documentation provides a comprehensive reference for the {componentName} component, guiding you through its configuration options."; + private const string imageUrl = DemoScreenshotSrcConstants.Demos_URL_FileInput; +} diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Form/NumberInput/NumberInput_Doc_01_Documentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Form/NumberInput/NumberInput_Doc_01_Documentation.razor new file mode 100644 index 000000000..2f59171a7 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Form/NumberInput/NumberInput_Doc_01_Documentation.razor @@ -0,0 +1,37 @@ +@attribute [Route(pageUrl)] +@layout DocsMainLayout + + + + + +
    + @metaTitle +
    + +
    + +
    + +
    + +
    + +
    + +
    + +@code { + private const string componentName = nameof(NumberInput); + private const string pageUrl = DemoRouteConstants.Docs_URL_NumberInput; + private const string pageTitle = componentName; + private const string pageDescription = $"This documentation provides a comprehensive reference for the {componentName} component, guiding you through its configuration options."; + private const string metaTitle = $"Blazor {componentName} Component"; + private const string metaDescription = $"This documentation provides a comprehensive reference for the {componentName} component, guiding you through its configuration options."; + private const string imageUrl = DemoScreenshotSrcConstants.Demos_URL_NumberInput; +} \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Form/OTPInput/OTPInput_Doc_01_Documentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Form/OTPInput/OTPInput_Doc_01_Documentation.razor new file mode 100644 index 000000000..277421558 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Form/OTPInput/OTPInput_Doc_01_Documentation.razor @@ -0,0 +1,37 @@ +@attribute [Route(pageUrl)] +@layout DocsMainLayout + + + + + +
    + @metaTitle +
    + +
    + +
    + +
    + +
    + +
    + +
    + +@code { + private const string componentName = nameof(OTPInput); + private const string pageUrl = DemoRouteConstants.Docs_URL_OTPInput; + private const string pageTitle = componentName; + private const string pageDescription = $"This documentation provides a comprehensive reference for the {componentName} component, guiding you through its configuration options."; + private const string metaTitle = $"Blazor {componentName} Component"; + private const string metaDescription = $"This documentation provides a comprehensive reference for the {componentName} component, guiding you through its configuration options."; + private const string imageUrl = DemoScreenshotSrcConstants.Demos_URL_OTPInput; +} \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Form/PasswordInput/PasswordInput_Doc_01_Documentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Form/PasswordInput/PasswordInput_Doc_01_Documentation.razor new file mode 100644 index 000000000..eb3802530 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Form/PasswordInput/PasswordInput_Doc_01_Documentation.razor @@ -0,0 +1,37 @@ +@attribute [Route(pageUrl)] +@layout DocsMainLayout + + + + + +
    + @metaTitle +
    + +
    + +
    + +
    + +
    + +
    + +
    + +@code { + private const string componentName = nameof(PasswordInput); + private const string pageUrl = DemoRouteConstants.Docs_URL_PasswordInput; + private const string pageTitle = componentName; + private const string pageDescription = $"This documentation provides a comprehensive reference for the {componentName} component, guiding you through its configuration options."; + private const string metaTitle = $"Blazor {componentName} Component"; + private const string metaDescription = $"This documentation provides a comprehensive reference for the {componentName} component, guiding you through its configuration options."; + private const string imageUrl = DemoScreenshotSrcConstants.Demos_URL_PasswordInput; +} \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Form/RadioInput/RadioInput_Doc_01_Documentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Form/RadioInput/RadioInput_Doc_01_Documentation.razor new file mode 100644 index 000000000..8d97a43d9 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Form/RadioInput/RadioInput_Doc_01_Documentation.razor @@ -0,0 +1,37 @@ +@attribute [Route(pageUrl)] +@layout DocsMainLayout + + + + + +
    + @metaTitle +
    + +
    + +
    + +
    + +
    + +
    + +
    + +@code { + private const string componentName = nameof(RadioInput); + private const string pageUrl = DemoRouteConstants.Docs_URL_RadioInput; + private const string pageTitle = componentName; + private const string pageDescription = $"This documentation provides a comprehensive reference for the {componentName} component, guiding you through its configuration options."; + private const string metaTitle = $"Blazor {componentName} Component"; + private const string metaDescription = $"This documentation provides a comprehensive reference for the {componentName} component, guiding you through its configuration options."; + private const string imageUrl = DemoScreenshotSrcConstants.Demos_URL_RadioInput; +} \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Form/RangeInput/RangeInput_Doc_01_Documentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Form/RangeInput/RangeInput_Doc_01_Documentation.razor new file mode 100644 index 000000000..4ee33bc1e --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Form/RangeInput/RangeInput_Doc_01_Documentation.razor @@ -0,0 +1,37 @@ +@attribute [Route(pageUrl)] +@layout DocsMainLayout + + + + + +
    + @metaTitle +
    + +
    + +
    + +
    + +
    + +
    + +
    + +@code { + private const string componentName = nameof(RangeInput); + private const string pageUrl = DemoRouteConstants.Docs_URL_RangeInput; + private const string pageTitle = componentName; + private const string pageDescription = $"This documentation provides a comprehensive reference for the {componentName} component, guiding you through its configuration options."; + private const string metaTitle = $"Blazor {componentName} Component"; + private const string metaDescription = $"This documentation provides a comprehensive reference for the {componentName} component, guiding you through its configuration options."; + private const string imageUrl = DemoScreenshotSrcConstants.Demos_URL_RangeInput; +} \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Form/RichTextEditor/RichTextEditor_Doc_01_Documentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Form/RichTextEditor/RichTextEditor_Doc_01_Documentation.razor new file mode 100644 index 000000000..04d47ff1c --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Form/RichTextEditor/RichTextEditor_Doc_01_Documentation.razor @@ -0,0 +1,31 @@ +@attribute [Route(DemoRouteConstants.Docs_URL_RichTextEditor)] +@layout DocsMainLayout + + + + + +
    + +
    + +
    + +
    + +
    + +
    + +@code { + private const string componentName = nameof(RichTextEditor); + private const string pageDescription = $"This documentation provides a comprehensive reference for the {componentName} component, guiding you through its configuration options."; + private const string metaTitle = $"Blazor {componentName} Component"; + private const string metaDescription = $"This documentation provides a comprehensive reference for the {componentName} component, guiding you through its configuration options."; + private const string imageUrl = DemoScreenshotSrcConstants.Demos_URL_RichTextEditor; +} diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Form/Switch/Switch_Doc_01_Documentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Form/Switch/Switch_Doc_01_Documentation.razor new file mode 100644 index 000000000..774ae1da7 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Form/Switch/Switch_Doc_01_Documentation.razor @@ -0,0 +1,37 @@ +@attribute [Route(pageUrl)] +@layout DocsMainLayout + + + + + +
    + @metaTitle +
    + +
    + +
    + +
    + +
    + +
    + +
    + +@code { + private const string componentName = nameof(Switch); + private const string pageUrl = DemoRouteConstants.Docs_URL_Switch; + private const string pageTitle = componentName; + private const string pageDescription = $"This documentation provides a comprehensive reference for the {componentName} component, guiding you through its configuration options."; + private const string metaTitle = $"Blazor {componentName} Component"; + private const string metaDescription = $"This documentation provides a comprehensive reference for the {componentName} component, guiding you through its configuration options."; + private const string imageUrl = DemoScreenshotSrcConstants.Demos_URL_Switch; +} \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Form/TextAreaInput/TextAreaInput_Doc_01_Documentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Form/TextAreaInput/TextAreaInput_Doc_01_Documentation.razor new file mode 100644 index 000000000..83b78778c --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Form/TextAreaInput/TextAreaInput_Doc_01_Documentation.razor @@ -0,0 +1,37 @@ +@attribute [Route(pageUrl)] +@layout DocsMainLayout + + + + + +
    + @metaTitle +
    + +
    + +
    + +
    + +
    + +
    + +
    + +@code { + private const string componentName = nameof(TextAreaInput); + private const string pageUrl = DemoRouteConstants.Docs_URL_TextAreaInput; + private const string pageTitle = componentName; + private const string pageDescription = $"This documentation provides a comprehensive reference for the {componentName} component, guiding you through its configuration options."; + private const string metaTitle = $"Blazor {componentName} Component"; + private const string metaDescription = $"This documentation provides a comprehensive reference for the {componentName} component, guiding you through its configuration options."; + private const string imageUrl = DemoScreenshotSrcConstants.Demos_URL_TextAreaInput; +} \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Form/TextInput/TextInput_Doc_01_Documentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Form/TextInput/TextInput_Doc_01_Documentation.razor new file mode 100644 index 000000000..ef1a04d81 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Form/TextInput/TextInput_Doc_01_Documentation.razor @@ -0,0 +1,37 @@ +@attribute [Route(pageUrl)] +@layout DocsMainLayout + + + + + +
    + @metaTitle +
    + +
    + +
    + +
    + +
    + +
    + +
    + +@code { + private const string componentName = nameof(TextInput); + private const string pageUrl = DemoRouteConstants.Docs_URL_TextInput; + private const string pageTitle = componentName; + private const string pageDescription = $"This documentation provides a comprehensive reference for the {componentName} component, guiding you through its configuration options."; + private const string metaTitle = $"Blazor {componentName} Component"; + private const string metaDescription = $"This documentation provides a comprehensive reference for the {componentName} component, guiding you through its configuration options."; + private const string imageUrl = DemoScreenshotSrcConstants.Demos_URL_TextInput; +} \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Form/TimeInput/TimeInput_Doc_01_Documentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Form/TimeInput/TimeInput_Doc_01_Documentation.razor new file mode 100644 index 000000000..b173cf48d --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Form/TimeInput/TimeInput_Doc_01_Documentation.razor @@ -0,0 +1,37 @@ +@attribute [Route(pageUrl)] +@layout DocsMainLayout + + + + + +
    + @metaTitle +
    + +
    + +
    + +
    + +
    + +
    + +
    + +@code { + private const string componentName = nameof(TimeInput); + private const string pageUrl = DemoRouteConstants.Docs_URL_TimeInput; + private const string pageTitle = componentName; + private const string pageDescription = $"This documentation provides a comprehensive reference for the {componentName} component, guiding you through its configuration options."; + private const string metaTitle = $"Blazor {componentName} Component"; + private const string metaDescription = $"This documentation provides a comprehensive reference for the {componentName} component, guiding you through its configuration options."; + private const string imageUrl = DemoScreenshotSrcConstants.Demos_URL_TimeInput; +} \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/GettingStarted/GettingStarted_Doc_01_Documentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/GettingStarted/GettingStarted_Doc_01_Documentation.razor new file mode 100644 index 000000000..4a7cf85ca --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/GettingStarted/GettingStarted_Doc_01_Documentation.razor @@ -0,0 +1,36 @@ +@page "/docs" +@page "/docs/getting-started/blazor-webassembly" +@page "/docs/getting-started/blazor-server" +@page "/docs/getting-started/maui-blazor" + +@attribute [Route(pageUrl)] +@layout DocsMainLayout + + + +
    + +
    + +@code { + private const string pageUrl = DemoRouteConstants.Docs_URL_GettingStarted; + private const string pageTitle = "Getting started with Blazor Bootstrap - Blazor Project Setup"; + private const string pageDescription = "High-performance, lightweight, and responsive blazor bootstrap components in a single package from the developers for the developers."; + private const string metaTitle = "Getting started with Blazor Bootstrap - Blazor Project Setup"; + private const string metaDescription = "High-performance, lightweight, and responsive blazor bootstrap components in a single package from the developers for the developers."; + private const string imageUrl = DemoScreenshotSrcConstants.Home; // TODO: Update image URL + + private string? version; + [Inject] public IConfiguration Configuration { get; set; } = default!; + + protected override void OnInitialized() + { + version = Configuration["version"]; // example: v3.5.0 + base.OnInitialized(); + } +} diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Grid/Grid_Doc_01_Documentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Grid/Grid_Doc_01_Documentation.razor new file mode 100644 index 000000000..1c17fb02c --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Grid/Grid_Doc_01_Documentation.razor @@ -0,0 +1,69 @@ +@attribute [Route(pageUrl)] +@layout DocsMainLayout + + + + + +
    + @metaTitle +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    + +@code { + private const string componentName = nameof(Grid); + private const string pageUrl = DemoRouteConstants.Docs_URL_Grid; + private const string pageTitle = componentName; + private const string pageDescription = $"This documentation provides a comprehensive reference for the {componentName} component, guiding you through its configuration options."; + private const string metaTitle = $"Blazor {componentName} Component"; + private const string metaDescription = $"This documentation provides a comprehensive reference for the {componentName} component, guiding you through its configuration options."; + private const string imageUrl = DemoScreenshotSrcConstants.Demos_URL_Grid_Overview; + + public class TItem : object + { + } +} \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Icons/Icon_Doc_01_Documentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Icons/Icon_Doc_01_Documentation.razor new file mode 100644 index 000000000..35d687578 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Icons/Icon_Doc_01_Documentation.razor @@ -0,0 +1,41 @@ +@attribute [Route(pageUrl)] +@layout DocsMainLayout + + + + + +
    + @metaTitle +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    + +@code { + private const string componentName = nameof(Icon); + private const string pageUrl = DemoRouteConstants.Docs_URL_Icons; + private const string pageTitle = componentName; + private const string pageDescription = $"This documentation provides a comprehensive reference for the {componentName} component, guiding you through its configuration options."; + private const string metaTitle = $"Blazor {componentName} Component"; + private const string metaDescription = $"This documentation provides a comprehensive reference for the {componentName} component, guiding you through its configuration options."; + private const string imageUrl = DemoScreenshotSrcConstants.Demos_URL_Icons; +} \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Images/Image_Doc_01_Documentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Images/Image_Doc_01_Documentation.razor new file mode 100644 index 000000000..14afba315 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Images/Image_Doc_01_Documentation.razor @@ -0,0 +1,29 @@ +@attribute [Route(pageUrl)] +@layout DocsMainLayout + + + + + +
    + @metaTitle +
    + +
    + +
    + +@code { + private const string componentName = nameof(Image); + private const string pageUrl = DemoRouteConstants.Docs_URL_Images; + private const string pageTitle = componentName; + private const string pageDescription = $"This documentation provides a comprehensive reference for the {componentName} component, guiding you through its configuration options."; + private const string metaTitle = $"Blazor {componentName} Component"; + private const string metaDescription = $"This documentation provides a comprehensive reference for the {componentName} component, guiding you through its configuration options."; + private const string imageUrl = DemoScreenshotSrcConstants.Demos_URL_Images; +} \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Layout/Layout_Doc_01_Documentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Layout/Layout_Doc_01_Documentation.razor new file mode 100644 index 000000000..bf58515fd --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Layout/Layout_Doc_01_Documentation.razor @@ -0,0 +1,39 @@ +@attribute [Route(pageUrl)] +@layout DocsMainLayout + + + + + +
    + @metaTitle +
    + +
    + +
    + +@code { + private const string componentName = nameof(BlazorBootstrapLayout); + private const string pageUrl = DemoRouteConstants.Docs_URL_Layout; + private const string pageTitle = componentName; + private const string pageDescription = $"This documentation provides a comprehensive reference for the {componentName} component, guiding you through its configuration options."; + private const string metaTitle = $"Blazor {componentName} Component"; + private const string metaDescription = $"This documentation provides a comprehensive reference for the {componentName} component, guiding you through its configuration options."; + private const string imageUrl = DemoScreenshotSrcConstants.Demos_URL_Layout; + + private string version = default!; + + [Inject] public IConfiguration Configuration { get; set; } = default!; + + protected override void OnInitialized() + { + version = Configuration["version"]!; // example: v3.5.0 + base.OnInitialized(); + } +} diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Maps/GoogleMap_Doc_01_Documentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Maps/GoogleMap_Doc_01_Documentation.razor new file mode 100644 index 000000000..152a41e09 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Maps/GoogleMap_Doc_01_Documentation.razor @@ -0,0 +1,37 @@ +@attribute [Route(pageUrl)] +@layout DocsMainLayout + + + + + +
    + @metaTitle +
    + +
    + +
    + +
    + +
    + +
    + +
    + +@code { + private const string componentName = nameof(GoogleMap); + private const string pageUrl = DemoRouteConstants.Docs_URL_GoogleMap; + private const string pageTitle = componentName; + private const string pageDescription = $"This documentation provides a comprehensive reference for the {componentName} component, guiding you through its configuration options."; + private const string metaTitle = $"Blazor {componentName} Component"; + private const string metaDescription = $"This documentation provides a comprehensive reference for the {componentName} component, guiding you through its configuration options."; + private const string imageUrl = DemoScreenshotSrcConstants.Demos_URL_GoogleMap; +} \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Markdown/Markdown_Doc_01_Documentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Markdown/Markdown_Doc_01_Documentation.razor new file mode 100644 index 000000000..6fbe7b352 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Markdown/Markdown_Doc_01_Documentation.razor @@ -0,0 +1,29 @@ +@attribute [Route(pageUrl)] +@layout DocsMainLayout + + + + + +
    + @metaTitle +
    + +
    + +
    + +@code { + private const string componentName = nameof(Markdown); + private const string pageUrl = DemoRouteConstants.Docs_URL_Markdown; + private const string pageTitle = componentName; + private const string pageDescription = $"This documentation provides a comprehensive reference for the {componentName} component, guiding you through its configuration options."; + private const string metaTitle = $"Blazor {componentName} Component"; + private const string metaDescription = $"This documentation provides a comprehensive reference for the {componentName} component, guiding you through its configuration options."; + private const string imageUrl = DemoScreenshotSrcConstants.Demos_URL_Markdown; +} \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Modal/Modal_Doc_01_Documentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Modal/Modal_Doc_01_Documentation.razor new file mode 100644 index 000000000..bb5e2d15b --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Modal/Modal_Doc_01_Documentation.razor @@ -0,0 +1,37 @@ +@attribute [Route(pageUrl)] +@layout DocsMainLayout + + + + + +
    + @metaTitle +
    + +
    + +
    + +
    + +
    + +
    + +
    + +@code { + private const string componentName = nameof(Modal); + private const string pageUrl = DemoRouteConstants.Docs_URL_Modal; + private const string pageTitle = componentName; + private const string pageDescription = $"This documentation provides a comprehensive reference for the {componentName} component, guiding you through its configuration options."; + private const string metaTitle = $"Blazor {componentName} Component"; + private const string metaDescription = $"This documentation provides a comprehensive reference for the {componentName} component, guiding you through its configuration options."; + private const string imageUrl = DemoScreenshotSrcConstants.Demos_URL_Modal; +} \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Offcanvas/Offcanvas_Doc_01_Documentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Offcanvas/Offcanvas_Doc_01_Documentation.razor new file mode 100644 index 000000000..7c4ef42b2 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Offcanvas/Offcanvas_Doc_01_Documentation.razor @@ -0,0 +1,37 @@ +@attribute [Route(pageUrl)] +@layout DocsMainLayout + + + + + +
    + @metaTitle +
    + +
    + +
    + +
    + +
    + +
    + +
    + +@code { + private const string componentName = nameof(Offcanvas); + private const string pageUrl = DemoRouteConstants.Docs_URL_Offcanvas; + private const string pageTitle = componentName; + private const string pageDescription = $"This documentation provides a comprehensive reference for the {componentName} component, guiding you through its configuration options."; + private const string metaTitle = $"Blazor {componentName} Component"; + private const string metaDescription = $"This documentation provides a comprehensive reference for the {componentName} component, guiding you through its configuration options."; + private const string imageUrl = DemoScreenshotSrcConstants.Demos_URL_Offcanvas; +} \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Pagination/Pagination_Doc_01_Documentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Pagination/Pagination_Doc_01_Documentation.razor new file mode 100644 index 000000000..1a3b297d4 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Pagination/Pagination_Doc_01_Documentation.razor @@ -0,0 +1,33 @@ +@attribute [Route(pageUrl)] +@layout DocsMainLayout + + + + + +
    + @metaTitle +
    + +
    + +
    + +
    + +
    + +@code { + private const string componentName = nameof(Pagination); + private const string pageUrl = DemoRouteConstants.Docs_URL_Pagination; + private const string pageTitle = componentName; + private const string pageDescription = $"This documentation provides a comprehensive reference for the {componentName} component, guiding you through its configuration options."; + private const string metaTitle = $"Blazor {componentName} Component"; + private const string metaDescription = $"This documentation provides a comprehensive reference for the {componentName} component, guiding you through its configuration options."; + private const string imageUrl = DemoScreenshotSrcConstants.Demos_URL_Pagination; +} \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/PdfViewer/PdfViewer_Doc_01_Documentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/PdfViewer/PdfViewer_Doc_01_Documentation.razor new file mode 100644 index 000000000..ffd0fd1bc --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/PdfViewer/PdfViewer_Doc_01_Documentation.razor @@ -0,0 +1,41 @@ +@attribute [Route(pageUrl)] +@layout DocsMainLayout + + + + + +
    + @metaTitle +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    + +@code { + private const string componentName = nameof(PdfViewer); + private const string pageUrl = DemoRouteConstants.Docs_URL_PDFViewer; + private const string pageTitle = componentName; + private const string pageDescription = $"This documentation provides a comprehensive reference for the {componentName} component, guiding you through its configuration options."; + private const string metaTitle = $"Blazor {componentName} Component"; + private const string metaDescription = $"This documentation provides a comprehensive reference for the {componentName} component, guiding you through its configuration options."; + private const string imageUrl = DemoScreenshotSrcConstants.Demos_URL_PDFViewer; +} \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Placeholders/Placeholder_Doc_01_Documentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Placeholders/Placeholder_Doc_01_Documentation.razor new file mode 100644 index 000000000..7cc2a1cba --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Placeholders/Placeholder_Doc_01_Documentation.razor @@ -0,0 +1,33 @@ +@attribute [Route(pageUrl)] +@layout DocsMainLayout + + + + + +
    + @metaTitle +
    + +
    + +
    + +
    + +
    + +@code { + private const string componentName = nameof(Placeholder); + private const string pageUrl = DemoRouteConstants.Docs_URL_Placeholders; + private const string pageTitle = componentName; + private const string pageDescription = $"This documentation provides a comprehensive reference for the {componentName} component, guiding you through its configuration options."; + private const string metaTitle = $"Blazor {componentName} Component"; + private const string metaDescription = $"This documentation provides a comprehensive reference for the {componentName} component, guiding you through its configuration options."; + private const string imageUrl = DemoScreenshotSrcConstants.Demos_URL_Placeholders; +} \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Preload/Preload_Doc_01_Documentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Preload/Preload_Doc_01_Documentation.razor new file mode 100644 index 000000000..579c3d7df --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Preload/Preload_Doc_01_Documentation.razor @@ -0,0 +1,33 @@ +@attribute [Route(pageUrl)] +@layout DocsMainLayout + + + + + +
    + @metaTitle +
    + +
    + +
    + +
    + +
    + +@code { + private const string componentName = nameof(Preload); + private const string pageUrl = DemoRouteConstants.Docs_URL_Preload; + private const string pageTitle = componentName; + private const string pageDescription = $"This documentation provides a comprehensive reference for the {componentName} component, guiding you through its configuration options."; + private const string metaTitle = $"Blazor {componentName} Component"; + private const string metaDescription = $"This documentation provides a comprehensive reference for the {componentName} component, guiding you through its configuration options."; + private const string imageUrl = DemoScreenshotSrcConstants.Demos_URL_Preload; +} \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Progress/Progress_Doc_01_Documentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Progress/Progress_Doc_01_Documentation.razor new file mode 100644 index 000000000..69ac22c8d --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Progress/Progress_Doc_01_Documentation.razor @@ -0,0 +1,37 @@ +@attribute [Route(pageUrl)] +@layout DocsMainLayout + + + + + +
    + @metaTitle +
    + +
    + +
    + +
    + +
    + +
    + +
    + +@code { + private const string componentName = nameof(Progress); + private const string pageUrl = DemoRouteConstants.Docs_URL_Progress; + private const string pageTitle = componentName; + private const string pageDescription = $"This documentation provides a comprehensive reference for the {componentName} component, guiding you through its configuration options."; + private const string metaTitle = $"Blazor {componentName} Component"; + private const string metaDescription = $"This documentation provides a comprehensive reference for the {componentName} component, guiding you through its configuration options."; + private const string imageUrl = DemoScreenshotSrcConstants.Demos_URL_Progress; +} \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Ribbon/Ribbon_Doc_01_Documentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Ribbon/Ribbon_Doc_01_Documentation.razor new file mode 100644 index 000000000..707a0ed94 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Ribbon/Ribbon_Doc_01_Documentation.razor @@ -0,0 +1,61 @@ +@attribute [Route(pageUrl)] +@layout DocsMainLayout + + + + + +
    + @metaTitle +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    + +@code { + private const string componentName = nameof(Ribbon); + private const string pageUrl = DemoRouteConstants.Docs_URL_Ribbon; + private const string pageTitle = componentName; + private const string pageDescription = $"This documentation provides a comprehensive reference for the {componentName} component, guiding you through its configuration options."; + private const string metaTitle = $"Blazor {componentName} Component"; + private const string metaDescription = $"This documentation provides a comprehensive reference for the {componentName} component, guiding you through its configuration options."; + private const string imageUrl = DemoScreenshotSrcConstants.Demos_URL_Ribbon; +} \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/ScriptLoader/ScriptLoader_Doc_01_Documentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/ScriptLoader/ScriptLoader_Doc_01_Documentation.razor new file mode 100644 index 000000000..975888326 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/ScriptLoader/ScriptLoader_Doc_01_Documentation.razor @@ -0,0 +1,33 @@ +@attribute [Route(pageUrl)] +@layout DocsMainLayout + + + + + +
    + @metaTitle +
    + +
    + +
    + +
    + +
    + +@code { + private const string componentName = nameof(ScriptLoader); + private const string pageUrl = DemoRouteConstants.Docs_URL_ScriptLoader; + private const string pageTitle = componentName; + private const string pageDescription = $"This documentation provides a comprehensive reference for the {componentName} component, guiding you through its configuration options."; + private const string metaTitle = $"Blazor {componentName} Component"; + private const string metaDescription = $"This documentation provides a comprehensive reference for the {componentName} component, guiding you through its configuration options."; + private const string imageUrl = DemoScreenshotSrcConstants.Demos_URL_ScriptLoader; +} \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Services/BreadcrumbService/BreadcrumbService_Doc_01_Documentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Services/BreadcrumbService/BreadcrumbService_Doc_01_Documentation.razor new file mode 100644 index 000000000..f33ff4eb3 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Services/BreadcrumbService/BreadcrumbService_Doc_01_Documentation.razor @@ -0,0 +1,29 @@ +@attribute [Route(pageUrl)] +@layout DocsMainLayout + + + + + +
    + @metaTitle +
    + +
    + +
    + +@code { + private const string componentName = nameof(BreadcrumbService); + private const string pageUrl = DemoRouteConstants.Docs_URL_BreadcrumbService; + private const string pageTitle = componentName; + private const string pageDescription = $"This documentation provides a comprehensive reference for the {componentName} component, guiding you through its configuration options."; + private const string metaTitle = $"Blazor {componentName} Component"; + private const string metaDescription = $"This documentation provides a comprehensive reference for the {componentName} component, guiding you through its configuration options."; + private const string imageUrl = DemoScreenshotSrcConstants.Demos_URL_Breadcrumb; +} \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Services/ModalService/ModalService_Doc_01_Documentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Services/ModalService/ModalService_Doc_01_Documentation.razor new file mode 100644 index 000000000..db752923f --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Services/ModalService/ModalService_Doc_01_Documentation.razor @@ -0,0 +1,33 @@ +@attribute [Route(pageUrl)] +@layout DocsMainLayout + + + + + +
    + @metaTitle +
    + +
    + +
    + +
    + +
    + +@code { + private const string componentName = nameof(ModalService); + private const string pageUrl = DemoRouteConstants.Docs_URL_ModalService; + private const string pageTitle = componentName; + private const string pageDescription = $"This documentation provides a comprehensive reference for the {componentName} component, guiding you through its configuration options."; + private const string metaTitle = $"Blazor {componentName} Component"; + private const string metaDescription = $"This documentation provides a comprehensive reference for the {componentName} component, guiding you through its configuration options."; + private const string imageUrl = DemoScreenshotSrcConstants.Demos_URL_ModalService; +} \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Services/PreloadService/PreloadService_Doc_01_Documentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Services/PreloadService/PreloadService_Doc_01_Documentation.razor new file mode 100644 index 000000000..6c67507b6 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Services/PreloadService/PreloadService_Doc_01_Documentation.razor @@ -0,0 +1,29 @@ +@attribute [Route(pageUrl)] +@layout DocsMainLayout + + + + + +
    + @metaTitle +
    + +
    + +
    + +@code { + private const string componentName = nameof(PreloadService); + private const string pageUrl = DemoRouteConstants.Docs_URL_PreloadService; + private const string pageTitle = componentName; + private const string pageDescription = $"This documentation provides a comprehensive reference for the {componentName} component, guiding you through its configuration options."; + private const string metaTitle = $"Blazor {componentName} Component"; + private const string metaDescription = $"This documentation provides a comprehensive reference for the {componentName} component, guiding you through its configuration options."; + private const string imageUrl = DemoScreenshotSrcConstants.Demos_URL_PreloadService; +} \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Services/ToastService/ToastService_Doc_01_Documentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Services/ToastService/ToastService_Doc_01_Documentation.razor new file mode 100644 index 000000000..6d486bc51 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Services/ToastService/ToastService_Doc_01_Documentation.razor @@ -0,0 +1,42 @@ +@attribute [Route(pageUrl)] +@layout DocsMainLayout + + + + + +
    + @metaTitle +
    + +
    + +
    + +
    +
    Use Notify(...) for the common single Toasts host scenario.
    +
    Use await NotifyAsync(...) when multiple toast subscribers may be registered and the caller needs to await all handlers.
    +
    + +
    + +
    + +
    + +
    + +@code { + private const string componentName = nameof(ToastService); + private const string pageUrl = DemoRouteConstants.Docs_URL_ToastService; + private const string pageTitle = componentName; + private const string pageDescription = $"This documentation provides a comprehensive reference for the {componentName} service, guiding you through its usage."; + private const string metaTitle = $"Blazor {componentName} Service"; + private const string metaDescription = $"This documentation provides a comprehensive reference for the {componentName} service, guiding you through its usage."; + private const string imageUrl = DemoScreenshotSrcConstants.Demos_URL_Toasts; +} \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Sidebar/Sidebar_Doc_01_Documentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Sidebar/Sidebar_Doc_01_Documentation.razor new file mode 100644 index 000000000..d2e88ec93 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Sidebar/Sidebar_Doc_01_Documentation.razor @@ -0,0 +1,37 @@ +@attribute [Route(pageUrl)] +@layout DocsMainLayout + + + + + +
    + @metaTitle +
    + +
    + +
    + +
    + +
    + +
    + +
    + +@code { + private const string componentName = nameof(Sidebar); + private const string pageUrl = DemoRouteConstants.Docs_URL_Sidebar; + private const string pageTitle = componentName; + private const string pageDescription = $"This documentation provides a comprehensive reference for the {componentName} component, guiding you through its configuration options."; + private const string metaTitle = $"Blazor {componentName} Component"; + private const string metaDescription = $"This documentation provides a comprehensive reference for the {componentName} component, guiding you through its configuration options."; + private const string imageUrl = DemoScreenshotSrcConstants.Demos_URL_Sidebar; +} \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Sidebar2/Sidebar2_Doc_01_Documentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Sidebar2/Sidebar2_Doc_01_Documentation.razor new file mode 100644 index 000000000..76a6de150 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Sidebar2/Sidebar2_Doc_01_Documentation.razor @@ -0,0 +1,37 @@ +@attribute [Route(pageUrl)] +@layout DocsMainLayout + + + + + +
    + @metaTitle +
    + +
    + +
    + +
    + +
    + +
    + +
    + +@code { + private const string componentName = nameof(Sidebar2); + private const string pageUrl = DemoRouteConstants.Docs_URL_Sidebar2; + private const string pageTitle = componentName; + private const string pageDescription = $"This documentation provides a comprehensive reference for the {componentName} component, guiding you through its configuration options."; + private const string metaTitle = $"Blazor {componentName} Component"; + private const string metaDescription = $"This documentation provides a comprehensive reference for the {componentName} component, guiding you through its configuration options."; + private const string imageUrl = DemoScreenshotSrcConstants.Demos_URL_Sidebar2; +} \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/SortableList/SortableList_Doc_01_Documentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/SortableList/SortableList_Doc_01_Documentation.razor new file mode 100644 index 000000000..270439e47 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/SortableList/SortableList_Doc_01_Documentation.razor @@ -0,0 +1,35 @@ +@attribute [Route(pageUrl)] +@layout DocsMainLayout + + + + + +
    + @metaTitle +
    + +
    + +
    + +
    + +
    + +@code { + private const string componentName = nameof(SortableList); + private const string pageUrl = DemoRouteConstants.Docs_URL_SortableList; + private const string pageTitle = componentName; + private const string pageDescription = $"This documentation provides a comprehensive reference for the {componentName} component, guiding you through its configuration options."; + private const string metaTitle = $"Blazor {componentName} Component"; + private const string metaDescription = $"This documentation provides a comprehensive reference for the {componentName} component, guiding you through its configuration options."; + private const string imageUrl = DemoScreenshotSrcConstants.Demos_URL_SortableList; + + public class TItem : object { } +} diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Spinners/Spinner_Doc_01_Documentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Spinners/Spinner_Doc_01_Documentation.razor new file mode 100644 index 000000000..e08b4c9c9 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Spinners/Spinner_Doc_01_Documentation.razor @@ -0,0 +1,29 @@ +@attribute [Route(pageUrl)] +@layout DocsMainLayout + + + + + +
    + @metaTitle +
    + +
    + +
    + +@code { + private const string componentName = nameof(Spinner); + private const string pageUrl = DemoRouteConstants.Docs_URL_Spinners; + private const string pageTitle = componentName; + private const string pageDescription = $"This documentation provides a comprehensive reference for the {componentName} component, guiding you through its configuration options."; + private const string metaTitle = $"Blazor {componentName} Component"; + private const string metaDescription = $"This documentation provides a comprehensive reference for the {componentName} component, guiding you through its configuration options."; + private const string imageUrl = DemoScreenshotSrcConstants.Demos_URL_Spinners; +} \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/SplitView/SplitView_Doc_01_Documentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/SplitView/SplitView_Doc_01_Documentation.razor new file mode 100644 index 000000000..332d836d1 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/SplitView/SplitView_Doc_01_Documentation.razor @@ -0,0 +1,45 @@ +@attribute [Route(pageUrl)] +@layout DocsMainLayout + + + + + +
    + @metaTitle +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    + +@code { + private const string componentName = nameof(SplitView); + private const string pageUrl = DemoRouteConstants.Docs_URL_SplitView; + private const string pageTitle = componentName; + private const string pageDescription = $"This documentation provides a comprehensive reference for the {componentName} component, guiding you through its configuration options."; + private const string metaTitle = $"Blazor {componentName} Component"; + private const string metaDescription = $"This documentation provides a comprehensive reference for the {componentName} component, guiding you through its configuration options."; + private const string imageUrl = DemoScreenshotSrcConstants.Demos_URL_SplitView; +} \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Tabs/Tabs_Doc_01_Documentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Tabs/Tabs_Doc_01_Documentation.razor new file mode 100644 index 000000000..c8cf62f11 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Tabs/Tabs_Doc_01_Documentation.razor @@ -0,0 +1,53 @@ +@attribute [Route(pageUrl)] +@layout DocsMainLayout + + + + + +
    + @metaTitle +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    + +@code { + private const string componentName = nameof(Tabs); + private const string pageUrl = DemoRouteConstants.Docs_URL_Tabs; + private const string pageTitle = componentName; + private const string pageDescription = $"This documentation provides a comprehensive reference for the {componentName} component, guiding you through its configuration options."; + private const string metaTitle = $"Blazor {componentName} Component"; + private const string metaDescription = $"This documentation provides a comprehensive reference for the {componentName} component, guiding you through its configuration options."; + private const string imageUrl = DemoScreenshotSrcConstants.Demos_URL_Tabs; +} \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/ThemeSwitcher/ThemeSwitcher_Doc_01_Documentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/ThemeSwitcher/ThemeSwitcher_Doc_01_Documentation.razor new file mode 100644 index 000000000..a0c1e39bf --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/ThemeSwitcher/ThemeSwitcher_Doc_01_Documentation.razor @@ -0,0 +1,33 @@ +@attribute [Route(pageUrl)] +@layout DocsMainLayout + + + + + +
    + @metaTitle +
    + +
    + +
    + +
    + +
    + +@code { + private const string componentName = nameof(ThemeSwitcher); + private const string pageUrl = DemoRouteConstants.Docs_URL_ThemeSwitcher; + private const string pageTitle = componentName; + private const string pageDescription = $"This documentation provides a comprehensive reference for the {componentName} component, guiding you through its configuration options."; + private const string metaTitle = $"Blazor {componentName} Component"; + private const string metaDescription = $"This documentation provides a comprehensive reference for the {componentName} component, guiding you through its configuration options."; + private const string imageUrl = DemoScreenshotSrcConstants.Demos_URL_ThemeSwitcher; +} \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Toasts/Toasts_Doc_01_Documentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Toasts/Toasts_Doc_01_Documentation.razor new file mode 100644 index 000000000..bc68c190b --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Toasts/Toasts_Doc_01_Documentation.razor @@ -0,0 +1,41 @@ +@attribute [Route(pageUrl)] +@layout DocsMainLayout + + + + + +
    + @metaTitle +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    + +@code { + private const string componentName = nameof(Toasts); + private const string pageUrl = DemoRouteConstants.Docs_URL_Toasts; + private const string pageTitle = componentName; + private const string pageDescription = $"This documentation provides a comprehensive reference for the {componentName} component, guiding you through its configuration options."; + private const string metaTitle = $"Blazor {componentName} Component"; + private const string metaDescription = $"This documentation provides a comprehensive reference for the {componentName} component, guiding you through its configuration options."; + private const string imageUrl = DemoScreenshotSrcConstants.Demos_URL_Toasts; +} \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Tooltips/Tooltips_Doc_01_Documentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Tooltips/Tooltips_Doc_01_Documentation.razor new file mode 100644 index 000000000..0df5f282f --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Docs/Tooltips/Tooltips_Doc_01_Documentation.razor @@ -0,0 +1,37 @@ +@attribute [Route(pageUrl)] +@layout DocsMainLayout + + + + + +
    + @metaTitle +
    + +
    + +
    + +
    + +
    + +
    + +
    + +@code { + private const string componentName = nameof(Tooltip); + private const string pageUrl = DemoRouteConstants.Docs_URL_Tooltips; + private const string pageTitle = componentName; + private const string pageDescription = $"This documentation provides a comprehensive reference for the {componentName} component, guiding you through its configuration options."; + private const string metaTitle = $"Blazor {componentName} Component"; + private const string metaDescription = $"This documentation provides a comprehensive reference for the {componentName} component, guiding you through its configuration options."; + private const string imageUrl = DemoScreenshotSrcConstants.Demos_URL_Tooltips; +} \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Dropdowns/Dropdown_Demo_13_AutoClose.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Dropdowns/Dropdown_Demo_13_AutoClose.razor deleted file mode 100644 index 79033412b..000000000 --- a/BlazorBootstrap.Demo.RCL/Components/Pages/Dropdowns/Dropdown_Demo_13_AutoClose.razor +++ /dev/null @@ -1,35 +0,0 @@ - - Default dropdown - - Menu item - Menu item - Menu item - - - - - Clickable outside - - Menu item - Menu item - Menu item - - - - - Clickable inside - - Menu item - Menu item - Menu item - - - - - Manual close - - Menu item - Menu item - Menu item - - diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Dropdowns/Dropdown_Demo_14_Methods.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Dropdowns/Dropdown_Demo_14_Methods.razor deleted file mode 100644 index 85d7034b6..000000000 --- a/BlazorBootstrap.Demo.RCL/Components/Pages/Dropdowns/Dropdown_Demo_14_Methods.razor +++ /dev/null @@ -1,20 +0,0 @@ - - Dropdown button - - Action - Another action - Something else here - - - - - - - -@code{ - private Dropdown dropdown1 = default!; - - private async Task ShowAsync() => await dropdown1.ShowAsync(); - private async Task HideAsync() => await dropdown1.HideAsync(); - private async Task ToggleAsync() => await dropdown1.ToggleAsync(); -} diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/GettingStarted/GettingStartedDocumentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/GettingStarted/GettingStartedDocumentation.razor deleted file mode 100644 index 839fbd92d..000000000 --- a/BlazorBootstrap.Demo.RCL/Components/Pages/GettingStarted/GettingStartedDocumentation.razor +++ /dev/null @@ -1,123 +0,0 @@ -@page "/getting-started/blazor-webassembly" -@page "/getting-started/blazor-server" -@page "/getting-started/maui-blazor" - -@attribute [Route(pageUrl)] - - - - - @pageDescription - - - - -
    -
    - Please find the getting started documentation links, corresponding to each .NET version and project type, listed below: -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    #.NET VersionDocumentation Link
    1.NET 8Blazor WebAssembly (.NET 8)
    2.NET 8Blazor WebApp (.NET 8) - Interactive render mode Server - Global location
    3.NET 8Blazor WebApp (.NET 8) - Interactive render mode Auto - Global location
    4.NET 8MAUI Blazor Hybrid App (.NET 8)
    - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    #.NET VersionDocumentation Link
    1.NET 7Blazor WebAssembly (.NET 7)
    2.NET 7Blazor Server (.NET 7)
    3.NET 7MAUI Blazor Hybrid App (.NET 7)
    - - - - - - - - - - - - - - - - - - - - - - -
    #.NET VersionDocumentation Link
    1.NET 6Blazor WebAssembly (.NET 6)
    2.NET 6Blazor Server (.NET 6)
    -
    - -@code { - private const string pageUrl = RouteConstants.Demos_GettingStarted_Documentation; - private const string pageTitle = "Getting started with Blazor Bootstrap - Blazor Project Setup"; - private const string pageDescription = "High-performance, lightweight, and responsive blazor bootstrap components in a single package from the developers for the developers."; - private const string metaTitle = "Getting started with Blazor Bootstrap - Blazor Project Setup"; - private const string metaDescription = "High-performance, lightweight, and responsive blazor bootstrap components in a single package from the developers for the developers."; - private const string imageUrl = "https://i.imgur.com/SCbZVd4.jpg"; - - private string? version; - [Inject] public IConfiguration Configuration { get; set; } = default!; - - protected override void OnInitialized() - { - version = Configuration["version"]; // example: v0.6.1 - base.OnInitialized(); - } -} diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Index.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Home/Index.razor similarity index 50% rename from BlazorBootstrap.Demo.RCL/Components/Pages/Index.razor rename to BlazorBootstrap.Demo.RCL/Components/Pages/Home/Index.razor index 7f65a9275..67cf8f50f 100644 --- a/BlazorBootstrap.Demo.RCL/Components/Pages/Index.razor +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Home/Index.razor @@ -1,9 +1,9 @@ -@page "/" +@page "/" @layout EmptyLayout Blazor Bootstrap Components Examples & Demos | Blazor Bootstrap - +
    @@ -264,37 +309,91 @@ + +

    Utilities

    @@ -352,7 +540,7 @@
    @@ -379,7 +567,7 @@ protected override void OnInitialized() { - version = $"v{Configuration["version"]}"; // example: v0.6.1 + version = $"v{Configuration["version"]}"; // example: v4.0.1 releaseShortDescription = Configuration["release:short_description"]!; base.OnInitialized(); diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Maps/GoogleMap_Demo_01_Examples.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Maps/GoogleMap_Demo_01_Examples.razor deleted file mode 100644 index 16b50dc0d..000000000 --- a/BlazorBootstrap.Demo.RCL/Components/Pages/Maps/GoogleMap_Demo_01_Examples.razor +++ /dev/null @@ -1,7 +0,0 @@ -@inherits GoogleMapDemoComponentBase - - \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Shared/CarbonAds.razor b/BlazorBootstrap.Demo.RCL/Components/Shared/CarbonAds.razor index 7fc30386e..8e3f7ba25 100644 --- a/BlazorBootstrap.Demo.RCL/Components/Shared/CarbonAds.razor +++ b/BlazorBootstrap.Demo.RCL/Components/Shared/CarbonAds.razor @@ -5,5 +5,5 @@ + Source="//cdn.carbonads.com/carbon.js?serve=CW7ILK7W&placement=docsblazorbootstrapcom&format=cover" /> } diff --git a/BlazorBootstrap.Demo.RCL/Components/Shared/ChartJSCallout.razor b/BlazorBootstrap.Demo.RCL/Components/Shared/ChartJSCallout.razor new file mode 100644 index 000000000..bbe3d08c8 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Shared/ChartJSCallout.razor @@ -0,0 +1,34 @@ +@namespace BlazorBootstrap.Demo.RCL + + +

    Chart Components — Dedicated Library

    +

    + Chart components have been moved to the dedicated BlazorExpress.ChartJS library + to support independent feature additions and easier maintenance. + Complete the following steps in the Blazor project that renders the charts. +

    +
      +
    1. + Install the package used by these demos: +
      dotnet add package BlazorExpress.ChartJS --version 1.2.4
      +
    2. +
    3. + Import the component namespace in _Imports.razor: +
      @@using BlazorExpress.ChartJS
      +
    4. +
    5. + Load the browser scripts in this order from the host page, after the Blazor framework script. + The data-labels plugin is needed only when a chart uses data labels. +
      <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/4.4.1/chart.umd.js"></script>
      +<script src="https://cdnjs.cloudflare.com/ajax/libs/chartjs-plugin-datalabels/2.2.0/chartjs-plugin-datalabels.min.js"></script>
      +<script src="_content/BlazorExpress.ChartJS/blazorexpress.chartjs.js"></script>
      +
    6. +
    +

    + See the BlazorExpress.ChartJS website + and GitHub repository + for current package documentation. We also recommend checking the + original BlazorExpress.ChartJS demos + when adapting advanced examples. +

    +
    diff --git a/BlazorBootstrap.Demo.RCL/Components/Shared/CodeChunk.razor b/BlazorBootstrap.Demo.RCL/Components/Shared/CodeChunk.razor new file mode 100644 index 000000000..6cffa7bbe --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Shared/CodeChunk.razor @@ -0,0 +1,2 @@ +@namespace BlazorBootstrap.Demo.RCL +@inherits BlazorBootstrapComponentBase \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Shared/CodeChunk.razor.cs b/BlazorBootstrap.Demo.RCL/Components/Shared/CodeChunk.razor.cs new file mode 100644 index 000000000..43579ebec --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Shared/CodeChunk.razor.cs @@ -0,0 +1,6 @@ +namespace BlazorBootstrap.Demo.RCL; + +public partial class CodeChunk : BlazorBootstrapComponentBase +{ +} + diff --git a/BlazorBootstrap.Demo.RCL/Components/Shared/Demo.razor.cs b/BlazorBootstrap.Demo.RCL/Components/Shared/Demo.razor.cs index d2b282d24..226158eda 100644 --- a/BlazorBootstrap.Demo.RCL/Components/Shared/Demo.razor.cs +++ b/BlazorBootstrap.Demo.RCL/Components/Shared/Demo.razor.cs @@ -24,7 +24,7 @@ public partial class Demo : BlazorBootstrapComponentBase protected override async Task OnAfterRenderAsync(bool firstRender) { if (firstRender) - await JS.InvokeVoidAsync("highlightCode"); + await SafeInvokeVoidAsync("highlightCode"); await base.OnAfterRenderAsync(firstRender); } @@ -97,7 +97,7 @@ public void ResetCopyStatusJS() StateHasChanged(); } - private async Task CopyToClipboardAsync() => await JS.InvokeVoidAsync("copyToClipboard", snippet, objRef); + private async Task CopyToClipboardAsync() => await SafeInvokeVoidAsync("copyToClipboard", snippet, objRef); #endregion @@ -105,8 +105,6 @@ public void ResetCopyStatusJS() protected override string? ClassNames => BuildClassNames(Class, ("bd-example-snippet bd-code-snippet", true)); - [Inject] protected IJSRuntime JS { get; set; } = default!; - [Parameter] public LanguageCode LanguageCode { get; set; } = LanguageCode.Razor; [Parameter] public bool ShowCodeOnly { get; set; } diff --git a/BlazorBootstrap.Demo.RCL/Components/Shared/DemoLink.razor b/BlazorBootstrap.Demo.RCL/Components/Shared/DemoLink.razor new file mode 100644 index 000000000..ea6a322e3 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Shared/DemoLink.razor @@ -0,0 +1,14 @@ +@namespace BlazorBootstrap.Demo.RCL +@inherits BlazorBootstrapComponentBase + +
    + +
    + +@code{ + [Parameter] + public string? Href { get; set; } +} \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Shared/DemosPageHeadSection.razor b/BlazorBootstrap.Demo.RCL/Components/Shared/DemosPageHeadSection.razor new file mode 100644 index 000000000..bbb64616e --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Shared/DemosPageHeadSection.razor @@ -0,0 +1,33 @@ +@namespace BlazorBootstrap.Demo.RCL +@inherits BlazorBootstrapComponentBase + + + + + @((MarkupString)PageDescription!) + + + + +@code { + [Parameter] + public string? PageUrl { get; set; } + + [Parameter] + public string? PageTitle { get; set; } + + [Parameter] + public string? PageDescription { get; set; } + + [Parameter] + public string? MetaTitle { get; set; } + + [Parameter] + public string? MetaDescription { get; set; } + + [Parameter] + public string? ImageUrl { get; set; } +} \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Shared/DoYouKnow.razor b/BlazorBootstrap.Demo.RCL/Components/Shared/DoYouKnow.razor new file mode 100644 index 000000000..6cffa7bbe --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Shared/DoYouKnow.razor @@ -0,0 +1,2 @@ +@namespace BlazorBootstrap.Demo.RCL +@inherits BlazorBootstrapComponentBase \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Shared/DocsLink.razor b/BlazorBootstrap.Demo.RCL/Components/Shared/DocsLink.razor new file mode 100644 index 000000000..6cf566c5e --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Shared/DocsLink.razor @@ -0,0 +1,17 @@ +@namespace BlazorBootstrap.Demo.RCL +@inherits BlazorBootstrapComponentBase + +
    + +
    + +@code { + [Parameter] + public string? Href { get; set; } + + [Parameter] + public string? Text { get; set; } = "API Documentation"; +} \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Shared/DocsPageHeadSection.razor b/BlazorBootstrap.Demo.RCL/Components/Shared/DocsPageHeadSection.razor new file mode 100644 index 000000000..bbb64616e --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Shared/DocsPageHeadSection.razor @@ -0,0 +1,33 @@ +@namespace BlazorBootstrap.Demo.RCL +@inherits BlazorBootstrapComponentBase + + + + + @((MarkupString)PageDescription!) + + + + +@code { + [Parameter] + public string? PageUrl { get; set; } + + [Parameter] + public string? PageTitle { get; set; } + + [Parameter] + public string? PageDescription { get; set; } + + [Parameter] + public string? MetaTitle { get; set; } + + [Parameter] + public string? MetaDescription { get; set; } + + [Parameter] + public string? ImageUrl { get; set; } +} \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Shared/DocxTable/DocxEnumRow.razor b/BlazorBootstrap.Demo.RCL/Components/Shared/DocxTable/DocxEnumRow.razor new file mode 100644 index 000000000..9b72ff62f --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Shared/DocxTable/DocxEnumRow.razor @@ -0,0 +1,10 @@ +@namespace BlazorBootstrap.Demo.RCL +@inherits BlazorBootstrapComponentBase +@typeparam TItem + + + @Name + @Value + @((MarkupString)Description) + @AddedVersion + \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Shared/DocxTable/DocxEnumRow.razor.cs b/BlazorBootstrap.Demo.RCL/Components/Shared/DocxTable/DocxEnumRow.razor.cs new file mode 100644 index 000000000..b50102e13 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Shared/DocxTable/DocxEnumRow.razor.cs @@ -0,0 +1,21 @@ +namespace BlazorBootstrap.Demo.RCL; + +public partial class DocxEnumRow : BlazorBootstrapComponentBase +{ + private string Name => EnumValue.ToString(); + + private string Value => Convert.ToInt64(EnumValue).ToString(); + + private string Description => EnumFieldInfo? + .GetCustomAttribute(inherit: false)? + .Description ?? Name; + + private string AddedVersion => EnumFieldInfo? + .GetCustomAttribute(inherit: false)? + .Version ?? string.Empty; + + private FieldInfo? EnumFieldInfo => EnumValue.GetType().GetField(Name); + + [Parameter] + public Enum EnumValue { get; set; } = default!; +} diff --git a/BlazorBootstrap.Demo.RCL/Components/Shared/DocxTable/DocxEventCallbackRow.razor b/BlazorBootstrap.Demo.RCL/Components/Shared/DocxTable/DocxEventCallbackRow.razor new file mode 100644 index 000000000..a33d38400 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Shared/DocxTable/DocxEventCallbackRow.razor @@ -0,0 +1,10 @@ +@namespace BlazorBootstrap.Demo.RCL +@inherits BlazorBootstrapComponentBase +@typeparam TItem + + + @PropertyInfo.Name + @ReturnType + @((MarkupString)Description) + @AddedVersion + \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Shared/DocxTable/DocxEventCallbackRow.razor.cs b/BlazorBootstrap.Demo.RCL/Components/Shared/DocxTable/DocxEventCallbackRow.razor.cs new file mode 100644 index 000000000..5e2b27c9a --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Shared/DocxTable/DocxEventCallbackRow.razor.cs @@ -0,0 +1,22 @@ +namespace BlazorBootstrap.Demo.RCL; + +/// +/// +/// +/// +public partial class DocxEventCallbackRow : BlazorBootstrapComponentBase +{ + private string AddedVersion => PropertyInfo.GetPropertyAddedVersion(VersionContextType); + + private string Description => PropertyInfo.GetPropertyDescription(); + + private string ParameterTypeName => PropertyInfo.GetParameterTypeName(); + + private string ReturnType => ParameterTypeName ?? PropertyInfo.GetEventCallbackReturnType(); + + [Parameter] + public PropertyInfo PropertyInfo { get; set; } = default!; + [Parameter] + public Type? VersionContextType { get; set; } + +} diff --git a/BlazorBootstrap.Demo.RCL/Components/Shared/DocxTable/DocxMethodRow.razor b/BlazorBootstrap.Demo.RCL/Components/Shared/DocxTable/DocxMethodRow.razor new file mode 100644 index 000000000..58916f04b --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Shared/DocxTable/DocxMethodRow.razor @@ -0,0 +1,10 @@ +@namespace BlazorBootstrap.Demo.RCL +@inherits BlazorBootstrapComponentBase +@typeparam TItem + + + @MethodName + @ReturnType + @((MarkupString)Description) + @AddedVersion + \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Shared/DocxTable/DocxMethodRow.razor.cs b/BlazorBootstrap.Demo.RCL/Components/Shared/DocxTable/DocxMethodRow.razor.cs new file mode 100644 index 000000000..e344d1ceb --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Shared/DocxTable/DocxMethodRow.razor.cs @@ -0,0 +1,21 @@ +namespace BlazorBootstrap.Demo.RCL; + +/// +/// +/// +public partial class DocxMethodRow : BlazorBootstrapComponentBase +{ + private string AddedVersion => MethodInfo.GetMethodAddedVersion(VersionContextType ?? typeof(TItem)); + + private string Description => MethodInfo.GetMethodDescription(); + + public string ReturnType => MethodInfo.GetMethodReturnType(); + + public string MethodName => MethodInfo.GetMethodName(); + + [Parameter] + public MethodInfo MethodInfo { get; set; } = default!; + + [Parameter] + public Type? VersionContextType { get; set; } +} diff --git a/BlazorBootstrap.Demo.RCL/Components/Shared/DocxTable/DocxPropertyRow.razor b/BlazorBootstrap.Demo.RCL/Components/Shared/DocxTable/DocxPropertyRow.razor new file mode 100644 index 000000000..7d2fa351a --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Shared/DocxTable/DocxPropertyRow.razor @@ -0,0 +1,17 @@ +@namespace BlazorBootstrap.Demo.RCL +@inherits BlazorBootstrapComponentBase +@typeparam TItem + + + @PropertyInfo.Name + @ParameterTypeName + @DefaultValue + + @if (IsRequired) + { + + } + + @((MarkupString)Description) + @AddedVersion + \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Shared/DocxTable/DocxPropertyRow.razor.cs b/BlazorBootstrap.Demo.RCL/Components/Shared/DocxTable/DocxPropertyRow.razor.cs new file mode 100644 index 000000000..508786a0c --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Shared/DocxTable/DocxPropertyRow.razor.cs @@ -0,0 +1,26 @@ +namespace BlazorBootstrap.Demo.RCL; + +/// +/// +/// +public partial class DocxPropertyRow : BlazorBootstrapComponentBase +{ + private string DefaultValue => PropertyInfo.GetPropertyDefaultValue(); + + private string ParameterTypeName => PropertyInfo.GetParameterTypeName(); + + private bool IsRequired => PropertyInfo.IsPropertyRequired(); + + private string AddedVersion => PropertyInfo.GetPropertyAddedVersion(VersionContextType ?? typeof(TItem), AddedVersionOverrides); + + private string Description => PropertyInfo.GetPropertyDescription(); + + [Parameter] + public PropertyInfo PropertyInfo { get; set; } = default!; + + [Parameter] + public IReadOnlyDictionary? AddedVersionOverrides { get; set; } + + [Parameter] + public Type? VersionContextType { get; set; } +} diff --git a/BlazorBootstrap.Demo.RCL/Components/Shared/DocxTable/DocxTable.razor b/BlazorBootstrap.Demo.RCL/Components/Shared/DocxTable/DocxTable.razor new file mode 100644 index 000000000..f422166d3 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Shared/DocxTable/DocxTable.razor @@ -0,0 +1,126 @@ +@namespace BlazorBootstrap.Demo.RCL +@inherits BlazorBootstrapComponentBase +@typeparam TItem + + + @if (DocType is DocType.Parameters) + { +
    + + + + + + + + + + + + + @foreach (var propertyInfo in typeof(TItem).GetComponentParametersOnly()) + { + + } + +
    NameTypeDefaultRequiredDescriptionAdded Version
    +
    + } + else if (DocType is DocType.Properties) + { +
    + + + + + + + + + + + + + @foreach (var propertyInfo in typeof(TItem).GetModelProperties()) + { + + } + +
    NameTypeDefaultRequiredDescriptionAdded Version
    +
    + } + else if (DocType == DocType.Methods) + { +
    + + + + + + + + + + + @foreach (var methodInfo in typeof(TItem).GetComponentMethods()) + { + + } + +
    NameReturn typeDescriptionAdded Version
    +
    + } + else if (DocType == DocType.Events) + { +
    + + + + + + + + + + + @foreach (var propertyInfo in typeof(TItem).GetComponentEventCallbacks()) + { + + } + +
    NameReturn TypeDescriptionAdded Version
    +
    + } + else if (DocType == DocType.Enum) + { +
    + + + + + + + + + + + @if (typeof(TItem).IsEnum) + { + @foreach (var enumValue in Enum.GetValues(typeof(TItem))) + { + + } + } + +
    NameValueDescriptionAdded Version
    +
    + } +
    + +@code { + [Parameter] + public IReadOnlyDictionary? AddedVersionOverrides { get; set; } + + [Parameter] + public Type? VersionContextType { get; set; } +} \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Shared/DocxTable/DocxTable.razor.cs b/BlazorBootstrap.Demo.RCL/Components/Shared/DocxTable/DocxTable.razor.cs new file mode 100644 index 000000000..0ecf41adc --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Shared/DocxTable/DocxTable.razor.cs @@ -0,0 +1,7 @@ +namespace BlazorBootstrap.Demo.RCL; + +public partial class DocxTable : BlazorBootstrapComponentBase +{ + [Parameter] + public DocType DocType { get; set; } = DocType.Parameters; +} diff --git a/BlazorBootstrap.Demo.RCL/Components/Shared/GettingStarted/GettingStarted.razor b/BlazorBootstrap.Demo.RCL/Components/Shared/GettingStarted/GettingStarted.razor new file mode 100644 index 000000000..0af6247cc --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Shared/GettingStarted/GettingStarted.razor @@ -0,0 +1,42 @@ +@namespace BlazorBootstrap.Demo.RCL +@inherits BlazorBootstrapComponentBase + +
    + Please find the getting started documentation links, corresponding to each .NET version and project type, listed below: +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    #.NET VersionDocumentation Link
    1.NET 8Blazor WebAssembly (.NET 8)
    2.NET 8Blazor WebApp (.NET 8) - Interactive render mode Server - Global location
    3.NET 8Blazor WebApp (.NET 8) - Interactive render mode Auto - Global location
    4.NET 8MAUI Blazor Hybrid App (.NET 8)
    + +
    + +
    \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Shared/Snippet.cs b/BlazorBootstrap.Demo.RCL/Components/Shared/Snippet.cs index 929ff8d96..e4600d8ec 100644 --- a/BlazorBootstrap.Demo.RCL/Components/Shared/Snippet.cs +++ b/BlazorBootstrap.Demo.RCL/Components/Shared/Snippet.cs @@ -1,10 +1,11 @@ namespace BlazorBootstrap.Demo.RCL; -public class Snippet : ComponentBase +public class Snippet : BlazorBootstrapComponentBase { #region Members private string? snippet; + private bool isJsRuntimeAvailable = true; #endregion @@ -31,7 +32,7 @@ protected override void BuildRenderTree(RenderTreeBuilder builder) protected override async Task OnAfterRenderAsync(bool firstRender) { if (firstRender) - await JS.InvokeVoidAsync("highlightCode"); + await SafeInvokeVoidAsync("highlightCode"); await base.OnAfterRenderAsync(firstRender); } @@ -69,8 +70,6 @@ protected override async Task OnParametersSetAsync() #region Properties - [Inject] protected IJSRuntime JS { get; set; } = null!; - [Parameter] public LanguageCode LanguageCode { get; set; } = LanguageCode.Razor; [Parameter] public string? FilePath { get; set; } diff --git a/BlazorBootstrap.Demo.RCL/Components/Shared/StarOnGitHub.razor b/BlazorBootstrap.Demo.RCL/Components/Shared/StarOnGitHub.razor new file mode 100644 index 000000000..e69de29bb diff --git a/BlazorBootstrap.Demo.RCL/Components/Shared/WebsiteNavbar.razor b/BlazorBootstrap.Demo.RCL/Components/Shared/WebsiteNavbar.razor new file mode 100644 index 000000000..94648376f --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Shared/WebsiteNavbar.razor @@ -0,0 +1,28 @@ +@namespace BlazorBootstrap.Demo.RCL +@inherits BlazorBootstrapComponentBase + + + + + +
    +
    +
    + + \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Shared/WebsiteNavbar.razor.cs b/BlazorBootstrap.Demo.RCL/Components/Shared/WebsiteNavbar.razor.cs new file mode 100644 index 000000000..55bd956cd --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Shared/WebsiteNavbar.razor.cs @@ -0,0 +1,88 @@ +namespace BlazorBootstrap.Demo.RCL; + +public partial class WebsiteNavbar : BlazorBootstrapComponentBase +{ + #region Fields and Constants + + private bool navbarMenuActive; + + private string version = default!; + private string dotNetVersion = default!; + private string docsUrl = default!; + private string blogUrl = default!; + private string githubUrl = default!; + private string nugetUrl = default!; + private string twitterUrl = default!; + private string linkedInUrl = default!; + private string openCollectiveUrl = default!; + private string githubIssuesUrl = default!; + private string githubDiscussionsUrl = default!; + private string stackoverflowUrl = default!; + + #endregion + + #region Methods + + protected override void OnInitialized() + { + version = $"v{Configuration["version"]}"; // example: v0.6.1 + dotNetVersion = $".NET {Configuration["dotNetVersion"]}"; // example: 9.0.0 + docsUrl = $"{Configuration["urls:docs"]}"; + blogUrl = $"{Configuration["urls:blog"]}"; + githubUrl = $"{Configuration["urls:github"]}"; + nugetUrl = $"{Configuration["urls:nuget"]}"; + twitterUrl = $"{Configuration["urls:twitter"]}"; + linkedInUrl = $"{Configuration["urls:linkedin"]}"; + openCollectiveUrl = $"{Configuration["urls:opencollective"]}"; + githubIssuesUrl = $"{Configuration["urls:github_issues"]}"; + githubDiscussionsUrl = $"{Configuration["urls:github_discussions"]}"; + stackoverflowUrl = $"{Configuration["urls:stackoverflow"]}"; + } + + private Task SetAutoTheme() => SetTheme("system"); + + private Task SetDarkTheme() => SetTheme("dark"); + + private Task SetLightTheme() => SetTheme("light"); + + private async Task SetTheme(string themeName) + { + await JSRuntime.InvokeVoidAsync("setTheme", themeName); + navbarMenuActive = false; + } + + private void ToggleNavbarMenu(bool isActive) + { + navbarMenuActive = isActive; + } + + private async ValueTask OnThemeChanged(string themeName) + => await JSRuntime.InvokeVoidAsync("updateDemoCodeThemeCss", themeName); + + #endregion + + #region Properties, Indexers + + [Inject] public IConfiguration Configuration { get; set; } = default!; + + [Parameter] public string? ApplicationName { get; set; } = null; + + [Parameter] public string? BrandImgAltText { get; set; } = null; + + [Parameter] public string? BrandImgSrc { get; set; } = null; + + public string Version => version; + public string DotNetVersion => dotNetVersion; + public string DocsUrl => docsUrl; + public string BlogUrl => blogUrl; + public string GithubUrl => githubUrl; + public string NuGetUrl => nugetUrl; + public string TwitterUrl => twitterUrl; + public string LinkedInUrl => linkedInUrl; + public string OpenCollectiveUrl => openCollectiveUrl; + public string GithubIssuesUrl => githubIssuesUrl; + public string GithubDiscussionsUrl => githubDiscussionsUrl; + public string StackoverflowUrl => stackoverflowUrl; + + #endregion +} diff --git a/BlazorBootstrap.Demo.RCL/Constants/DemoRouteConstants.cs b/BlazorBootstrap.Demo.RCL/Constants/DemoRouteConstants.cs new file mode 100644 index 000000000..65ab47f61 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Constants/DemoRouteConstants.cs @@ -0,0 +1,212 @@ +namespace BlazorBootstrap.Demo.RCL; + +public static class DemoRouteConstants +{ + public const string Blog_URL_Prefix = "/blog"; + public const string Demos_URL_Prefix = "/demos"; + public const string Docs_URL_Prefix = "/docs"; + + #region Demos + + // Getting Started + public const string Demos_URL_GettingStarted = Demos_URL_Prefix + "/getting-started"; + + // Layout + public const string Demos_URL_Layout_Prefix = Demos_URL_Prefix + "/layout-setup"; + public const string Demos_URL_Layout_BlazorWebAssembly = Demos_URL_Layout_Prefix + "/blazor-webassembly"; + public const string Demos_URL_Layout_Blazor_Server = Demos_URL_Layout_Prefix + "/blazor-server"; + + // AI + //public const string Demos_URL_AI_Prefix = Demos_URL_Prefix + "/ai"; + //public const string Demos_URL_AI_Chat = Demos_URL_AI_Prefix + "/open-ai-chat"; + + // Content + public const string Demos_URL_Icons = Demos_URL_Prefix + "/icons"; + public const string Demos_URL_Images = Demos_URL_Prefix + "/images"; + + // Forms + public const string Demos_URL_Forms_Prefix = Demos_URL_Prefix + "/form"; + public const string Demos_URL_AutoComplete = Demos_URL_Forms_Prefix + "/autocomplete"; + public const string Demos_URL_CheckboxInput = Demos_URL_Forms_Prefix + "/checkbox-input"; + public const string Demos_URL_CurrencyInput = Demos_URL_Forms_Prefix + "/currency-input"; + public const string Demos_URL_DateInput = Demos_URL_Forms_Prefix + "/date-input"; + public const string Demos_URL_DragAndDropFileInput = Demos_URL_Forms_Prefix + "/drag-and-drop-file-input"; + public const string Demos_URL_EnumInput = Demos_URL_Forms_Prefix + "/enum-input"; + public const string Demos_URL_FileInput = Demos_URL_Forms_Prefix + "/file-input"; + public const string Demos_URL_NumberInput = Demos_URL_Forms_Prefix + "/number-input"; + public const string Demos_URL_OTPInput = Demos_URL_Forms_Prefix + "/otp-input"; + public const string Demos_URL_PasswordInput = Demos_URL_Forms_Prefix + "/password-input"; + public const string Demos_URL_RadioInput = Demos_URL_Forms_Prefix + "/radio-input"; + public const string Demos_URL_RangeInput = Demos_URL_Forms_Prefix + "/range-input"; + public const string Demos_URL_RichTextEditor = Demos_URL_Forms_Prefix + "/rich-text-editor"; + public const string Demos_URL_SelectInput = Demos_URL_Forms_Prefix + "/select-input"; + public const string Demos_URL_Switch = Demos_URL_Forms_Prefix + "/switch"; + public const string Demos_URL_TextInput = Demos_URL_Forms_Prefix + "/text-input"; + public const string Demos_URL_TextAreaInput = Demos_URL_Forms_Prefix + "/text-area-input"; + public const string Demos_URL_TimeInput = Demos_URL_Forms_Prefix + "/time-input"; + + // Components + public const string Demos_URL_Accordion = Demos_URL_Prefix + "/accordion"; + public const string Demos_URL_Alerts = Demos_URL_Prefix + "/alerts"; + public const string Demos_URL_Badge = Demos_URL_Prefix + "/badge"; + public const string Demos_URL_Breadcrumb = Demos_URL_Prefix + "/breadcrumb"; + public const string Demos_URL_Buttons = Demos_URL_Prefix + "/buttons"; + public const string Demos_URL_Callout = Demos_URL_Prefix + "/callout"; + public const string Demos_URL_Card = Demos_URL_Prefix + "/card"; + public const string Demos_URL_Carousel = Demos_URL_Prefix + "/carousel"; + public const string Demos_URL_Charts = Demos_URL_Prefix + "/charts"; + public const string Demos_URL_Collapse = Demos_URL_Prefix + "/collapse"; + public const string Demos_URL_ConfirmDialog = Demos_URL_Prefix + "/confirm-dialog"; + public const string Demos_URL_Dropdown = Demos_URL_Prefix + "/dropdown"; + public const string Demos_URL_GoogleMap = Demos_URL_Prefix + "/google-map"; + + #region Grid + public const string Demos_URL_Grid_Prefix = Demos_URL_Prefix + "/grid"; + public const string Demos_URL_Grid_Overview = Demos_URL_Grid_Prefix + "/overview"; + public const string Demos_URL_Grid_Alignment = Demos_URL_Grid_Prefix + "/alignment"; + public const string Demos_URL_Grid_CustomCSSClass = Demos_URL_Grid_Prefix + "/custom-css-class"; + public const string Demos_URL_Grid_DataBinding = Demos_URL_Grid_Prefix + "/data-binding"; + public const string Demos_URL_Grid_DetailView = Demos_URL_Grid_Prefix + "/detail-view"; + public const string Demos_URL_Grid_Events = Demos_URL_Grid_Prefix + "/events"; + public const string Demos_URL_Grid_Filters = Demos_URL_Grid_Prefix + "/filters"; + public const string Demos_URL_Grid_FixedHeader = Demos_URL_Grid_Prefix + "/fixed-header"; + public const string Demos_URL_Grid_FreezeColumns = Demos_URL_Grid_Prefix + "/freeze-columns"; + public const string Demos_URL_Grid_Settings = Demos_URL_Grid_Prefix + "/settings"; + public const string Demos_URL_Grid_NestedGrid = Demos_URL_Grid_Prefix + "/nested-grid"; + public const string Demos_URL_Grid_Paging = Demos_URL_Grid_Prefix + "/paging"; + public const string Demos_URL_Grid_Selection = Demos_URL_Grid_Prefix + "/selection"; + public const string Demos_URL_Grid_Sorting = Demos_URL_Grid_Prefix + "/sorting"; + public const string Demos_URL_Grid_Summary = Demos_URL_Grid_Prefix + "/summary"; + public const string Demos_URL_Grid_Translations = Demos_URL_Grid_Prefix + "/translations"; + public const string Demos_URL_Grid_OtherExamples = Demos_URL_Grid_Prefix + "/other"; + #endregion Grid + + public const string Demos_URL_Markdown = Demos_URL_Prefix + "/markdown"; + public const string Demos_URL_Modal = Demos_URL_Prefix + "/modals"; + public const string Demos_URL_Offcanvas = Demos_URL_Prefix + "/offcanvas"; + public const string Demos_URL_Pagination = Demos_URL_Prefix + "/pagination"; + public const string Demos_URL_PDFViewer = Demos_URL_Prefix + "/pdf-viewer"; + public const string Demos_URL_Placeholders = Demos_URL_Prefix + "/placeholders"; + public const string Demos_URL_Preload = Demos_URL_Prefix + "/preload"; + public const string Demos_URL_Progress = Demos_URL_Prefix + "/progress"; + public const string Demos_URL_Ribbon = Demos_URL_Prefix + "/ribbon"; + public const string Demos_URL_ScriptLoader = Demos_URL_Prefix + "/script-loader"; + public const string Demos_URL_Sidebar = Demos_URL_Prefix + "/sidebar"; + public const string Demos_URL_Sidebar2 = Demos_URL_Prefix + "/sidebar2"; + public const string Demos_URL_SplitView = Demos_URL_Prefix + "/split-view"; + public const string Demos_URL_SortableList = Demos_URL_Prefix + "/sortable-list"; + public const string Demos_URL_Spinners = Demos_URL_Prefix + "/spinners"; + public const string Demos_URL_Tabs = Demos_URL_Prefix + "/tabs"; + public const string Demos_URL_ThemeSwitcher = Demos_URL_Prefix + "/theme-switcher"; + public const string Demos_URL_Toasts = Demos_URL_Prefix + "/toasts"; + public const string Demos_URL_Tooltips = Demos_URL_Prefix + "/tooltips"; + + // Data Visualization + public const string Demos_URL_Charts_Prefix = Demos_URL_Prefix + "/charts"; + public const string Demos_URL_BarChart = Demos_URL_Charts_Prefix + "/bar-chart"; + public const string Demos_URL_BubbleChart = Demos_URL_Charts_Prefix + "/bubble-chart"; + public const string Demos_URL_DoughnutChart = Demos_URL_Charts_Prefix + "/doughnut-chart"; + public const string Demos_URL_LineChart = Demos_URL_Charts_Prefix + "/line-chart"; + public const string Demos_URL_PieChart = Demos_URL_Charts_Prefix + "/pie-chart"; + public const string Demos_URL_PolarAreaChart = Demos_URL_Charts_Prefix + "/polar-area-chart"; + public const string Demos_URL_RadarChart = Demos_URL_Charts_Prefix + "/radar-chart"; + public const string Demos_URL_ScatterChart = Demos_URL_Charts_Prefix + "/scatter-chart"; + + // Services + public const string Demos_URL_Services_Prefix = Demos_URL_Prefix + "/services"; + public const string Demos_URL_BreadcrumbService = Demos_URL_Services_Prefix + "/breadcrumb-service"; + public const string Demos_URL_ModalService = Demos_URL_Services_Prefix + "/modal-service"; + public const string Demos_URL_PreloadService = Demos_URL_Services_Prefix + "/preload-service"; + public const string Demos_URL_ToastService = Demos_URL_Services_Prefix + "/toast-service"; + + // Utilities + public const string Demos_URL_Utils_Prefix = Demos_URL_Prefix + "/utils"; + public const string Demos_URL_ColorUtils = Demos_URL_Utils_Prefix + "/color-utility"; + + #endregion Demos + + #region Docs + + // Getting Started + public const string Docs_URL_GettingStarted = Docs_URL_Prefix + "/getting-started"; + + // Layout + public const string Docs_URL_Layout = Docs_URL_Prefix + "/layout"; + + // AI + //public const string Docs_URL_AI_Prefix = Docs_URL_Prefix + "/ai"; + //public const string Docs_URL_AI_Chat = Docs_URL_Prefix + "/open-ai-chat"; + + // Content + public const string Docs_URL_Icons = Docs_URL_Prefix + "/icons"; + public const string Docs_URL_Images = Docs_URL_Prefix + "/images"; + + // Forms + public const string Docs_URL_Forms_Prefix = Docs_URL_Prefix + "/form"; + public const string Docs_URL_AutoComplete = Docs_URL_Forms_Prefix + "/autocomplete"; + public const string Docs_URL_CheckboxInput = Docs_URL_Forms_Prefix + "/checkbox-input"; + public const string Docs_URL_CurrencyInput = Docs_URL_Forms_Prefix + "/currency-input"; + public const string Docs_URL_DateInput = Docs_URL_Forms_Prefix + "/date-input"; + public const string Docs_URL_DragAndDropFileInput = Docs_URL_Forms_Prefix + "/drag-and-drop-file-input"; + public const string Docs_URL_EnumInput = Docs_URL_Forms_Prefix + "/enum-input"; + public const string Docs_URL_FileInput = Docs_URL_Forms_Prefix + "/file-input"; + public const string Docs_URL_NumberInput = Docs_URL_Forms_Prefix + "/number-input"; + public const string Docs_URL_OTPInput = Docs_URL_Forms_Prefix + "/otp-input"; + public const string Docs_URL_PasswordInput = Docs_URL_Forms_Prefix + "/password-input"; + public const string Docs_URL_RadioInput = Docs_URL_Forms_Prefix + "/radio-input"; + public const string Docs_URL_RangeInput = Docs_URL_Forms_Prefix + "/range-input"; + public const string Docs_URL_RichTextEditor = Docs_URL_Forms_Prefix + "/rich-text-editor"; + public const string Docs_URL_SelectInput = Docs_URL_Forms_Prefix + "/select-input"; + public const string Docs_URL_Switch = Docs_URL_Forms_Prefix + "/switch"; + public const string Docs_URL_TextInput = Docs_URL_Forms_Prefix + "/text-input"; + public const string Docs_URL_TextAreaInput = Docs_URL_Forms_Prefix + "/text-area-input"; + public const string Docs_URL_TimeInput = Docs_URL_Forms_Prefix + "/time-input"; + + // Components + public const string Docs_URL_Accordion = Docs_URL_Prefix + "/accordion"; + public const string Docs_URL_Alerts = Docs_URL_Prefix + "/alerts"; + public const string Docs_URL_Badge = Docs_URL_Prefix + "/badge"; + public const string Docs_URL_Breadcrumb = Docs_URL_Prefix + "/breadcrumb"; + public const string Docs_URL_Buttons = Docs_URL_Prefix + "/buttons"; + public const string Docs_URL_Callout = Docs_URL_Prefix + "/callout"; + public const string Docs_URL_Card = Docs_URL_Prefix + "/card"; + public const string Docs_URL_Carousel = Docs_URL_Prefix + "/carousel"; + public const string Docs_URL_Charts = Docs_URL_Prefix + "/charts"; + public const string Docs_URL_Collapse = Docs_URL_Prefix + "/collapse"; + public const string Docs_URL_ConfirmDialog = Docs_URL_Prefix + "/confirm-dialog"; + public const string Docs_URL_Dropdown = Docs_URL_Prefix + "/dropdown"; + public const string Docs_URL_GoogleMap = Docs_URL_Prefix + "/google-map"; + public const string Docs_URL_Grid = Docs_URL_Prefix + "/grid"; + public const string Docs_URL_Markdown = Docs_URL_Prefix + "/markdown"; + public const string Docs_URL_Modal = Docs_URL_Prefix + "/modals"; + public const string Docs_URL_Offcanvas = Docs_URL_Prefix + "/offcanvas"; + public const string Docs_URL_Pagination = Docs_URL_Prefix + "/pagination"; + public const string Docs_URL_PDFViewer = Docs_URL_Prefix + "/pdf-viewer"; + public const string Docs_URL_Placeholders = Docs_URL_Prefix + "/placeholders"; + public const string Docs_URL_Preload = Docs_URL_Prefix + "/preload"; + public const string Docs_URL_Progress = Docs_URL_Prefix + "/progress"; + public const string Docs_URL_Ribbon = Docs_URL_Prefix + "/ribbon"; + public const string Docs_URL_ScriptLoader = Docs_URL_Prefix + "/script-loader"; + public const string Docs_URL_Sidebar = Docs_URL_Prefix + "/sidebar"; + public const string Docs_URL_Sidebar2 = Docs_URL_Prefix + "/sidebar2"; + public const string Docs_URL_SplitView = Docs_URL_Prefix + "/split-view"; + public const string Docs_URL_SortableList = Docs_URL_Prefix + "/sortable-list"; + public const string Docs_URL_Spinners = Docs_URL_Prefix + "/spinners"; + public const string Docs_URL_Tabs = Docs_URL_Prefix + "/tabs"; + public const string Docs_URL_ThemeSwitcher = Docs_URL_Prefix + "/theme-switcher"; + public const string Docs_URL_Toasts = Docs_URL_Prefix + "/toasts"; + public const string Docs_URL_Tooltips = Docs_URL_Prefix + "/tooltips"; + + // Services + public const string Docs_URL_Services_Prefix = Docs_URL_Prefix + "/services"; + public const string Docs_URL_BreadcrumbService = Docs_URL_Services_Prefix + "/breadcrumb-service"; + public const string Docs_URL_ModalService = Docs_URL_Services_Prefix + "/modal-service"; + public const string Docs_URL_PreloadService = Docs_URL_Services_Prefix + "/preload-service"; + public const string Docs_URL_ToastService = Docs_URL_Services_Prefix + "/toast-service"; + + // Utilities + public const string Docs_URL_Utils_Prefix = Docs_URL_Prefix + "/utils"; + public const string Docs_URL_ColorUtils = Docs_URL_Utils_Prefix + "/color-utility"; + + #endregion Docs +} diff --git a/BlazorBootstrap.Demo.RCL/Constants/DemoScreenshotSrcConstants.cs b/BlazorBootstrap.Demo.RCL/Constants/DemoScreenshotSrcConstants.cs new file mode 100644 index 000000000..1a06c1222 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Constants/DemoScreenshotSrcConstants.cs @@ -0,0 +1,118 @@ +namespace BlazorBootstrap.Demo.RCL; + +public class DemoScreenshotSrcConstants +{ + #region Fields and Constants + + public const string DemoScreenshotSrcPrefix = $"{DemoStringConstants.StaticAssets_Images_Path}/screenshots/"; + + // Home + public const string Home = DemoScreenshotSrcPrefix + "home.png"; + + // Layout + public const string Demos_URL_Layout = DemoScreenshotSrcPrefix + "layout.png"; + + // Content + public const string Demos_URL_Icons = DemoScreenshotSrcPrefix + "icons.png"; + public const string Demos_URL_Images = DemoScreenshotSrcPrefix + "images.png"; + + // Forms + public const string Demos_URL_Forms_Prefix = DemoScreenshotSrcPrefix + "home.png"; + public const string Demos_URL_AutoComplete = DemoScreenshotSrcPrefix + "autocomplete.png"; + public const string Demos_URL_CheckboxInput = DemoScreenshotSrcPrefix + "checkbox-input.png"; + public const string Demos_URL_CurrencyInput = DemoScreenshotSrcPrefix + "currency-input.png"; + public const string Demos_URL_DateInput = DemoScreenshotSrcPrefix + "date-input.png"; + public const string Demos_URL_EnumInput = DemoScreenshotSrcPrefix + "enum-input.png"; // TODO: pending + public const string Demos_URL_DragAndDropFileInput = DemoScreenshotSrcPrefix + "drag-and-drop-file-input.png"; + public const string Demos_URL_NumberInput = DemoScreenshotSrcPrefix + "number-input.png"; + public const string Demos_URL_FileInput = DemoScreenshotSrcPrefix + "file-input.png"; + public const string Demos_URL_OTPInput = DemoScreenshotSrcPrefix + "otp-input.png"; + public const string Demos_URL_PasswordInput = DemoScreenshotSrcPrefix + "password-input.png"; + public const string Demos_URL_RadioInput = DemoScreenshotSrcPrefix + "radio-input.png"; + public const string Demos_URL_RangeInput = DemoScreenshotSrcPrefix + "range-input.png"; + public const string Demos_URL_SelectInput = DemoScreenshotSrcPrefix + "select-input.png"; + public const string Demos_URL_RichTextEditor = DemoScreenshotSrcPrefix + "rich-text-editor.png"; + public const string Demos_URL_Switch = DemoScreenshotSrcPrefix + "switch.png"; + public const string Demos_URL_TextAreaInput = DemoScreenshotSrcPrefix + "textarea-input.png"; + public const string Demos_URL_TextInput = DemoScreenshotSrcPrefix + "text-input.png"; + public const string Demos_URL_TimeInput = DemoScreenshotSrcPrefix + "time-input.png"; + + // Components + public const string Demos_URL_Accordion = DemoScreenshotSrcPrefix + "accordion.png"; + public const string Demos_URL_Alerts = DemoScreenshotSrcPrefix + "alerts.png"; + public const string Demos_URL_Badge = DemoScreenshotSrcPrefix + "badge.png"; + public const string Demos_URL_Breadcrumb = DemoScreenshotSrcPrefix + "breadcrumb.png"; + public const string Demos_URL_Buttons = DemoScreenshotSrcPrefix + "buttons.png"; + public const string Demos_URL_Callout = DemoScreenshotSrcPrefix + "callout.png"; + public const string Demos_URL_Card = DemoScreenshotSrcPrefix + "card.png"; + public const string Demos_URL_Carousel = DemoScreenshotSrcPrefix + "carousel.png"; + public const string Demos_URL_Charts = DemoScreenshotSrcPrefix + "charts.png"; + public const string Demos_URL_Collapse = DemoScreenshotSrcPrefix + "collapse.png"; + public const string Demos_URL_ConfirmDialog = DemoScreenshotSrcPrefix + "confirm-dialog.png"; + public const string Demos_URL_Dropdown = DemoScreenshotSrcPrefix + "dropdown.png"; + public const string Demos_URL_GoogleMap = DemoScreenshotSrcPrefix + "google-map.png"; + + #region Grid + public const string Demos_URL_Grid_Prefix = DemoScreenshotSrcPrefix + "grid.png"; + public const string Demos_URL_Grid_Overview = DemoScreenshotSrcPrefix + "grid_fixed_header_freeze_columns.png"; + public const string Demos_URL_Grid_Alignment = DemoScreenshotSrcPrefix + "home.png"; + public const string Demos_URL_Grid_CustomCSSClass = DemoScreenshotSrcPrefix + "home.png"; + public const string Demos_URL_Grid_DataBinding = DemoScreenshotSrcPrefix + "home.png"; + public const string Demos_URL_Grid_DetailView = DemoScreenshotSrcPrefix + "home.png"; + public const string Demos_URL_Grid_Events = DemoScreenshotSrcPrefix + "home.png"; + public const string Demos_URL_Grid_Filters = DemoScreenshotSrcPrefix + "home.png"; + public const string Demos_URL_Grid_FixedHeader = DemoScreenshotSrcPrefix + "grid_fixed_header_freeze_columns.png"; + public const string Demos_URL_Grid_FreezeColumns = DemoScreenshotSrcPrefix + "grid_fixed_header_freeze_columns.png"; + public const string Demos_URL_Grid_Settings = DemoScreenshotSrcPrefix + "home.png"; + public const string Demos_URL_Grid_NestedGrid = DemoScreenshotSrcPrefix + "home.png"; + public const string Demos_URL_Grid_Paging = DemoScreenshotSrcPrefix + "home.png"; + public const string Demos_URL_Grid_Selection = DemoScreenshotSrcPrefix + "home.png"; + public const string Demos_URL_Grid_Sorting = DemoScreenshotSrcPrefix + "home.png"; + public const string Demos_URL_Grid_Summary = DemoScreenshotSrcPrefix + "home.png"; + public const string Demos_URL_Grid_Translations = DemoScreenshotSrcPrefix + "home.png"; + public const string Demos_URL_Grid_OtherExamples = DemoScreenshotSrcPrefix + "home.png"; + #endregion Grid + + public const string Demos_URL_Markdown = DemoScreenshotSrcPrefix + "markdown.png"; + public const string Demos_URL_Modal = DemoScreenshotSrcPrefix + "modal.png"; + public const string Demos_URL_Offcanvas = DemoScreenshotSrcPrefix + "offcanvas.png"; + public const string Demos_URL_Pagination = DemoScreenshotSrcPrefix + "pagination.png"; + public const string Demos_URL_PDFViewer = DemoScreenshotSrcPrefix + "pdf-viewer.png"; + public const string Demos_URL_Placeholders = DemoScreenshotSrcPrefix + "placeholders.png"; + public const string Demos_URL_Preload = DemoScreenshotSrcPrefix + "preload.png"; + public const string Demos_URL_Progress = DemoScreenshotSrcPrefix + "progress.png"; + public const string Demos_URL_Ribbon = DemoScreenshotSrcPrefix + "ribbon.png"; + public const string Demos_URL_ScriptLoader = DemoScreenshotSrcPrefix + "script-loader.png"; + public const string Demos_URL_Sidebar = DemoScreenshotSrcPrefix + "sidebar.png"; + public const string Demos_URL_Sidebar2 = DemoScreenshotSrcPrefix + "sidebar2.png"; + public const string Demos_URL_SplitView = DemoScreenshotSrcPrefix + "split-view.png"; + public const string Demos_URL_SortableList = DemoScreenshotSrcPrefix + "sortable-list.png"; + public const string Demos_URL_Spinners = DemoScreenshotSrcPrefix + "spinners.png"; + public const string Demos_URL_Tabs = DemoScreenshotSrcPrefix + "tabs.png"; + public const string Demos_URL_ThemeSwitcher = DemoScreenshotSrcPrefix + "theme-switcher.png"; + public const string Demos_URL_Toasts = DemoScreenshotSrcPrefix + "toasts.png"; + public const string Demos_URL_Tooltips = DemoScreenshotSrcPrefix + "tooltips.png"; + + // Data Visualization + public const string Demos_URL_Charts_Prefix = DemoScreenshotSrcPrefix + "home.png"; + public const string Demos_URL_BarChart = DemoScreenshotSrcPrefix + "bar-chart.png"; + public const string Demos_URL_BubbleChart = DemoScreenshotSrcPrefix + "charts.png"; // TODO: add a dedicated screenshot + public const string Demos_URL_DoughnutChart = DemoScreenshotSrcPrefix + "doughnut-chart.png"; + public const string Demos_URL_LineChart = DemoScreenshotSrcPrefix + "line-chart.png"; + public const string Demos_URL_PieChart = DemoScreenshotSrcPrefix + "pie-chart.png"; + public const string Demos_URL_PolarAreaChart = DemoScreenshotSrcPrefix + "polar-area-chart.png"; + public const string Demos_URL_RadarChart = DemoScreenshotSrcPrefix + "radar-chart.png"; + public const string Demos_URL_ScatterChart = DemoScreenshotSrcPrefix + "scatter-chart.png"; + + // Services + public const string Demos_URL_Services_Prefix = DemoScreenshotSrcPrefix + "home.png"; // TODO: update screenshot + public const string Demos_URL_BreadcrumbService = DemoScreenshotSrcPrefix + "breadcrumb.png"; + public const string Demos_URL_ModalService = DemoScreenshotSrcPrefix + "modal.png"; + public const string Demos_URL_PreloadService = DemoScreenshotSrcPrefix + "preload.png"; + + // Utilities + public const string Demos_URL_Utils_Prefix = DemoScreenshotSrcPrefix + "home.png"; + public const string Demos_URL_ColorUtils = DemoScreenshotSrcPrefix + "home.png"; + + #endregion +} diff --git a/BlazorBootstrap.Demo.RCL/Constants/DemoStringConstants.cs b/BlazorBootstrap.Demo.RCL/Constants/DemoStringConstants.cs new file mode 100644 index 000000000..571e1a7ad --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Constants/DemoStringConstants.cs @@ -0,0 +1,25 @@ +namespace BlazorBootstrap.Demo.RCL; + +public static class DemoStringConstants +{ + #region Fields and Constants + + public const string NugetPackageName = "Blazor.Bootstrap"; + public const string NugetPackageDisplayName = "Blazor Bootstrap"; + + public const string PageTitle_Suffix = " | Blazor Bootstrap: An Enterprise-class Blazor Bootstrap Component library built on the Blazor and Bootstrap CSS frameworks."; + + public const string StaticAssets_RootPath = "_content/BlazorBootstrap.Demo.RCL"; + + public const string StaticAssets_Css_Path = StaticAssets_RootPath + "/css"; + public const string StaticAssets_JS_Path = StaticAssets_RootPath + "/js"; + + public const string StaticAssets_Docs_Path = StaticAssets_RootPath + "/docs"; + + public const string StaticAssets_Icons_Path = StaticAssets_RootPath + "/icons"; + public const string StaticAssets_Icons_Logo_png = StaticAssets_Icons_Path + "/logo.png"; + + public const string StaticAssets_Images_Path = StaticAssets_RootPath + "/images"; + + #endregion +} diff --git a/BlazorBootstrap.Demo.RCL/Constants/RouteConstants.cs b/BlazorBootstrap.Demo.RCL/Constants/RouteConstants.cs deleted file mode 100644 index bc6ddfca0..000000000 --- a/BlazorBootstrap.Demo.RCL/Constants/RouteConstants.cs +++ /dev/null @@ -1,105 +0,0 @@ -namespace BlazorBootstrap.Demo.RCL; - -public static class RouteConstants -{ - public const string Blog_Prefix = "/blog"; - public const string Docs_Prefix = "/docs"; - public const string Demos_Prefix = ""; - - #region Demos - - // Getting Started - public const string Demos_GettingStarted_Documentation = Demos_Prefix + "/getting-started"; - - // AI - public const string Demos_AI_Prefix = Demos_Prefix + "/ai"; - public const string Demos_AI_Chat_Documentation = Demos_AI_Prefix + "/open-ai-chat"; - - // Content - public const string Demos_Icons_Documentation = Demos_Prefix + "/icons"; - public const string Demos_Images_Documentation = Demos_Prefix + "/images"; - - // Forms - public const string Demos_Forms_Prefix = Demos_Prefix + "/form"; - public const string Demos_AutoComplete_Documentation = Demos_Forms_Prefix + "/autocomplete"; - public const string Demos_CurrencyInput_Documentation = Demos_Forms_Prefix + "/currency-input"; - public const string Demos_DateInput_Documentation = Demos_Forms_Prefix + "/date-input"; - public const string Demos_NumberInput_Documentation = Demos_Forms_Prefix + "/number-input"; - public const string Demos_RangeInput_Documentation = Demos_Forms_Prefix + "/range-input"; - public const string Demos_Switch_Documentation = Demos_Forms_Prefix + "/switch"; - public const string Demos_TimeInput_Documentation = Demos_Forms_Prefix + "/time-input"; - - // Components - public const string Demos_Accordion_Documentation = Demos_Prefix + "/accordion"; - public const string Demos_Alerts_Documentation = Demos_Prefix + "/alerts"; - public const string Demos_Badge_Documentation = Demos_Prefix + "/badge"; - public const string Demos_Breadcrumb_Documentation = Demos_Prefix + "/breadcrumb"; - public const string Demos_Buttons_Documentation = Demos_Prefix + "/buttons"; - public const string Demos_Callout_Documentation = Demos_Prefix + "/callout"; - public const string Demos_Card_Documentation = Demos_Prefix + "/card"; - public const string Demos_Carousel_Documentation = Demos_Prefix + "/carousel"; - public const string Demos_Charts_Documentation = Demos_Prefix + "/charts"; - public const string Demos_Collapse_Documentation = Demos_Prefix + "/collapse"; - public const string Demos_ConfirmDialog_Documentation = Demos_Prefix + "/confirm-dialog"; - public const string Demos_Dropdown_Documentation = Demos_Prefix + "/dropdown"; - public const string Demos_GoogleMap_Documentation = Demos_Prefix + "/google-map"; - - #region Grid - public const string Demos_Grid_Prefix = Demos_Prefix + "/grid"; - public const string Demos_Grid_Overview_Documentation = Demos_Grid_Prefix + "/overview"; - public const string Demos_Grid_Alignment_Documentation = Demos_Grid_Prefix + "/alignment"; - public const string Demos_Grid_CustomCSSClass_Documentation = Demos_Grid_Prefix + "/custom-css-class"; - public const string Demos_Grid_DataBinding_Documentation = Demos_Grid_Prefix + "/data-binding"; - public const string Demos_Grid_DetailView_Documentation = Demos_Grid_Prefix + "/detail-view"; - public const string Demos_Grid_Events_Documentation = Demos_Grid_Prefix + "/events"; - public const string Demos_Grid_Filters_Documentation = Demos_Grid_Prefix + "/filters"; - public const string Demos_Grid_FixedHeader_Documentation = Demos_Grid_Prefix + "/fixed-header"; - public const string Demos_Grid_FreezeColumns_Documentation = Demos_Grid_Prefix + "/freeze-columns"; - public const string Demos_Grid_Settings_Documentation = Demos_Grid_Prefix + "/settings"; - public const string Demos_Grid_NestedGrid_Documentation = Demos_Grid_Prefix + "/nested-grid"; - public const string Demos_Grid_Paging_Documentation = Demos_Grid_Prefix + "/paging"; - public const string Demos_Grid_Selection_Documentation = Demos_Grid_Prefix + "/selection"; - public const string Demos_Grid_Sorting_Documentation = Demos_Grid_Prefix + "/sorting"; - public const string Demos_Grid_Translations_Documentation = Demos_Grid_Prefix + "/translations"; - public const string Demos_Grid_OtherExamples_Documentation = Demos_Grid_Prefix + "/other"; - #endregion Grid - - public const string Demos_Markdown_Documentation = Demos_Prefix + "/markdown"; - public const string Demos_Modal_Documentation = Demos_Prefix + "/modals"; - public const string Demos_Offcanvas_Documentation = Demos_Prefix + "/offcanvas"; - public const string Demos_Pagination_Documentation = Demos_Prefix + "/pagination"; - public const string Demos_PDFViewer_Documentation = Demos_Prefix + "/pdf-viewer"; - public const string Demos_Placeholders_Documentation = Demos_Prefix + "/placeholders"; - public const string Demos_Preload_Documentation = Demos_Prefix + "/preload"; - public const string Demos_Progress_Documentation = Demos_Prefix + "/progress"; - public const string Demos_Ribbon_Documentation = Demos_Prefix + "/ribbon"; - public const string Demos_ScriptLoader_Documentation = Demos_Prefix + "/script-loader"; - public const string Demos_Sidebar_Documentation = Demos_Prefix + "/sidebar"; - public const string Demos_Sidebar2_Documentation = Demos_Prefix + "/sidebar2"; - public const string Demos_SortableList_Documentation = Demos_Prefix + "/sortable-list"; - public const string Demos_Spinners_Documentation = Demos_Prefix + "/spinners"; - public const string Demos_Tabs_Documentation = Demos_Prefix + "/tabs"; - public const string Demos_ThemeSwitcher_Documentation = Demos_Prefix + "/theme-switcher"; - public const string Demos_Toasts_Documentation = Demos_Prefix + "/toasts"; - public const string Demos_Tooltips_Documentation = Demos_Prefix + "/tooltips"; - - // Data Visualization - public const string Demos_Charts_Prefix = Demos_Prefix + "/charts"; - public const string Demos_BarChart_Documentation = Demos_Charts_Prefix + "/bar-chart"; - public const string Demos_DoughnutChart_Documentation = Demos_Charts_Prefix + "/doughnut-chart"; - public const string Demos_LineChart_Documentation = Demos_Charts_Prefix + "/line-chart"; - public const string Demos_PieChart_Documentation = Demos_Charts_Prefix + "/pie-chart"; - public const string Demos_PolarAreaChart_Documentation = Demos_Charts_Prefix + "/polar-area-chart"; - public const string Demos_RadarChart_Documentation = Demos_Charts_Prefix + "/radar-chart"; - public const string Demos_ScatterChart_Documentation = Demos_Charts_Prefix + "/scatter-chart"; - - // Services - public const string Demos_Services_Prefix = Demos_Prefix + "/services"; - public const string Demos_ModalService_Documentation = Demos_Services_Prefix + "/modal-service"; - - // Utilities - public const string Demos_Utils_Prefix = Demos_Prefix + "/utils"; - public const string Demos_ColorUtils_Documentation = Demos_Utils_Prefix + "/color-utility"; - - #endregion -} diff --git a/BlazorBootstrap.Demo.RCL/Enums/DocType.cs b/BlazorBootstrap.Demo.RCL/Enums/DocType.cs new file mode 100644 index 000000000..c20562e0c --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Enums/DocType.cs @@ -0,0 +1,11 @@ +namespace BlazorBootstrap.Demo.RCL; + +public enum DocType +{ + None, + Enum, + Events, + Methods, + Parameters, + Properties +} diff --git a/BlazorBootstrap.Demo.RCL/Enums/PageLinkCategory.cs b/BlazorBootstrap.Demo.RCL/Enums/PageLinkCategory.cs new file mode 100644 index 000000000..3c7a90ad2 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Enums/PageLinkCategory.cs @@ -0,0 +1,28 @@ +namespace BlazorBootstrap.Demo.RCL; + +public enum PageLinkCategory +{ + [Description("All")] + All, + + [Description("Getting Started")] + GettingStarted, + + [Description("Features")] + Features, + + [Description("Icons")] + Icons, + + [Description("Elements")] + Elements, + + [Description("Form")] + Form, + + [Description("Components")] + Components, + + [Description("Layout")] + Layout +} diff --git a/BlazorBootstrap.Demo.RCL/Enums/PageLinkStatus.cs b/BlazorBootstrap.Demo.RCL/Enums/PageLinkStatus.cs new file mode 100644 index 000000000..4778c7085 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Enums/PageLinkStatus.cs @@ -0,0 +1,8 @@ +namespace BlazorBootstrap.Demo.RCL; + +public enum PageLinkStatus +{ + None, + New, + Updated +} diff --git a/BlazorBootstrap.Demo.RCL/Extensions/MethodInfoExtensions.cs b/BlazorBootstrap.Demo.RCL/Extensions/MethodInfoExtensions.cs new file mode 100644 index 000000000..6c0534aa6 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Extensions/MethodInfoExtensions.cs @@ -0,0 +1,98 @@ +namespace BlazorBootstrap.Demo.RCL; + +/// +/// Extension methods for . +/// +/// +/// +/// +public static class MethodInfoExtensions +{ + private static readonly NullabilityInfoContext _nullabilityInfoContext = new(); + + /// + /// Get added version of a method. + /// + /// + /// + /// string + public static string GetMethodAddedVersion(this MethodInfo methodInfo) + { + var addedVersionAttribute = (AddedVersionAttribute?)Attribute.GetCustomAttribute(methodInfo, typeof(AddedVersionAttribute)); + return addedVersionAttribute?.Version ?? string.Empty; + } + + /// + /// Get the effective added version of a method using an optional docs context. + /// + /// + /// + /// string + public static string GetMethodAddedVersion(this MethodInfo methodInfo, Type? versionContextType) + { + var methodVersion = methodInfo.GetMethodAddedVersion(); + var contextVersion = versionContextType.GetTypeAddedVersion(); + + if (string.IsNullOrWhiteSpace(methodVersion)) + return contextVersion; + + if (string.IsNullOrWhiteSpace(contextVersion)) + return methodVersion; + + if (Version.TryParse(methodVersion, out var parsedMethodVersion) + && Version.TryParse(contextVersion, out var parsedContextVersion)) + return parsedMethodVersion >= parsedContextVersion ? methodVersion : contextVersion; + + return methodVersion; + } + + /// + /// Get method description. + /// + /// + /// + /// string + public static string GetMethodDescription(this MethodInfo methodInfo) + { + var descriptionAttribute = (DescriptionAttribute?)Attribute.GetCustomAttribute(methodInfo, typeof(DescriptionAttribute)); + return descriptionAttribute?.Description ?? string.Empty; + } + + /// + /// Get method name. + /// + /// + /// string + public static string GetMethodName(this MethodInfo methodInfo) + { + var parameters = methodInfo.GetParameters(); + var parameterStrings = parameters.Select(p => + { + var paramNullabilityInfo = _nullabilityInfoContext.Create(p); + return $"{paramNullabilityInfo.GetFriendlyTypeName()} {p.Name}"; + }); + + return $"{methodInfo.Name}({string.Join(", ", parameterStrings)})"; + } + + /// + /// Get method return type. + /// + /// + /// + /// string + public static string GetMethodReturnType(this MethodInfo methodInfo) + { + var nullabilityInfo = _nullabilityInfoContext.Create(methodInfo.ReturnParameter); + return nullabilityInfo.GetFriendlyTypeName(); + } + + private static string GetTypeAddedVersion(this Type? type) + { + if (type is null) + return string.Empty; + + var addedVersionAttribute = (AddedVersionAttribute?)Attribute.GetCustomAttribute(type, typeof(AddedVersionAttribute)); + return addedVersionAttribute?.Version ?? string.Empty; + } +} diff --git a/BlazorBootstrap.Demo.RCL/Extensions/NullabilityInfoExtensions.cs b/BlazorBootstrap.Demo.RCL/Extensions/NullabilityInfoExtensions.cs new file mode 100644 index 000000000..53d25fc25 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Extensions/NullabilityInfoExtensions.cs @@ -0,0 +1,72 @@ +namespace BlazorBootstrap.Demo.RCL; + +/// +/// Extension methods for . +/// These methods help in getting friendly type names considering nullability and generics. +/// +public static class NullabilityInfoExtensions +{ + public static string GetFriendlyTypeName(this NullabilityInfo info) + { + if (info.Type.IsGenericType && info.Type.GetGenericTypeDefinition() == typeof(Nullable<>)) + { + var underlyingType = Nullable.GetUnderlyingType(info.Type); + return $"{underlyingType?.GetCSharpTypeName()}?"; + } + + var type = info.Type; + string typeName; + + if (IsTuple(type)) + { + var genericArgs = info.GenericTypeArguments.Select(GetFriendlyTypeName); + typeName = $"({string.Join(", ", genericArgs)})"; + } + else if (info.Type.IsGenericType) + { + if (type.GetGenericTypeDefinition() == typeof(EventHandler<>)) + { + var genericArg = info.GenericTypeArguments.Select(GetFriendlyTypeName); + typeName = $"EventHandler<{string.Join(", ", genericArg)}>"; + } + else + { + var genericTypeName = info.Type.Name; + var backtickIndex = genericTypeName.IndexOf('`'); + if (backtickIndex > 0) + { + genericTypeName = genericTypeName.Remove(backtickIndex); + } + var genericArgs = info.GenericTypeArguments.Select(GetFriendlyTypeName); + typeName = $"{genericTypeName}<{string.Join(", ", genericArgs)}>"; + } + } + else + { + typeName = info.Type.GetCSharpTypeName(); + } + + if (info.ReadState == NullabilityState.Nullable && info.Type.IsValueType == false) + { + typeName += "?"; + } + + return typeName; + } + + private static bool IsTuple(Type type) + { + if (!type.IsGenericType) + return false; + + var genericTypeDefinition = type.GetGenericTypeDefinition(); + return genericTypeDefinition == typeof(ValueTuple<>) || + genericTypeDefinition == typeof(ValueTuple<,>) || + genericTypeDefinition == typeof(ValueTuple<,,>) || + genericTypeDefinition == typeof(ValueTuple<,,,>) || + genericTypeDefinition == typeof(ValueTuple<,,,,>) || + genericTypeDefinition == typeof(ValueTuple<,,,,,>) || + genericTypeDefinition == typeof(ValueTuple<,,,,,,>) || + genericTypeDefinition == typeof(ValueTuple<,,,,,,,>); + } +} diff --git a/BlazorBootstrap.Demo.RCL/Extensions/PropertyInfoExtenstions.cs b/BlazorBootstrap.Demo.RCL/Extensions/PropertyInfoExtenstions.cs new file mode 100644 index 000000000..e199cc3fc --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Extensions/PropertyInfoExtenstions.cs @@ -0,0 +1,160 @@ +namespace BlazorBootstrap.Demo.RCL; + +/// +/// Extension methods for . +/// +/// +/// +/// +public static class PropertyInfoExtenstions +{ + private static readonly NullabilityInfoContext _nullabilityInfoContext = new(); + + /// + /// Get event callback return type. + /// + /// + /// Returns list of component event callbacks. + public static string GetEventCallbackReturnType(this PropertyInfo propertyInfo) + { + HashSet arguments = new(); + if (propertyInfo.PropertyType.IsGenericType) + { + Type[] genericArguments = propertyInfo.PropertyType.GetGenericArguments(); + if (genericArguments.Length > 0) + { + foreach (Type genericArgument in genericArguments) + arguments.Add(genericArgument.GetCSharpTypeName()); + } + } + + return arguments.Count > 0 ? $"EventCallback<{string.Join(",", arguments)}>" : "EventCallback"; + } + + /// + /// Get parameter type name. + /// + /// + /// string + public static string GetParameterTypeName(this PropertyInfo propertyInfo) + { + var nullabilityInfo = _nullabilityInfoContext.Create(propertyInfo); + var typeName = nullabilityInfo.GetFriendlyTypeName(); + return typeName; + } + + /// + /// Get added version of a property. + /// + /// + /// string + public static string GetPropertyAddedVersion(this PropertyInfo propertyInfo) + { + var addedVersionAttribute = (AddedVersionAttribute?)Attribute.GetCustomAttribute(propertyInfo, typeof(AddedVersionAttribute)); + return addedVersionAttribute?.Version ?? string.Empty; + } + + /// + /// Get the effective added version of a property using an optional docs context and overrides. + /// + /// + /// + /// + /// string + public static string GetPropertyAddedVersion(this PropertyInfo propertyInfo, Type? versionContextType, IReadOnlyDictionary? addedVersionOverrides = null) + { + if (addedVersionOverrides is not null && addedVersionOverrides.TryGetValue(propertyInfo.Name, out var overrideVersion)) + return overrideVersion; + + var propertyVersion = propertyInfo.GetPropertyAddedVersion(); + var contextVersion = versionContextType.GetTypeAddedVersion(); + + return GetEffectiveAddedVersion(propertyVersion, contextVersion); + } + + /// + /// Get default value of a property. + /// + /// + /// string + public static string GetPropertyDefaultValue(this PropertyInfo propertyInfo) + { + var defaultValueAttribute = (DefaultValueAttribute?)Attribute.GetCustomAttribute(propertyInfo, typeof(DefaultValueAttribute)); + return defaultValueAttribute?.Value?.ToString() ?? "null"; + } + + /// + /// Get property description. + /// + /// + /// string + public static string GetPropertyDescription(this PropertyInfo propertyInfo) + { + var descriptionAttribute = (DescriptionAttribute?)Attribute.GetCustomAttribute(propertyInfo, typeof(DescriptionAttribute)); + return descriptionAttribute?.Description ?? string.Empty; + } + + /// + /// Determines whether the specified property is an EventCallback or EventCallback<T>. + /// + /// + /// bool + /// + public static bool IsEventCallbackProperty(this PropertyInfo propertyInfo) + { + if (propertyInfo == null) + { + throw new ArgumentNullException(nameof(propertyInfo)); + } + + // Check for EventCallback + if (propertyInfo.PropertyType == typeof(EventCallback)) + { + return true; + } + + // Check for EventCallback + if (propertyInfo.PropertyType.IsGenericType && + propertyInfo.PropertyType.GetGenericTypeDefinition() == typeof(EventCallback<>)) + { + return true; + } + + return false; + } + + /// + /// Returns true if the property is required. Otherwise, false. + /// + /// + /// bool + public static bool IsPropertyRequired(this PropertyInfo propertyInfo) + { + var editorRequiredAttribute = (EditorRequiredAttribute?)Attribute.GetCustomAttribute(propertyInfo, typeof(EditorRequiredAttribute)); + return editorRequiredAttribute is not null; + } + + private static string GetEffectiveAddedVersion(string propertyVersion, string contextVersion) + { + if (string.IsNullOrWhiteSpace(propertyVersion)) + return contextVersion; + + if (string.IsNullOrWhiteSpace(contextVersion)) + return propertyVersion; + + if (Version.TryParse(propertyVersion, out var parsedPropertyVersion) + && Version.TryParse(contextVersion, out var parsedContextVersion)) + return parsedPropertyVersion >= parsedContextVersion ? propertyVersion : contextVersion; + + return propertyVersion; + } + + private static string GetTypeAddedVersion(this Type? type) + { + if (type is null) + return string.Empty; + + var addedVersionAttribute = (AddedVersionAttribute?)Attribute.GetCustomAttribute(type, typeof(AddedVersionAttribute)); + return addedVersionAttribute?.Version ?? string.Empty; + } +} \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Extensions/TypeExtensions.cs b/BlazorBootstrap.Demo.RCL/Extensions/TypeExtensions.cs new file mode 100644 index 000000000..11796107a --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Extensions/TypeExtensions.cs @@ -0,0 +1,174 @@ +namespace BlazorBootstrap.Demo.RCL; + +/// +/// Extension methods for . +/// +/// +/// +/// +public static class TypeExtensions +{ + #region Methods + + /// + /// Get component parameters. + /// + /// + /// Returns list of component parameters + private static IEnumerable? GetComponentParameters(this Type type) + { + if (type is null) + return null; + + var properties = type.GetProperties(); + return properties?.Where(p => p.GetCustomAttributes(typeof(ParameterAttribute), false).Any())?.OrderBy(p => p.Name); + } + + /// + /// Get component parameters and excludes event callbacks. + /// + /// + /// Returns list of component parameters + public static HashSet GetComponentParametersOnly(this Type type) + { + var parameters = type.GetComponentParameters(); + if (parameters is null) + return new HashSet(); + + return parameters + .Where(p => !p.IsEventCallbackProperty()) + .ToHashSet(); + } + + /// + /// Get component event callbacks. + /// + /// + /// Returns list of component event callbacks. + public static HashSet GetComponentEventCallbacks(this Type type) + { + HashSet eventCallbacks = new(); + + var parameters = type.GetComponentParameters(); + if (parameters is null) + return new HashSet(); + + return parameters + .Where(p => p.IsEventCallbackProperty()) + .ToHashSet(); + } + + /// + /// Get component methods. + /// + /// + /// Returns list of component methods. + public static HashSet GetComponentMethods(this Type type) + { + var methods = new HashSet(); + + var includeChartComponentBaseMethods = typeof(BlazorExpress.ChartJS.ChartComponentBase).IsAssignableFrom(type); + + foreach (MethodInfo method in type.GetMethods(BindingFlags.Public | BindingFlags.Instance)) + { + var isChartComponentBaseMethod = includeChartComponentBaseMethods && method.DeclaringType == typeof(BlazorExpress.ChartJS.ChartComponentBase); + var isDocumentedChartClickHandler = isChartComponentBaseMethod && method.Name == nameof(BlazorExpress.ChartJS.ChartComponentBase.HandleClickAsync); + + // Filter out methods inherited from System.Object (if needed) + if (method.DeclaringType != typeof(object) + && (method.DeclaringType == type + || isChartComponentBaseMethod) + && !method.Name.StartsWith("get_") // Exclude get_ methods + && !method.Name.StartsWith("set_") // Exclude set_ methods + && (!method.GetCustomAttributes(typeof(JSInvokableAttribute), false).Any() || isDocumentedChartClickHandler)) // Exclude methods that are not general public methods + { + methods.Add(method); + } + } + + return methods.ToHashSet(); + } + + /// + /// Get property type name. + /// + /// + /// + /// string + public static string GetCSharpTypeName(this Type type) + { + if (type is null) + return string.Empty; + + var typeName = type.Name; + + if (typeName.Contains(StringConstants.PropertyTypeNameInt16, StringComparison.InvariantCulture)) + typeName = StringConstants.PropertyTypeNameInt16CSharpTypeKeyword; + + else if (typeName.Contains(StringConstants.PropertyTypeNameInt32, StringComparison.InvariantCulture)) + typeName = StringConstants.PropertyTypeNameInt32CSharpTypeKeyword; + + else if (typeName.Contains(StringConstants.PropertyTypeNameInt64, StringComparison.InvariantCulture)) + typeName = StringConstants.PropertyTypeNameInt64CSharpTypeKeyword; + + else if (typeName.Contains(StringConstants.PropertyTypeNameChar, StringComparison.InvariantCulture)) + typeName = StringConstants.PropertyTypeNameCharCSharpTypeKeyword; + + else if (typeName.Contains(StringConstants.PropertyTypeNameStringComparison, StringComparison.InvariantCulture)) + typeName = StringConstants.PropertyTypeNameStringComparisonCSharpTypeKeyword; + + else if (typeName.Contains(StringConstants.PropertyTypeNameString, StringComparison.InvariantCulture)) + typeName = StringConstants.PropertyTypeNameStringCSharpTypeKeyword; + + else if (typeName.Contains(StringConstants.PropertyTypeNameSingle, StringComparison.InvariantCulture)) // float + typeName = StringConstants.PropertyTypeNameSingleCSharpTypeKeyword; + + else if (typeName.Contains(StringConstants.PropertyTypeNameDecimal, StringComparison.InvariantCulture)) + typeName = StringConstants.PropertyTypeNameDecimalCSharpTypeKeyword; + + else if (typeName.Contains(StringConstants.PropertyTypeNameDouble, StringComparison.InvariantCulture)) + typeName = StringConstants.PropertyTypeNameDoubleCSharpTypeKeyword; + + else if (typeName.Contains(StringConstants.PropertyTypeNameDateOnly, StringComparison.InvariantCulture)) + typeName = StringConstants.PropertyTypeNameDateOnlyCSharpTypeKeyword; + + else if (typeName.Contains(StringConstants.PropertyTypeNameDateTime, StringComparison.InvariantCulture)) + typeName = StringConstants.PropertyTypeNameDateTimeCSharpTypeKeyword; + + else if (typeName.Contains(StringConstants.PropertyTypeNameBoolean, StringComparison.InvariantCulture)) + typeName = StringConstants.PropertyTypeNameBooleanCSharpTypeKeyword; + + //else if (propertyType!.IsEnum) + // propertyTypeName = StringConstants.PropertyTypeNameEnumCSharpTypeKeyword; + + else if (typeName.Contains(StringConstants.PropertyTypeNameGuid, StringComparison.InvariantCulture)) + typeName = StringConstants.PropertyTypeNameGuidCSharpTypeKeyword; + + else if (typeName.Contains(StringConstants.PropertyTypeNameObject, StringComparison.InvariantCulture)) + typeName = StringConstants.PropertyTypeNameObjectCSharpTypeKeyword; + + else if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(IEnumerable<>)) + { + Type enumerableType = type.GetGenericArguments()[0]; // Get the T in IEnumerable + typeName = $"IEnumerable<{enumerableType.Name}>"; + } + + return typeName; + } + + /// + /// Get model properties. + /// + /// + /// Returns list of model properties + public static IEnumerable GetModelProperties(this Type type) + { + if (type is null) + return Enumerable.Empty(); + + var properties = type.GetProperties(); + return properties?.OrderBy(p => p.Name) ?? Enumerable.Empty(); + } + + #endregion +} diff --git a/BlazorBootstrap.Demo.RCL/Usings.cs b/BlazorBootstrap.Demo.RCL/Usings.cs index dcf504199..f9a5810be 100644 --- a/BlazorBootstrap.Demo.RCL/Usings.cs +++ b/BlazorBootstrap.Demo.RCL/Usings.cs @@ -6,5 +6,7 @@ global using Microsoft.Extensions.Configuration; global using Microsoft.Extensions.DependencyInjection; global using Microsoft.JSInterop; +global using System.ComponentModel; global using System.Linq.Expressions; global using System.Net.Http.Json; +global using System.Reflection; diff --git a/BlazorBootstrap.Demo.RCL/_Imports.razor b/BlazorBootstrap.Demo.RCL/_Imports.razor index 3bf195e4f..870477c55 100644 --- a/BlazorBootstrap.Demo.RCL/_Imports.razor +++ b/BlazorBootstrap.Demo.RCL/_Imports.razor @@ -1,4 +1,4 @@ -@using System.Net.Http +@using System.Net.Http @using System.Net.Http.Json @using Microsoft.AspNetCore.Components.Forms @using Microsoft.AspNetCore.Components.Routing @@ -8,5 +8,6 @@ @using BlazorBootstrap @using System.Threading.Tasks @using Microsoft.Extensions.Configuration; +@using BlazorBootstrap.Demo.RCL.Components.Shared @using BlazorBootstrap.Demo.RCL.Models; @using BlazorBootstrap.Demo.RCL.Services; diff --git a/BlazorBootstrap.Demo.RCL/wwwroot/css/blazorbootstrap.demo.rcl.css b/BlazorBootstrap.Demo.RCL/wwwroot/css/blazorbootstrap.demo.rcl.css index bfde67c9d..f69fe503f 100644 --- a/BlazorBootstrap.Demo.RCL/wwwroot/css/blazorbootstrap.demo.rcl.css +++ b/BlazorBootstrap.Demo.RCL/wwwroot/css/blazorbootstrap.demo.rcl.css @@ -177,10 +177,10 @@ h1:focus-visible { background-color: transparent } -.bd-masthead #carbonads { +/*.bd-masthead #carbonads { margin-right: auto; margin-left: auto -} +}*/ @media (min-width: 768px) { .bd-masthead .lead { @@ -404,7 +404,7 @@ pre[class*=language-] { } /* carbon ads */ -#carbonads { +/*#carbonads { position: static; display: block; max-width: 400px; @@ -437,7 +437,7 @@ pre[class*=language-] { display: block; margin-top: .75rem; color: var(--bs-body-color) !important -} +}*/ .bg-body-tertiary { --bs-bg-opacity: 1; diff --git a/BlazorBootstrap.Demo.RCL/wwwroot/docs/pdf_password_protected.pdf b/BlazorBootstrap.Demo.RCL/wwwroot/docs/pdf_password_protected.pdf new file mode 100644 index 000000000..9c8652248 Binary files /dev/null and b/BlazorBootstrap.Demo.RCL/wwwroot/docs/pdf_password_protected.pdf differ diff --git a/BlazorBootstrap.Demo.RCL/wwwroot/images/slide-01.png b/BlazorBootstrap.Demo.RCL/wwwroot/images/carousel/slide-01.png similarity index 100% rename from BlazorBootstrap.Demo.RCL/wwwroot/images/slide-01.png rename to BlazorBootstrap.Demo.RCL/wwwroot/images/carousel/slide-01.png diff --git a/BlazorBootstrap.Demo.RCL/wwwroot/images/slide-02.png b/BlazorBootstrap.Demo.RCL/wwwroot/images/carousel/slide-02.png similarity index 100% rename from BlazorBootstrap.Demo.RCL/wwwroot/images/slide-02.png rename to BlazorBootstrap.Demo.RCL/wwwroot/images/carousel/slide-02.png diff --git a/BlazorBootstrap.Demo.RCL/wwwroot/images/slide-03.png b/BlazorBootstrap.Demo.RCL/wwwroot/images/carousel/slide-03.png similarity index 100% rename from BlazorBootstrap.Demo.RCL/wwwroot/images/slide-03.png rename to BlazorBootstrap.Demo.RCL/wwwroot/images/carousel/slide-03.png diff --git a/BlazorBootstrap.Demo.RCL/wwwroot/images/slide-04.png b/BlazorBootstrap.Demo.RCL/wwwroot/images/carousel/slide-04.png similarity index 100% rename from BlazorBootstrap.Demo.RCL/wwwroot/images/slide-04.png rename to BlazorBootstrap.Demo.RCL/wwwroot/images/carousel/slide-04.png diff --git a/BlazorBootstrap.Demo.RCL/wwwroot/images/slide-05.png b/BlazorBootstrap.Demo.RCL/wwwroot/images/carousel/slide-05.png similarity index 100% rename from BlazorBootstrap.Demo.RCL/wwwroot/images/slide-05.png rename to BlazorBootstrap.Demo.RCL/wwwroot/images/carousel/slide-05.png diff --git a/BlazorBootstrap.Demo.RCL/wwwroot/images/slide-06.png b/BlazorBootstrap.Demo.RCL/wwwroot/images/carousel/slide-06.png similarity index 100% rename from BlazorBootstrap.Demo.RCL/wwwroot/images/slide-06.png rename to BlazorBootstrap.Demo.RCL/wwwroot/images/carousel/slide-06.png diff --git a/BlazorBootstrap.Demo.RCL/wwwroot/images/demos_logo_bw.png b/BlazorBootstrap.Demo.RCL/wwwroot/images/demos_logo_bw.png new file mode 100644 index 000000000..d6870b4be Binary files /dev/null and b/BlazorBootstrap.Demo.RCL/wwwroot/images/demos_logo_bw.png differ diff --git a/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/accordion.png b/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/accordion.png new file mode 100644 index 000000000..f0f46da91 Binary files /dev/null and b/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/accordion.png differ diff --git a/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/alerts.png b/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/alerts.png new file mode 100644 index 000000000..efb715f06 Binary files /dev/null and b/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/alerts.png differ diff --git a/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/autocomplete.png b/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/autocomplete.png new file mode 100644 index 000000000..545bbd133 Binary files /dev/null and b/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/autocomplete.png differ diff --git a/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/badge.png b/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/badge.png new file mode 100644 index 000000000..72c3ff794 Binary files /dev/null and b/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/badge.png differ diff --git a/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/bar-chart.png b/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/bar-chart.png new file mode 100644 index 000000000..2c1c39fac Binary files /dev/null and b/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/bar-chart.png differ diff --git a/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/breadcrumb.png b/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/breadcrumb.png new file mode 100644 index 000000000..ec0b856d3 Binary files /dev/null and b/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/breadcrumb.png differ diff --git a/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/buttons.png b/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/buttons.png new file mode 100644 index 000000000..bda5bf98a Binary files /dev/null and b/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/buttons.png differ diff --git a/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/callout.png b/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/callout.png new file mode 100644 index 000000000..cf88b4ee6 Binary files /dev/null and b/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/callout.png differ diff --git a/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/card.png b/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/card.png new file mode 100644 index 000000000..c4d107c01 Binary files /dev/null and b/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/card.png differ diff --git a/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/carousel.png b/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/carousel.png new file mode 100644 index 000000000..241da0ad9 Binary files /dev/null and b/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/carousel.png differ diff --git a/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/charts.png b/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/charts.png new file mode 100644 index 000000000..8f1db5e6e Binary files /dev/null and b/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/charts.png differ diff --git a/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/checkbox-input.png b/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/checkbox-input.png new file mode 100644 index 000000000..436c78caa Binary files /dev/null and b/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/checkbox-input.png differ diff --git a/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/collapse.png b/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/collapse.png new file mode 100644 index 000000000..98beb2cc1 Binary files /dev/null and b/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/collapse.png differ diff --git a/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/confirm-dialog.png b/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/confirm-dialog.png new file mode 100644 index 000000000..41682ab0e Binary files /dev/null and b/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/confirm-dialog.png differ diff --git a/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/currency-input.png b/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/currency-input.png new file mode 100644 index 000000000..2dfa864a2 Binary files /dev/null and b/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/currency-input.png differ diff --git a/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/date-input.png b/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/date-input.png new file mode 100644 index 000000000..9f3fa7398 Binary files /dev/null and b/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/date-input.png differ diff --git a/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/doughnut-chart.png b/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/doughnut-chart.png new file mode 100644 index 000000000..8cd9b2ef1 Binary files /dev/null and b/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/doughnut-chart.png differ diff --git a/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/drag-and-drop-file-input.png b/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/drag-and-drop-file-input.png new file mode 100644 index 000000000..1e6c110b9 Binary files /dev/null and b/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/drag-and-drop-file-input.png differ diff --git a/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/dropdown.png b/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/dropdown.png new file mode 100644 index 000000000..01d7020c0 Binary files /dev/null and b/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/dropdown.png differ diff --git a/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/enum-input.png b/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/enum-input.png new file mode 100644 index 000000000..c6695200b Binary files /dev/null and b/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/enum-input.png differ diff --git a/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/file-input.png b/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/file-input.png new file mode 100644 index 000000000..a4f35123d Binary files /dev/null and b/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/file-input.png differ diff --git a/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/google-map.png b/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/google-map.png new file mode 100644 index 000000000..48fc66e0d Binary files /dev/null and b/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/google-map.png differ diff --git a/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/grid.png b/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/grid.png new file mode 100644 index 000000000..1f4e0856a Binary files /dev/null and b/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/grid.png differ diff --git a/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/grid_detail_view.png b/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/grid_detail_view.png new file mode 100644 index 000000000..1cb9b96fb Binary files /dev/null and b/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/grid_detail_view.png differ diff --git a/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/grid_fixed_header_freeze_columns.png b/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/grid_fixed_header_freeze_columns.png new file mode 100644 index 000000000..a81ce0b07 Binary files /dev/null and b/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/grid_fixed_header_freeze_columns.png differ diff --git a/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/grid_nested_grid.png b/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/grid_nested_grid.png new file mode 100644 index 000000000..0a16e7d3c Binary files /dev/null and b/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/grid_nested_grid.png differ diff --git a/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/grid_translations.png b/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/grid_translations.png new file mode 100644 index 000000000..bdba45fef Binary files /dev/null and b/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/grid_translations.png differ diff --git a/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/icons.png b/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/icons.png new file mode 100644 index 000000000..89ced596f Binary files /dev/null and b/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/icons.png differ diff --git a/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/images.png b/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/images.png new file mode 100644 index 000000000..8de975864 Binary files /dev/null and b/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/images.png differ diff --git a/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/layout.png b/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/layout.png new file mode 100644 index 000000000..b8c659b22 Binary files /dev/null and b/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/layout.png differ diff --git a/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/line-chart.png b/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/line-chart.png new file mode 100644 index 000000000..c42df2310 Binary files /dev/null and b/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/line-chart.png differ diff --git a/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/markdown.png b/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/markdown.png new file mode 100644 index 000000000..ca6f924f9 Binary files /dev/null and b/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/markdown.png differ diff --git a/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/modal.png b/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/modal.png new file mode 100644 index 000000000..23b948e05 Binary files /dev/null and b/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/modal.png differ diff --git a/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/number-input.png b/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/number-input.png new file mode 100644 index 000000000..a533ce24a Binary files /dev/null and b/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/number-input.png differ diff --git a/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/offcanvas.png b/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/offcanvas.png new file mode 100644 index 000000000..7236c17e6 Binary files /dev/null and b/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/offcanvas.png differ diff --git a/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/otp-input.png b/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/otp-input.png new file mode 100644 index 000000000..8b5ce98e2 Binary files /dev/null and b/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/otp-input.png differ diff --git a/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/pagination.png b/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/pagination.png new file mode 100644 index 000000000..7d71adf59 Binary files /dev/null and b/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/pagination.png differ diff --git a/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/password-input.png b/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/password-input.png new file mode 100644 index 000000000..374a7be9f Binary files /dev/null and b/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/password-input.png differ diff --git a/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/pdf-viewer.png b/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/pdf-viewer.png new file mode 100644 index 000000000..2e75a95ae Binary files /dev/null and b/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/pdf-viewer.png differ diff --git a/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/pie-chart.png b/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/pie-chart.png new file mode 100644 index 000000000..39dfc818d Binary files /dev/null and b/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/pie-chart.png differ diff --git a/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/placeholders.png b/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/placeholders.png new file mode 100644 index 000000000..ac87984bf Binary files /dev/null and b/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/placeholders.png differ diff --git a/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/polar-area-chart.png b/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/polar-area-chart.png new file mode 100644 index 000000000..67f08d6f2 Binary files /dev/null and b/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/polar-area-chart.png differ diff --git a/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/preload.png b/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/preload.png new file mode 100644 index 000000000..65b3a1eef Binary files /dev/null and b/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/preload.png differ diff --git a/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/progress.png b/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/progress.png new file mode 100644 index 000000000..83f611412 Binary files /dev/null and b/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/progress.png differ diff --git a/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/radar-chart.png b/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/radar-chart.png new file mode 100644 index 000000000..85167ee13 Binary files /dev/null and b/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/radar-chart.png differ diff --git a/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/radio-input.png b/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/radio-input.png new file mode 100644 index 000000000..b72bcac42 Binary files /dev/null and b/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/radio-input.png differ diff --git a/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/range-input.png b/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/range-input.png new file mode 100644 index 000000000..4b6809a2e Binary files /dev/null and b/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/range-input.png differ diff --git a/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/ribbon.png b/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/ribbon.png new file mode 100644 index 000000000..e2ab0723f Binary files /dev/null and b/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/ribbon.png differ diff --git a/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/rich-text-editor.png b/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/rich-text-editor.png new file mode 100644 index 000000000..8360c9f60 Binary files /dev/null and b/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/rich-text-editor.png differ diff --git a/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/scatter-chart.png b/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/scatter-chart.png new file mode 100644 index 000000000..8b1433c34 Binary files /dev/null and b/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/scatter-chart.png differ diff --git a/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/script-loader.png b/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/script-loader.png new file mode 100644 index 000000000..835de63ed Binary files /dev/null and b/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/script-loader.png differ diff --git a/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/sidebar.png b/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/sidebar.png new file mode 100644 index 000000000..46f9d27a5 Binary files /dev/null and b/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/sidebar.png differ diff --git a/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/sidebar2.png b/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/sidebar2.png new file mode 100644 index 000000000..67bd47c44 Binary files /dev/null and b/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/sidebar2.png differ diff --git a/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/sortable-list.png b/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/sortable-list.png new file mode 100644 index 000000000..abd0fbe42 Binary files /dev/null and b/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/sortable-list.png differ diff --git a/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/spinners.png b/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/spinners.png new file mode 100644 index 000000000..b4e2f8d59 Binary files /dev/null and b/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/spinners.png differ diff --git a/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/split-view.png b/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/split-view.png new file mode 100644 index 000000000..5b7cc12b7 Binary files /dev/null and b/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/split-view.png differ diff --git a/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/switch.png b/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/switch.png new file mode 100644 index 000000000..7d6769720 Binary files /dev/null and b/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/switch.png differ diff --git a/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/tabs.png b/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/tabs.png new file mode 100644 index 000000000..440620447 Binary files /dev/null and b/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/tabs.png differ diff --git a/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/text-input.png b/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/text-input.png new file mode 100644 index 000000000..f3fb7c0b4 Binary files /dev/null and b/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/text-input.png differ diff --git a/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/textarea-input.png b/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/textarea-input.png new file mode 100644 index 000000000..890fc7886 Binary files /dev/null and b/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/textarea-input.png differ diff --git a/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/theme-switcher.png b/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/theme-switcher.png new file mode 100644 index 000000000..41bc8c80d Binary files /dev/null and b/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/theme-switcher.png differ diff --git a/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/time-input.png b/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/time-input.png new file mode 100644 index 000000000..24ea2aaf7 Binary files /dev/null and b/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/time-input.png differ diff --git a/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/toasts.png b/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/toasts.png new file mode 100644 index 000000000..3a953ea09 Binary files /dev/null and b/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/toasts.png differ diff --git a/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/tooltips.png b/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/tooltips.png new file mode 100644 index 000000000..1f5982c39 Binary files /dev/null and b/BlazorBootstrap.Demo.RCL/wwwroot/images/screenshots/tooltips.png differ diff --git a/BlazorBootstrap.Demo.Server/BlazorBootstrap.Demo.Server.csproj b/BlazorBootstrap.Demo.Server/BlazorBootstrap.Demo.Server.csproj index f60b2a192..bf47d7d7f 100644 --- a/BlazorBootstrap.Demo.Server/BlazorBootstrap.Demo.Server.csproj +++ b/BlazorBootstrap.Demo.Server/BlazorBootstrap.Demo.Server.csproj @@ -1,9 +1,10 @@ - net9.0 + net10.0 enable enable + true 17d839f8-f71e-4856-829b-ccf23589bb77 diff --git a/BlazorBootstrap.Demo.Server/Components/App.razor b/BlazorBootstrap.Demo.Server/Components/App.razor index 58ede1844..7953abfbd 100644 --- a/BlazorBootstrap.Demo.Server/Components/App.razor +++ b/BlazorBootstrap.Demo.Server/Components/App.razor @@ -1,4 +1,4 @@ - + @@ -6,14 +6,16 @@ Blazor Bootstrap Demos & Examples | Enterprise-class Blazor Bootstrap Component library built on the Blazor and Bootstrap CSS frameworks | Blazor Bootstrap + - + - - - - + + + + + @@ -41,19 +43,21 @@ - - - + + + + - + + - + - + diff --git a/BlazorBootstrap.Demo.Server/Components/Layout/ReconnectModal.razor b/BlazorBootstrap.Demo.Server/Components/Layout/ReconnectModal.razor new file mode 100644 index 000000000..49d916bc5 --- /dev/null +++ b/BlazorBootstrap.Demo.Server/Components/Layout/ReconnectModal.razor @@ -0,0 +1,31 @@ + + + +
    + +

    + Rejoining the server... +

    +

    + Rejoin failed... trying again in seconds. +

    +

    + Failed to rejoin.
    Please retry or reload the page. +

    + +

    + The session has been paused by the server. +

    + +

    + Failed to resume the session.
    Please reload the page. +

    +
    +
    diff --git a/BlazorBootstrap.Demo.Server/Components/Layout/ReconnectModal.razor.css b/BlazorBootstrap.Demo.Server/Components/Layout/ReconnectModal.razor.css new file mode 100644 index 000000000..3ad3773f3 --- /dev/null +++ b/BlazorBootstrap.Demo.Server/Components/Layout/ReconnectModal.razor.css @@ -0,0 +1,157 @@ +.components-reconnect-first-attempt-visible, +.components-reconnect-repeated-attempt-visible, +.components-reconnect-failed-visible, +.components-pause-visible, +.components-resume-failed-visible, +.components-rejoining-animation { + display: none; +} + +#components-reconnect-modal.components-reconnect-show .components-reconnect-first-attempt-visible, +#components-reconnect-modal.components-reconnect-show .components-rejoining-animation, +#components-reconnect-modal.components-reconnect-paused .components-pause-visible, +#components-reconnect-modal.components-reconnect-resume-failed .components-resume-failed-visible, +#components-reconnect-modal.components-reconnect-retrying, +#components-reconnect-modal.components-reconnect-retrying .components-reconnect-repeated-attempt-visible, +#components-reconnect-modal.components-reconnect-retrying .components-rejoining-animation, +#components-reconnect-modal.components-reconnect-failed, +#components-reconnect-modal.components-reconnect-failed .components-reconnect-failed-visible { + display: block; +} + + +#components-reconnect-modal { + background-color: white; + width: 20rem; + margin: 20vh auto; + padding: 2rem; + border: 0; + border-radius: 0.5rem; + box-shadow: 0 3px 6px 2px rgba(0, 0, 0, 0.3); + opacity: 0; + transition: display 0.5s allow-discrete, overlay 0.5s allow-discrete; + animation: components-reconnect-modal-fadeOutOpacity 0.5s both; + &[open] + +{ + animation: components-reconnect-modal-slideUp 1.5s cubic-bezier(.05, .89, .25, 1.02) 0.3s, components-reconnect-modal-fadeInOpacity 0.5s ease-in-out 0.3s; + animation-fill-mode: both; +} + +} + +#components-reconnect-modal::backdrop { + background-color: rgba(0, 0, 0, 0.4); + animation: components-reconnect-modal-fadeInOpacity 0.5s ease-in-out; + opacity: 1; +} + +@keyframes components-reconnect-modal-slideUp { + 0% { + transform: translateY(30px) scale(0.95); + } + + 100% { + transform: translateY(0); + } +} + +@keyframes components-reconnect-modal-fadeInOpacity { + 0% { + opacity: 0; + } + + 100% { + opacity: 1; + } +} + +@keyframes components-reconnect-modal-fadeOutOpacity { + 0% { + opacity: 1; + } + + 100% { + opacity: 0; + } +} + +.components-reconnect-container { + display: flex; + flex-direction: column; + align-items: center; + gap: 1rem; +} + +#components-reconnect-modal p { + margin: 0; + text-align: center; +} + +#components-reconnect-modal button { + border: 0; + background-color: #6b9ed2; + color: white; + padding: 4px 24px; + border-radius: 4px; +} + + #components-reconnect-modal button:hover { + background-color: #3b6ea2; + } + + #components-reconnect-modal button:active { + background-color: #6b9ed2; + } + +.components-rejoining-animation { + position: relative; + width: 80px; + height: 80px; +} + + .components-rejoining-animation div { + position: absolute; + border: 3px solid #0087ff; + opacity: 1; + border-radius: 50%; + animation: components-rejoining-animation 1.5s cubic-bezier(0, 0.2, 0.8, 1) infinite; + } + + .components-rejoining-animation div:nth-child(2) { + animation-delay: -0.5s; + } + +@keyframes components-rejoining-animation { + 0% { + top: 40px; + left: 40px; + width: 0; + height: 0; + opacity: 0; + } + + 4.9% { + top: 40px; + left: 40px; + width: 0; + height: 0; + opacity: 0; + } + + 5% { + top: 40px; + left: 40px; + width: 0; + height: 0; + opacity: 1; + } + + 100% { + top: 0px; + left: 0px; + width: 80px; + height: 80px; + opacity: 0; + } +} diff --git a/BlazorBootstrap.Demo.Server/Components/Layout/ReconnectModal.razor.js b/BlazorBootstrap.Demo.Server/Components/Layout/ReconnectModal.razor.js new file mode 100644 index 000000000..e52a190ba --- /dev/null +++ b/BlazorBootstrap.Demo.Server/Components/Layout/ReconnectModal.razor.js @@ -0,0 +1,63 @@ +// Set up event handlers +const reconnectModal = document.getElementById("components-reconnect-modal"); +reconnectModal.addEventListener("components-reconnect-state-changed", handleReconnectStateChanged); + +const retryButton = document.getElementById("components-reconnect-button"); +retryButton.addEventListener("click", retry); + +const resumeButton = document.getElementById("components-resume-button"); +resumeButton.addEventListener("click", resume); + +function handleReconnectStateChanged(event) { + if (event.detail.state === "show") { + reconnectModal.showModal(); + } else if (event.detail.state === "hide") { + reconnectModal.close(); + } else if (event.detail.state === "failed") { + document.addEventListener("visibilitychange", retryWhenDocumentBecomesVisible); + } else if (event.detail.state === "rejected") { + location.reload(); + } +} + +async function retry() { + document.removeEventListener("visibilitychange", retryWhenDocumentBecomesVisible); + + try { + // Reconnect will asynchronously return: + // - true to mean success + // - false to mean we reached the server, but it rejected the connection (e.g., unknown circuit ID) + // - exception to mean we didn't reach the server (this can be sync or async) + const successful = await Blazor.reconnect(); + if (!successful) { + // We have been able to reach the server, but the circuit is no longer available. + // We'll reload the page so the user can continue using the app as quickly as possible. + const resumeSuccessful = await Blazor.resumeCircuit(); + if (!resumeSuccessful) { + location.reload(); + } else { + reconnectModal.close(); + } + } + } catch (err) { + // We got an exception, server is currently unavailable + document.addEventListener("visibilitychange", retryWhenDocumentBecomesVisible); + } +} + +async function resume() { + try { + const successful = await Blazor.resumeCircuit(); + if (!successful) { + location.reload(); + } + } catch { + location.reload(); + } +} + +async function retryWhenDocumentBecomesVisible() { + if (document.visibilityState === "visible") { + await retry(); + } +} diff --git a/BlazorBootstrap.Demo.Server/Components/_Imports.razor b/BlazorBootstrap.Demo.Server/Components/_Imports.razor index 74b407f2d..a38315bb2 100644 --- a/BlazorBootstrap.Demo.Server/Components/_Imports.razor +++ b/BlazorBootstrap.Demo.Server/Components/_Imports.razor @@ -8,3 +8,4 @@ @using Microsoft.JSInterop @using BlazorBootstrap.Demo.Server @using BlazorBootstrap.Demo.Server.Components +@using BlazorBootstrap.Demo.Server.Components.Layout \ No newline at end of file diff --git a/BlazorBootstrap.Demo.Server/Program.cs b/BlazorBootstrap.Demo.Server/Program.cs index 30dc3cfa3..5c1ac4ef7 100644 --- a/BlazorBootstrap.Demo.Server/Program.cs +++ b/BlazorBootstrap.Demo.Server/Program.cs @@ -21,12 +21,12 @@ // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. app.UseHsts(); } - +app.UseStatusCodePagesWithReExecute("/not-found", createScopeForStatusCodePages: true); app.UseHttpsRedirection(); -app.UseStaticFiles(); app.UseAntiforgery(); +app.MapStaticAssets(); app.MapRazorComponents() .AddInteractiveServerRenderMode() .AddAdditionalAssemblies(typeof(BlazorBootstrap.Demo.RCL.App).Assembly); ; diff --git a/BlazorBootstrap.Demo.Server/appsettings.json b/BlazorBootstrap.Demo.Server/appsettings.json index d2c683608..1c0f9ddcf 100644 --- a/BlazorBootstrap.Demo.Server/appsettings.json +++ b/BlazorBootstrap.Demo.Server/appsettings.json @@ -6,13 +6,14 @@ } }, "AllowedHosts": "*", - "version": "3.2.0", + "version": "4.0.0", "release": { - "short_description": "New MainLayout and Theme Switcher components, along with other enhancements!!!" + "short_description": "New RichTextEditor, FileInput, SplitView, OTP Input & more. Charts now via BlazorExpress.ChartJS." }, "urls": { - "docs": "//docs.blazorbootstrap.com/getting-started/blazor-webassembly-net-8", - "blog": "//docs.blazorbootstrap.com/blog", + "demos": "/demos/getting-started", + "docs": "/docs/getting-started", + "blog": "https://docs.blazorbootstrap.com/blog", "github": "//github.com/vikramlearning/blazorbootstrap", "twitter": "//twitter.com/blazorbootstrap", "linkedin": "//www.linkedin.com/groups/14161025", @@ -21,9 +22,9 @@ "github_discussions": "//github.com/vikramlearning/blazorbootstrap/discussions", "stackoverflow": "//stackoverflow.com/questions/tagged/blazor-bootstrap" }, - "dotNetVersion": "9.0.0", + "dotNetVersion": "10.0.0", "GoogleMap": { - "ApiKey": "AIzaSyDc110Rvu20IMJhlZcWTOPoLbVQdnjLyXs" + "ApiKey": "<>" }, "AzureOpenAI": { "Endpoint": "", diff --git a/BlazorBootstrap.Demo.WebAssembly/App.razor b/BlazorBootstrap.Demo.WebAssembly/App.razor index f0f0afe72..5ad56d783 100644 --- a/BlazorBootstrap.Demo.WebAssembly/App.razor +++ b/BlazorBootstrap.Demo.WebAssembly/App.razor @@ -1,4 +1,5 @@ - + diff --git a/BlazorBootstrap.Demo.WebAssembly/BlazorBootstrap.Demo.WebAssembly.csproj b/BlazorBootstrap.Demo.WebAssembly/BlazorBootstrap.Demo.WebAssembly.csproj index 3fcfea059..e40a042bd 100644 --- a/BlazorBootstrap.Demo.WebAssembly/BlazorBootstrap.Demo.WebAssembly.csproj +++ b/BlazorBootstrap.Demo.WebAssembly/BlazorBootstrap.Demo.WebAssembly.csproj @@ -1,15 +1,16 @@  - net9.0 + net10.0 enable enable + true - - - + + + diff --git a/BlazorBootstrap.Demo.WebAssembly/wwwroot/appsettings.json b/BlazorBootstrap.Demo.WebAssembly/wwwroot/appsettings.json index bb6e7f911..948bded28 100644 --- a/BlazorBootstrap.Demo.WebAssembly/wwwroot/appsettings.json +++ b/BlazorBootstrap.Demo.WebAssembly/wwwroot/appsettings.json @@ -1,11 +1,12 @@ { - "version": "3.2.0", + "version": "4.0.0", "release": { - "short_description": "New MainLayout and Theme Switcher components, along with other enhancements!!!" + "short_description": "New RichTextEditor, FileInput, SplitView, OTP Input & more. Charts now via BlazorExpress.ChartJS." }, "urls": { - "docs": "//docs.blazorbootstrap.com/getting-started/blazor-webassembly-net-8", - "blog": "//docs.blazorbootstrap.com/blog", + "demos": "/demos/getting-started", + "docs": "/docs/getting-started", + "blog": "https://docs.blazorbootstrap.com/blog", "github": "//github.com/vikramlearning/blazorbootstrap", "twitter": "//twitter.com/blazorbootstrap", "linkedin": "//www.linkedin.com/groups/14161025", @@ -14,8 +15,8 @@ "github_discussions": "//github.com/vikramlearning/blazorbootstrap/discussions", "stackoverflow": "//stackoverflow.com/questions/tagged/blazor-bootstrap" }, - "dotNetVersion": "9.0.0", + "dotNetVersion": "10.0.0", "GoogleMap": { - "ApiKey": "AIzaSyDc110Rvu20IMJhlZcWTOPoLbVQdnjLyXs" + "ApiKey": "<>" } } \ No newline at end of file diff --git a/BlazorBootstrap.Demo.WebAssembly/wwwroot/index.html b/BlazorBootstrap.Demo.WebAssembly/wwwroot/index.html index 336dbd219..c104150f6 100644 --- a/BlazorBootstrap.Demo.WebAssembly/wwwroot/index.html +++ b/BlazorBootstrap.Demo.WebAssembly/wwwroot/index.html @@ -6,14 +6,14 @@ Demos & Examples | Enterprise-class Blazor Bootstrap Component library built on the Blazor and Bootstrap CSS framework | Blazor Bootstrap + - + - - + @@ -36,6 +36,7 @@ y = l.getElementsByTagName(r)[0]; y.parentNode.insertBefore(t, y); })(window, document, "clarity", "script", "er4vb2d8gr"); + @@ -47,21 +48,20 @@
    - - - - - + + + + + + - - + + diff --git a/README.md b/README.md index 2f1571f1f..70be7174b 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -

    +

    Blazor Bootstrap logo @@ -15,7 +15,7 @@
    -**NOTE:** We strongly recommend all BlazorBootstrap users migrate to version 2.x.x. [Read more...](https://docs.blazorbootstrap.com/blog/2024/02/25/upgrade-to-v2.0.0) +**NOTE:** We strongly recommend all BlazorBootstrap users upgrade to version 4.0.0. [Read more...](https://docs.blazorbootstrap.com/blog/2025/12/01/upgrade-to-v4.0.0) ## Status @@ -41,7 +41,7 @@ ## Install -Install with [NuGet](https://www.nuget.org/): `Install-Package Blazor.Bootstrap -Version 3.2.0` +Install with [NuGet](https://www.nuget.org/): `Install-Package Blazor.Bootstrap -Version 4.0.0` ## Install Blazor Bootstrap templates @@ -51,6 +51,11 @@ Install [Blazor Bootstrap templates](https://github.com/vikramlearning/blazorboo - Read the [Getting started page](https://docs.blazorbootstrap.com/getting-started/blazor-webassembly-net-8) for information on the framework installation, contents, examples, and more. +## Charts + +Chart components have moved out of BlazorBootstrap and are now provided by the dedicated [BlazorExpress.ChartJS](https://chartjs.blazorexpress.com/) package. + +This is a breaking change for existing chart users: install `BlazorExpress.ChartJS`, import its namespace, load its browser scripts, and migrate from the former BlazorBootstrap chart API. See the [migration and setup guide](https://docs.blazorbootstrap.com/components/charts), the [GitHub repository](https://github.com/BlazorExpress/BlazorExpress.ChartJS), and the [original demos](https://chartjs.blazorexpress.com/demos/bar-chart). ## Blazor Bootstrap Components | Component Name | Docs | Demos | @@ -64,18 +69,15 @@ Install [Blazor Bootstrap templates](https://github.com/vikramlearning/blazorboo | Callout | [Docs](https://docs.blazorbootstrap.com/components/callout) | [Demos](https://demos.blazorbootstrap.com/callout) | | Card | [Docs](https://docs.blazorbootstrap.com/components/card) | [Demos](https://demos.blazorbootstrap.com/card) | | Carousel | [Docs](https://docs.blazorbootstrap.com/components/carousel) | [Demos](https://demos.blazorbootstrap.com/carousel) | -| Charts: Bar chart | [Docs](https://docs.blazorbootstrap.com/data-visualization/bar-chart) | [Demos](https://demos.blazorbootstrap.com/charts/bar-chart) | -| Charts: Doughnut chart | [Docs](https://docs.blazorbootstrap.com/data-visualization/doughnut-chart) | [Demos](https://demos.blazorbootstrap.com/charts/doughnut-chart) | -| Charts: Line chart | [Docs](https://docs.blazorbootstrap.com/data-visualization/line-chart) | [Demos](https://demos.blazorbootstrap.com/charts/line-chart) | -| Charts: Pie chart | [Docs](https://docs.blazorbootstrap.com/data-visualization/pie-chart) | [Demos](https://demos.blazorbootstrap.com/charts/pie-chart) | -| Charts: Polar Area chart | [Docs](https://docs.blazorbootstrap.com/data-visualization/polar-area-chart) | [Demos](https://demos.blazorbootstrap.com/charts/polar-area-chart) | -| Charts: Radar chart | [Docs](https://docs.blazorbootstrap.com/data-visualization/radar-chart) | [Demos](https://demos.blazorbootstrap.com/charts/radar-chart) | -| Charts: Scatter chart | [Docs](https://docs.blazorbootstrap.com/data-visualization/scatter-chart) | [Demos](https://demos.blazorbootstrap.com/charts/scatter-chart) | +| Checkbox Input | [Docs](https://docs.blazorbootstrap.com/forms/checkbox-input) | [Demos](https://demos.blazorbootstrap.com/form/checkbox-input) | | Collapse | [Docs](https://docs.blazorbootstrap.com/components/collapse) | [Demos](https://demos.blazorbootstrap.com/collapse) | | Confirm Dialog | [Docs](https://docs.blazorbootstrap.com/components/confirm-dialog) | [Demos](https://demos.blazorbootstrap.com/confirm-dialog) | | Currency Input | [Docs](https://docs.blazorbootstrap.com/forms/currency-input) | [Demos](https://demos.blazorbootstrap.com/form/currency-input) | | Date Input | [Docs](https://docs.blazorbootstrap.com/forms/date-input) | [Demos](https://demos.blazorbootstrap.com/form/date-input) | | Dropdown | [Docs](https://docs.blazorbootstrap.com/components/dropdown) | [Demos](https://demos.blazorbootstrap.com/dropdown) | +| DragAndDropFileInput | [Docs](https://docs.blazorbootstrap.com/forms/drag-and-drop-file-input) | [Demos](https://demos.blazorbootstrap.com/demos/form/drag-and-drop-file-input) | +| Enum Input| [Docs](https://docs.blazorbootstrap.com/forms/enum-input) | [Demos](https://demos.blazorbootstrap.com//form/enum-input) | +| FileInput | [Docs](https://docs.blazorbootstrap.com/forms/file-input) | [Demos](https://demos.blazorbootstrap.com/demos/form/file-input) | | Google Map | [Docs](https://docs.blazorbootstrap.com/components/google-map) | [Demos](https://demos.blazorbootstrap.com/google-map) | | Grid | [Docs](https://docs.blazorbootstrap.com/components/grid) | [Demos](https://demos.blazorbootstrap.com/grid) | | Icons | [Docs](https://docs.blazorbootstrap.com/content/icons) | [Demos](https://demos.blazorbootstrap.com/icons) | @@ -83,21 +85,28 @@ Install [Blazor Bootstrap templates](https://github.com/vikramlearning/blazorboo | Markdown | [Docs](https://docs.blazorbootstrap.com/content/markdown) | [Demos](https://demos.blazorbootstrap.com/markdown) | | Modals | [Docs](https://docs.blazorbootstrap.com/components/modal) | [Demos](https://demos.blazorbootstrap.com/modals) | | Number Input | [Docs](https://docs.blazorbootstrap.com/forms/number-input) | [Demos](https://demos.blazorbootstrap.com/form/number-input) | +| OTPInput | [Docs](https://docs.blazorbootstrap.com/forms/otp-input) | [Demos](https://demos.blazorbootstrap.com/demos/form/otp-input) | | Offcanvas | [Docs](https://docs.blazorbootstrap.com/components/offcanvas) | [Demos](https://demos.blazorbootstrap.com/offcanvas) | | Pagination | [Docs](https://docs.blazorbootstrap.com/components/pagination) | [Demos](https://demos.blazorbootstrap.com/pagination) | +| Password Input | [Docs](https://docs.blazorbootstrap.com/forms/password-input) | [Demos](https://demos.blazorbootstrap.com/form/password-input) | | PDF Viewer | [Docs](https://docs.blazorbootstrap.com/components/pdf-viewer) | [Demos](https://demos.blazorbootstrap.com/pdf-viewer) | | Placeholders | [Docs](https://docs.blazorbootstrap.com/components/placeholders) | [Demos](https://demos.blazorbootstrap.com/placeholders) | | Preload | [Docs](https://docs.blazorbootstrap.com/components/preload) | [Demos](https://demos.blazorbootstrap.com/preload) | | Progress | [Docs](https://docs.blazorbootstrap.com/components/progress) | [Demos](https://demos.blazorbootstrap.com/progress) | +| Radio Input | [Docs](https://docs.blazorbootstrap.com/forms/radio-input) | [Demos](https://demos.blazorbootstrap.com/form/radio-input) | | RangeInput | [Docs](https://docs.blazorbootstrap.com/forms/range-input) | [Demos](https://demos.blazorbootstrap.com/form/range-input) | +| RichTextEditor | [Docs](https://docs.blazorbootstrap.com/forms/rich-text-editor) | [Demos](https://demos.blazorbootstrap.com/demos/form/rich-text-editor) | | Ribbon | [Docs](https://docs.blazorbootstrap.com/components/ribbon) | [Demos](https://demos.blazorbootstrap.com/ribbon) | | Script Loader | [Docs](https://docs.blazorbootstrap.com/components/script-loader) | [Demos](https://demos.blazorbootstrap.com/script-loader) | | Sidebar | [Docs](https://docs.blazorbootstrap.com/components/sidebar) | [Demos](https://demos.blazorbootstrap.com/sidebar) | | Sidebar2 | [Docs](https://docs.blazorbootstrap.com/components/sidebar2) | [Demos](https://demos.blazorbootstrap.com/sidebar2) | +| SplitView | [Docs](https://docs.blazorbootstrap.com/components/split-view) | [Demos](https://demos.blazorbootstrap.com/demos/split-view) | | Sortable List | [Docs](https://docs.blazorbootstrap.com/components/sortable-list) | [Demos](https://demos.blazorbootstrap.com/sortable-list) | | Spinners | [Docs](https://docs.blazorbootstrap.com/components/spinners) | [Demos](https://demos.blazorbootstrap.com/spinners) | | Switch | [Docs](https://docs.blazorbootstrap.com/forms/switch) | [Demos](https://demos.blazorbootstrap.com/form/switch) | | Tabs | [Docs](https://docs.blazorbootstrap.com/components/tabs) | [Demos](https://demos.blazorbootstrap.com/tabs) | +| Text Input | [Docs](https://docs.blazorbootstrap.com/forms/text-input) | [Demos](https://demos.blazorbootstrap.com/form/text-input) | +| TextArea Input | [Docs](https://docs.blazorbootstrap.com/forms/textarea-input) | [Demos](https://demos.blazorbootstrap.com/form/text-area-input) | | Theme Switcher | [Docs](https://docs.blazorbootstrap.com/components/theme-switcher) | [Demos](https://demos.blazorbootstrap.com/theme-switcher) | | Time Input | [Docs](https://docs.blazorbootstrap.com/forms/time-input) | [Demos](https://demos.blazorbootstrap.com/form/time-input) | | Toasts | [Docs](https://docs.blazorbootstrap.com/components/toasts) | [Demos](https://demos.blazorbootstrap.com/toasts) | @@ -138,20 +147,8 @@ Blazor Bootstrap's documentation, which is included in this repository's root di ### Blazor Bootstrap - Carousel ![Blazor Bootstrap - Carousel](https://i.imgur.com/YoZd9Hy.png "Blazor Bootstrap - Carousel") -### Blazor Bootstrap - Charts: Bar Chart -![Blazor Bootstrap - Charts: Bar Chart](https://i.imgur.com/JLV7oss.png "Blazor Bootstrap - Charts: Bar Chart") - -### Blazor Bootstrap - Charts: Doughnut Chart -![Blazor Bootstrap - Charts: Doughnut Chart](https://i.imgur.com/e5fnMXQ.png "Blazor Bootstrap - Charts: Doughnut Chart") - -### Blazor Bootstrap - Charts: Line Chart -![Blazor Bootstrap - Charts: Line Chart](https://i.imgur.com/CzdXpqr.png "Blazor Bootstrap - Charts: Line Chart") - -### Blazor Bootstrap - Charts: Pie Chart -![Blazor Bootstrap - Charts: Pie Chart](https://i.imgur.com/jr3w0fM.png "Blazor Bootstrap - Charts: Pie Chart") - -### Blazor Bootstrap - Charts: Polar Area Chart -![Blazor Bootstrap - Charts: Polar Area Chart](https://i.imgur.com/MSFDsSo.png "Blazor Bootstrap - Charts: Polar Area Chart") +### Blazor Bootstrap - Checkbox Input +![Blazor Bootstrap - Checkbox Input](https://i.imgur.com/kqSggFK.png "Blazor Bootstrap - Checkbox Input") ### Blazor Bootstrap - Collapse ![Blazor Bootstrap - Collapse](https://i.imgur.com/8A0emQe.png "Blazor Bootstrap - Collapse") @@ -165,9 +162,18 @@ Blazor Bootstrap's documentation, which is included in this repository's root di ### Blazor Bootstrap - Date Input ![Blazor Bootstrap - Date Input](https://i.imgur.com/1mVjqQv.png "Blazor Bootstrap - Date Input") +### Blazor Bootstrap - DragAndDropFileInput +![Blazor Bootstrap - DragAndDropFileInput](https://demos.blazorbootstrap.com/_content/BlazorBootstrap.Demo.RCL/images/screenshots/drag-and-drop-file-input.png "Blazor Bootstrap - DragAndDropFileInput") + ### Blazor Bootstrap - Dropdown ![Blazor Bootstrap - Dropdown](https://i.imgur.com/beAr31J.png "Blazor Bootstrap - Dropdown") +### Blazor Bootstrap - Enum Input +![Blazor Bootstrap - Enum Input](https://private-user-images.githubusercontent.com/2337067/517874250-8a624590-1dfc-470a-8f9d-7636851d6c95.png?jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3NjM5MjAxNzEsIm5iZiI6MTc2MzkxOTg3MSwicGF0aCI6Ii8yMzM3MDY3LzUxNzg3NDI1MC04YTYyNDU5MC0xZGZjLTQ3MGEtOGY5ZC03NjM2ODUxZDZjOTUucG5nP1gtQW16LUFsZ29yaXRobT1BV1M0LUhNQUMtU0hBMjU2JlgtQW16LUNyZWRlbnRpYWw9QUtJQVZDT0RZTFNBNTNQUUs0WkElMkYyMDI1MTEyMyUyRnVzLWVhc3QtMSUyRnMzJTJGYXdzNF9yZXF1ZXN0JlgtQW16LURhdGU9MjAyNTExMjNUMTc0NDMxWiZYLUFtei1FeHBpcmVzPTMwMCZYLUFtei1TaWduYXR1cmU9ZmVlNDlmZDZkNGQ5ZWUxMjE5MGM3NmEzMzc2OTdhYzk0MjY4YTU3NTk5M2JmMGIxNDNkYjI0ZWYyM2UwMDA5YyZYLUFtei1TaWduZWRIZWFkZXJzPWhvc3QifQ.hvU9-57w9n41vwE3eyy3ZcDPDYXbQ3p_JW1RmDmT-c8 "Blazor Bootstrap - Enum Input") + +### Blazor Bootstrap - FileInput +![Blazor Bootstrap - FileInput](https://demos.blazorbootstrap.com/_content/BlazorBootstrap.Demo.RCL/images/screenshots/file-input.png "Blazor Bootstrap - FileInput") + ### Blazor Bootstrap - Google Map ![Blazor Bootstrap - Google Map](https://i.imgur.com/AbyDP51.png "Blazor Bootstrap - Google Map") @@ -189,9 +195,15 @@ Blazor Bootstrap's documentation, which is included in this repository's root di ### Blazor Bootstrap - Number Input ![Blazor Bootstrap - Number Input](https://i.imgur.com/iUNBkki.png "Blazor Bootstrap - Number Input") +### Blazor Bootstrap - OTPInput +![Blazor Bootstrap - OTPInput](https://demos.blazorbootstrap.com/_content/BlazorBootstrap.Demo.RCL/images/screenshots/otp-input.png "Blazor Bootstrap - OTPInput") + ### Blazor Bootstrap - Offcanvas ![Blazor Bootstrap - Offcanvas](https://i.imgur.com/1vNz5Ci.jpg "Blazor Bootstrap - Offcanvas") +### Blazor Bootstrap - Password Input +![Blazor Bootstrap - Password Input](https://i.imgur.com/0k1C2XS.png "Blazor Bootstrap - Password Input") + ### Blazor Bootstrap - Pagination ![Blazor Bootstrap - Pagination](https://i.imgur.com/SCbZVd4.jpg "Blazor Bootstrap - Pagination") @@ -207,9 +219,15 @@ Blazor Bootstrap's documentation, which is included in this repository's root di ### Blazor Bootstrap - Progress ![Blazor Bootstrap - Progress](https://i.imgur.com/MK142lQ.png "Blazor Bootstrap - Progress") +### Blazor Bootstrap - Radio Input +![Blazor Bootstrap - Radio Input](https://i.imgur.com/8koE00q.png "Blazor Bootstrap - Radio Input") + ### Blazor Bootstrap - Range Input ![Blazor Bootstrap - Range Input](https://i.imgur.com/rWDDHaf.png "Blazor Bootstrap - Range Input") +### Blazor Bootstrap - RichTextEditor +![Blazor Bootstrap - RichTextEditor](https://demos.blazorbootstrap.com/_content/BlazorBootstrap.Demo.RCL/images/screenshots/rich-text-editor.png "Blazor Bootstrap - RichTextEditor") + ### Blazor Bootstrap - Ribbon ![Blazor Bootstrap - Ribbon](https://i.imgur.com/LpZVLbF.png "Blazor Bootstrap - Ribbon") @@ -222,6 +240,9 @@ Blazor Bootstrap's documentation, which is included in this repository's root di ### Blazor Bootstrap - Sidebar2 ![Blazor Bootstrap - Sidebar2](https://i.imgur.com/HUP7ydv.png "Blazor Bootstrap - Sidebar2") +### Blazor Bootstrap - SplitView +![Blazor Bootstrap - SplitView](https://demos.blazorbootstrap.com/_content/BlazorBootstrap.Demo.RCL/images/screenshots/split-view.png "Blazor Bootstrap - SplitView") + ### Blazor Bootstrap - Sortable List ![Blazor Bootstrap - Sortable List](https://i.imgur.com/bfzP8Yi.png "Blazor Bootstrap - Sortable List") @@ -231,6 +252,12 @@ Blazor Bootstrap's documentation, which is included in this repository's root di ### Blazor Bootstrap - Tabs ![Blazor Bootstrap - Tabs](https://i.imgur.com/NdE5oqH.png "Blazor Bootstrap - Tabs") +### Blazor Bootstrap - Text Input +![Blazor Bootstrap - Text Input](https://i.imgur.com/N2VUHIn.png "Blazor Bootstrap - Text Input") + +### Blazor Bootstrap - TextArea Input +![Blazor Bootstrap - TextArea Input](https://i.imgur.com/aSVKMqv.png "Blazor Bootstrap - TextArea Input") + ### Blazor Bootstrap - Theme Switcher ![Blazor Bootstrap - Theme Switcher](https://i.imgur.com/2eixWho.png "Blazor Bootstrap - Theme Switcher") diff --git a/blazorbootstrap.sln b/blazorbootstrap.sln index 047f0f190..79b7c1ed7 100644 --- a/blazorbootstrap.sln +++ b/blazorbootstrap.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 17 -VisualStudioVersion = 17.0.31903.59 +# Visual Studio Version 18 +VisualStudioVersion = 18.3.11218.70 d18.3 MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BlazorBootstrap", "blazorbootstrap\BlazorBootstrap.csproj", "{23D9E8D8-8F90-457A-96B5-4BDA599D37AE}" EndProject @@ -9,10 +9,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{74FC2FB9-8E2 EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "demos", "demos", "{7DABA756-9F2F-48A6-B8D3-B104262D11B1}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BlazorBootstrap.Demo.Hosted.Server", "BlazorBootstrap.Demo.Hosted\Server\BlazorBootstrap.Demo.Hosted.Server.csproj", "{D8A68986-BC6C-46AD-A089-7F325884E966}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BlazorBootstrap.Demo.Hosted.Client", "BlazorBootstrap.Demo.Hosted\Client\BlazorBootstrap.Demo.Hosted.Client.csproj", "{CA121C94-88EC-4902-9FCD-8394BDEB0355}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BlazorBootstrap.Demo.RCL", "BlazorBootstrap.Demo.RCL\BlazorBootstrap.Demo.RCL.csproj", "{190E07ED-8888-4F3B-8484-46BF6FC4C982}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BlazorBootstrap.Demo.WebAssembly", "BlazorBootstrap.Demo.WebAssembly\BlazorBootstrap.Demo.WebAssembly.csproj", "{710E0A10-0567-495D-AA48-A99293D2EA62}" @@ -29,14 +25,6 @@ Global {23D9E8D8-8F90-457A-96B5-4BDA599D37AE}.Debug|Any CPU.Build.0 = Debug|Any CPU {23D9E8D8-8F90-457A-96B5-4BDA599D37AE}.Release|Any CPU.ActiveCfg = Release|Any CPU {23D9E8D8-8F90-457A-96B5-4BDA599D37AE}.Release|Any CPU.Build.0 = Release|Any CPU - {D8A68986-BC6C-46AD-A089-7F325884E966}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {D8A68986-BC6C-46AD-A089-7F325884E966}.Debug|Any CPU.Build.0 = Debug|Any CPU - {D8A68986-BC6C-46AD-A089-7F325884E966}.Release|Any CPU.ActiveCfg = Release|Any CPU - {D8A68986-BC6C-46AD-A089-7F325884E966}.Release|Any CPU.Build.0 = Release|Any CPU - {CA121C94-88EC-4902-9FCD-8394BDEB0355}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {CA121C94-88EC-4902-9FCD-8394BDEB0355}.Debug|Any CPU.Build.0 = Debug|Any CPU - {CA121C94-88EC-4902-9FCD-8394BDEB0355}.Release|Any CPU.ActiveCfg = Release|Any CPU - {CA121C94-88EC-4902-9FCD-8394BDEB0355}.Release|Any CPU.Build.0 = Release|Any CPU {190E07ED-8888-4F3B-8484-46BF6FC4C982}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {190E07ED-8888-4F3B-8484-46BF6FC4C982}.Debug|Any CPU.Build.0 = Debug|Any CPU {190E07ED-8888-4F3B-8484-46BF6FC4C982}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -55,8 +43,6 @@ Global EndGlobalSection GlobalSection(NestedProjects) = preSolution {23D9E8D8-8F90-457A-96B5-4BDA599D37AE} = {74FC2FB9-8E21-439A-8646-DF30A02041A1} - {D8A68986-BC6C-46AD-A089-7F325884E966} = {7DABA756-9F2F-48A6-B8D3-B104262D11B1} - {CA121C94-88EC-4902-9FCD-8394BDEB0355} = {7DABA756-9F2F-48A6-B8D3-B104262D11B1} {190E07ED-8888-4F3B-8484-46BF6FC4C982} = {7DABA756-9F2F-48A6-B8D3-B104262D11B1} {710E0A10-0567-495D-AA48-A99293D2EA62} = {7DABA756-9F2F-48A6-B8D3-B104262D11B1} {B133D9CF-EC94-416B-A4A6-6E2BD8DAF0C1} = {7DABA756-9F2F-48A6-B8D3-B104262D11B1} diff --git a/blazorbootstrap/Attributes/AddedVersionAttribute.cs b/blazorbootstrap/Attributes/AddedVersionAttribute.cs new file mode 100644 index 000000000..8bed9e7e3 --- /dev/null +++ b/blazorbootstrap/Attributes/AddedVersionAttribute.cs @@ -0,0 +1,22 @@ +namespace BlazorBootstrap; + +///

    +/// Attribute to specify the version when a property was added. +/// +public class AddedVersionAttribute : Attribute +{ + #region Constructors + + public AddedVersionAttribute(string version) + { + Version = version; + } + + #endregion + + #region Properties, Indexers + + public string Version { get; } + + #endregion +} diff --git a/blazorbootstrap/Attributes/MethodNameAttribute.cs b/blazorbootstrap/Attributes/MethodNameAttribute.cs new file mode 100644 index 000000000..7c6eaf6f3 --- /dev/null +++ b/blazorbootstrap/Attributes/MethodNameAttribute.cs @@ -0,0 +1,22 @@ +namespace BlazorBootstrap; + +/// +/// Attribute to specify the method name with parameters. +/// +public class MethodNameAttribute : Attribute +{ + #region Constructors + + public MethodNameAttribute(string methodName) + { + MethodName = methodName; + } + + #endregion + + #region Properties, Indexers + + public string MethodName { get; } + + #endregion +} diff --git a/blazorbootstrap/Attributes/MethodReturnTypeNameAttribute.cs b/blazorbootstrap/Attributes/MethodReturnTypeNameAttribute.cs new file mode 100644 index 000000000..8faced7c2 --- /dev/null +++ b/blazorbootstrap/Attributes/MethodReturnTypeNameAttribute.cs @@ -0,0 +1,22 @@ +namespace BlazorBootstrap; + +/// +/// Attribute to specify the method return type name. +/// +public class MethodReturnTypeNameAttribute : Attribute +{ + #region Constructors + + public MethodReturnTypeNameAttribute(string typeName) + { + TypeName = typeName; + } + + #endregion + + #region Properties, Indexers + + public string TypeName { get; } + + #endregion +} diff --git a/blazorbootstrap/Attributes/ParameterTypeNameAttribute.cs b/blazorbootstrap/Attributes/ParameterTypeNameAttribute.cs new file mode 100644 index 000000000..67a478155 --- /dev/null +++ b/blazorbootstrap/Attributes/ParameterTypeNameAttribute.cs @@ -0,0 +1,22 @@ +namespace BlazorBootstrap; + +/// +/// Attribute to specify the parameter type name. +/// +public class ParameterTypeNameAttribute : Attribute +{ + #region Constructors + + public ParameterTypeNameAttribute(string typeName) + { + TypeName = typeName; + } + + #endregion + + #region Properties, Indexers + + public string TypeName { get; } + + #endregion +} diff --git a/blazorbootstrap/BlazorBootstrap.csproj b/blazorbootstrap/BlazorBootstrap.csproj index ba6f40e44..1e81ce819 100644 --- a/blazorbootstrap/BlazorBootstrap.csproj +++ b/blazorbootstrap/BlazorBootstrap.csproj @@ -1,22 +1,22 @@ - + Blazor.Bootstrap - 3.2.0 - 3.2.0 + 4.0.0 + 4.0.0 Apache-2.0 https://docs.blazorbootstrap.com/ https://github.com/vikramlearning/blazorbootstrap - Blazor, WebAssembly, BlazorWebAssembly, Bootstrap, Bootstrap5, BlazorBootstrap, BlazorAlert, BlazorAutoComplete, BlazorButtons, BlazorCallout, BlazorCharts, BlazorConfirmDialog, BlazorGrid, BlazorIcon, BlazorImage, BlazorModal, BlazorCurrencyInput, BlazorNumberInput, BlazorInput, BlazorNumber, BlazorDate, BlazorDateInput, BlazorDatePicker, BlazorTime, BlazorTimeInput, BlazorTimePicker, BlazorOffcanvas, BlazorPagination, BlazorPdfViewer, BlazorPlaceholders, BlazorPreload, BlazorProgress, BlazorRibbon, BlazorScriptLoader, BlazorSidebar, BlazorSidebar2, BlazorSortableList, BlazorSwitch, BlazorSpinners, BlazorTabs, BlazorToasts, BlazorTooltips, BlazorTooltips, BlazorBarChart, BlazorDoughnutChart, BlazorLineChart, BlazorPieChart, BlazorPolarAreaChart, BlazorRadarChart, BlazorScatterChart, BlazorMarkdown + Blazor, WebAssembly, BlazorWebAssembly, Bootstrap, Bootstrap5, BlazorBootstrap, BlazorAlert, BlazorAutoComplete, BlazorButtons, BlazorCallout, BlazorConfirmDialog, BlazorGrid, BlazorIcon, BlazorImage, BlazorModal, BlazorCheckboxInput, BlazorCurrencyInput, BlazorNumberInput, BlazorInput, BlazorNumber, BlazorDate, BlazorDateInput, BlazorPasswordInput, BlazorDatePicker, BlazorRadioInput, BlazorTextInput, BlazortextAreaInput, BlazorTime, BlazorTimeInput, BlazorTimePicker, BlazorOffcanvas, BlazorPagination, BlazorPdfViewer, BlazorPlaceholders, BlazorPreload, BlazorProgress, BlazorRibbon, BlazorScriptLoader, BlazorSidebar, BlazorSidebar2, BlazorSortableList, BlazorSwitch, BlazorSpinners, BlazorTabs, BlazorToasts, BlazorTooltips, BlazorTooltips, BlazorMarkdown Blazor Bootstrap is a component library built on top of Blazor and Bootstrap5 CSS framework. Vikram Reddy - Copyright © 2024 Blazor Bootstrap + Copyright © 2025 Blazor Bootstrap - net6.0;net8.0;net9.0 + net8.0;net9.0;net10.0 enable enable Library @@ -44,19 +44,16 @@ - - - - - - - + + + + \ No newline at end of file diff --git a/blazorbootstrap/Components/AI/Chat/AIChat.razor b/blazorbootstrap/Components/AI/Chat/AIChat.razor deleted file mode 100644 index 254561235..000000000 --- a/blazorbootstrap/Components/AI/Chat/AIChat.razor +++ /dev/null @@ -1,63 +0,0 @@ -@namespace BlazorBootstrap -@inherits BlazorBootstrapComponentBase - - \ No newline at end of file diff --git a/blazorbootstrap/Components/AI/Chat/AIChat.razor.cs b/blazorbootstrap/Components/AI/Chat/AIChat.razor.cs deleted file mode 100644 index cc8c1ec77..000000000 --- a/blazorbootstrap/Components/AI/Chat/AIChat.razor.cs +++ /dev/null @@ -1,156 +0,0 @@ -namespace BlazorBootstrap; - -public partial class AIChat : BlazorBootstrapComponentBase -{ - #region Fields and Constants - - private readonly List conversationHistory = new(); - private string? apiKey; - private string? apiVersion; - private string? currentCompletion; - private string? deploymentName; - private string? endpoint; - private bool isRequestInProgress; - private DotNetObjectReference? objRef; - private string userPrompt = string.Empty; - - #endregion - - #region Methods - - protected override async Task OnInitializedAsync() - { - var configurationSection = Configuration.GetSection("AzureOpenAI"); - - if (Configuration is null) - throw new ArgumentException("`AzureOpenAI` section was not found in the application configuration."); - - endpoint = configurationSection["Endpoint"]; - - if (endpoint is null) - throw new ArgumentException("`Endpoint` key/value was not found in the 'AzureOpenAI' section of the application configuration."); - - deploymentName = configurationSection["DeploymentName"]; - - if (deploymentName is null) - throw new ArgumentException("`DeploymentName` key/value was not found in the 'AzureOpenAI' section of the application configuration."); - - apiKey = configurationSection["ApiKey"]; - - if (apiKey is null) - throw new ArgumentException("`ApiKey` key/value was not found in the 'AzureOpenAI' section of the application configuration."); - - apiVersion = configurationSection["ApiVersion"]; - - if (apiVersion is null) - throw new ArgumentException("`ApiVersion` key/value was not found in the 'AzureOpenAI' section of the application configuration."); - - objRef ??= DotNetObjectReference.Create(this); - - await base.OnInitializedAsync(); - } - - [JSInvokable] - public async Task ChartCompletetionsStreamJs(string content, bool done) - { - ClearInput(); - - if (isRequestInProgress) - isRequestInProgress = false; - - if (done) - { - conversationHistory.Add(new OpenAIChatMessage("system", currentCompletion!)); - currentCompletion = ""; - await InvokeAsync(StateHasChanged); - await JSRuntime.InvokeVoidAsync(BlazorBootstrapInterop.ScrollToElementBottom, Id); - - return; - } - - currentCompletion += content; - await InvokeAsync(StateHasChanged); - await JSRuntime.InvokeVoidAsync(BlazorBootstrapInterop.ScrollToElementBottom, Id); - } - - private void ClearInput() => userPrompt = string.Empty; - - private async Task CreateCompletionAsync(List messages) - { - isRequestInProgress = true; - - var payload = new OpenAIChatPayload { Messages = messages, MaximumTokens = MaximumTokens, Temperature = Temperature, TopP = TopP }; - - try - { - await JSRuntime.InvokeVoidAsync( - AIChatInterop.AzureOpenAIChatCompletions, - $"{endpoint}openai/deployments/{deploymentName}/chat/completions?api-version={apiVersion}", - apiKey, - payload, - objRef! - ); - } - catch - { - isRequestInProgress = false; - } - } - - private async Task SendPromptAsync() - { - if (string.IsNullOrWhiteSpace(userPrompt)) - return; - - var message = new OpenAIChatMessage("user", userPrompt); - conversationHistory.Add(message); - - await CreateCompletionAsync(new List { message }); - } - - #endregion - - #region Properties, Indexers - - protected override string? ClassNames => - BuildClassNames( - Class, - (BootstrapClass.Container, true) - ); - - protected override string? StyleNames => - BuildStyleNames( - Style, - //("min-height:200px", true), - //("max-height:400px", true), - ("overflow-x:hidden", true), - ("overflow-y:auto", true) - ); - - /// - /// The maximum number of tokens to generate shared between the prompt and completion. - /// The exact limit varies by model. (One token is roughly 4 characters for standard English text) - /// Minimum 1 and the maximum tokens is 4096. - /// - /// Default value is 2048. This value is limited by gpt-3.5-turbo. - [Parameter] - public long MaximumTokens { get; set; } = 2048; - - /// - /// Controls randomness: Lowering results in less random completions. - /// As the temperature approaches zero, the model will become deterministic and repetitive. - /// Minimum 1 and the maximum is 2. - /// - /// Default value is 1. - [Parameter] - public double Temperature { get; set; } = 1; - - /// - /// Controls diversity via nucleus sampling: 0.5 means half of all likelihood-weighted options are considered. - /// - /// Default value is 1. - [Parameter] - public double TopP { get; set; } = 1; - - #endregion -} diff --git a/blazorbootstrap/Components/AI/Chat/AIChatInterop.cs.cs b/blazorbootstrap/Components/AI/Chat/AIChatInterop.cs.cs deleted file mode 100644 index 8dc241100..000000000 --- a/blazorbootstrap/Components/AI/Chat/AIChatInterop.cs.cs +++ /dev/null @@ -1,12 +0,0 @@ -namespace BlazorBootstrap; - -public class AIChatInterop -{ - #region Fields and Constants - - private const string Prefix = "window.blazorBootstrap.ai."; - - public const string AzureOpenAIChatCompletions = Prefix + "azureOpenAI.chat.completions"; - - #endregion -} diff --git a/blazorbootstrap/Components/Accordion/Accordion.razor.cs b/blazorbootstrap/Components/Accordion/Accordion.razor.cs index 8fe07966b..59fd657dd 100644 --- a/blazorbootstrap/Components/Accordion/Accordion.razor.cs +++ b/blazorbootstrap/Components/Accordion/Accordion.razor.cs @@ -22,6 +22,8 @@ protected override async ValueTask DisposeAsyncCore(bool disposing) /// Hides the by index. /// /// The index of the AccordionItem to hide. + [AddedVersion("1.10.5")] + [Description("Hides the AccordionItem by index.")] public async Task HideAccordionItemByIndexAsync(int index) { if (!items?.Any() ?? false) return; @@ -38,6 +40,8 @@ public async Task HideAccordionItemByIndexAsync(int index) /// Hides the by name. /// /// The name of the AccordionItem to hide. + [AddedVersion("1.10.5")] + [Description("Hides the AccordionItem by name.")] public async Task HideAccordionItemByNameAsync(string accordionItemName) { if (!items?.Any() ?? false) return; @@ -51,6 +55,8 @@ public async Task HideAccordionItemByNameAsync(string accordionItemName) /// /// Hides all instances. /// + [AddedVersion("1.10.5")] + [Description("Hides all AccordionItem instances.")] public async Task HideAllAccordionItemsAsync() { if (!items?.Any() ?? false) return; @@ -63,6 +69,8 @@ public async Task HideAllAccordionItemsAsync() /// /// Hides the first . /// + [AddedVersion("1.10.5")] + [Description("Hides the first AccordionItem.")] public async Task HideFirstAccordionItemAsync() { if (!items?.Any() ?? false) return; @@ -76,6 +84,8 @@ public async Task HideFirstAccordionItemAsync() /// /// Hides the last . /// + [AddedVersion("1.10.5")] + [Description("Hides the last AccordionItem.")] public async Task HideLastAccordionItemAsync() { if (!items?.Any() ?? false) return; @@ -90,6 +100,8 @@ public async Task HideLastAccordionItemAsync() /// Shows the by index. /// /// The index of the AccordionItem to show. + [AddedVersion("1.7.0")] + [Description("Shows the AccordionItem by index.")] public async Task ShowAccordionItemByIndexAsync(int index) { if (!items?.Any() ?? false) return; @@ -106,6 +118,8 @@ public async Task ShowAccordionItemByIndexAsync(int index) /// Shows the by name. /// /// The name of the AccordionItem to show. + [AddedVersion("1.7.0")] + [Description("Shows the AccordionItem by name.")] public async Task ShowAccordionItemByNameAsync(string accordionItemName) { if (!items?.Any() ?? false) return; @@ -117,8 +131,10 @@ public async Task ShowAccordionItemByNameAsync(string accordionItemName) } /// - /// Shows all instances if AlwaysOpen is true. + /// Shows all instances if is . /// + [AddedVersion("1.10.5")] + [Description("Shows all AccordionItem instances if AlwaysOpen is true.")] public async Task ShowAllAccordionItemsAsync() { if (!items?.Any() ?? false) return; @@ -132,6 +148,8 @@ public async Task ShowAllAccordionItemsAsync() /// /// Shows the first . /// + [AddedVersion("1.7.0")] + [Description("Shows the first AccordionItem.")] public async Task ShowFirstAccordionItemAsync() { if (!items?.Any() ?? false) return; @@ -145,6 +163,8 @@ public async Task ShowFirstAccordionItemAsync() /// /// Shows the last . /// + [AddedVersion("1.7.0")] + [Description("Shows the last AccordionItem.")] public async Task ShowLastAccordionItemAsync() { if (!items?.Any() ?? false) return; @@ -179,54 +199,70 @@ internal void Add(AccordionItem accordionItem) /// /// If , accordion items stay open when another item is opened. + /// + /// Default value is . + /// /// - /// - /// Default value is false. - /// + [AddedVersion("1.7.0")] + [DefaultValue(false)] + [Description("If true, accordion items stay open when another item is opened.")] [Parameter] public bool AlwaysOpen { get; set; } /// /// Gets or sets the content to be rendered within the component. + /// + /// Default value is . + /// /// - /// - /// Default value is null. - /// - [Parameter] + [AddedVersion("1.7.0")] + [DefaultValue(null)] + [Description("Gets or sets the content to be rendered within the component.")] [EditorRequired] - public RenderFragment ChildContent { get; set; } = default!; + [Parameter] + public RenderFragment? ChildContent { get; set; } /// /// If , removes borders and rounded corners to render accordions edge-to-edge with their parent container. + /// + /// Default value is . + /// /// - /// - /// Default value is false. - /// + [AddedVersion("1.7.0")] + [DefaultValue(false)] + [Description("If true, removes borders and rounded corners to render accordions edge-to-edge with their parent container.")] [Parameter] public bool Flush { get; set; } /// /// This event is fired when a accordion item has been hidden from the user (will wait for CSS transitions to complete). /// + [AddedVersion("1.7.0")] + [Description("This event is fired when a accordion item has been hidden from the user (will wait for CSS transitions to complete).")] [Parameter] public EventCallback OnHidden { get; set; } /// /// This event is fired immediately when the hide method has been called. /// + [AddedVersion("1.7.0")] + [Description("This event is fired immediately when the hide method has been called.")] [Parameter] public EventCallback OnHiding { get; set; } /// /// This event fires immediately when the show method is called. /// + [AddedVersion("1.7.0")] + [Description("This event fires immediately when the show method is called.")] [Parameter] public EventCallback OnShowing { get; set; } /// - /// This event is fired when a accordion item has been made visible to the user (will wait for CSS transitions to - /// complete). + /// This event is fired when a accordion item has been made visible to the user (will wait for CSS transitions to complete). /// + [AddedVersion("1.7.0")] + [Description("This event is fired when a accordion item has been made visible to the user (will wait for CSS transitions to complete).")] [Parameter] public EventCallback OnShown { get; set; } diff --git a/blazorbootstrap/Components/Accordion/AccordionItem.razor.cs b/blazorbootstrap/Components/Accordion/AccordionItem.razor.cs index b691486ac..dd3bd2c5c 100644 --- a/blazorbootstrap/Components/Accordion/AccordionItem.razor.cs +++ b/blazorbootstrap/Components/Accordion/AccordionItem.razor.cs @@ -66,10 +66,13 @@ private async Task OnCollapseShownAsync() /// /// Gets or sets the active state. + /// + /// Default value is . + /// /// - /// - /// Default value is false. - /// + [AddedVersion("1.7.0")] + [DefaultValue(false)] + [Description("Gets or sets the active state.")] [Parameter] public bool Active { get; set; } @@ -77,22 +80,28 @@ private async Task OnCollapseShownAsync() /// /// Gets or sets the content to be rendered within the component. + /// + /// Default value is . + /// /// - /// - /// Default value is null. - /// - [Parameter] + [AddedVersion("1.7.0")] + [DefaultValue(null)] + [Description("Gets or sets the content to be rendered within the component.")] [EditorRequired] - public RenderFragment Content { get; set; } = default!; + [Parameter] + public RenderFragment? Content { get; set; } /// /// Gets or sets the name. + /// + /// Default value is . + /// /// - /// - /// Default value is null. - /// + [AddedVersion("1.7.0")] + [DefaultValue(null)] + [Description("Gets or sets the name.")] [Parameter] - public string Name { get; set; } = default!; + public string? Name { get; set; } /// /// Gets or sets the parent. @@ -102,21 +111,27 @@ private async Task OnCollapseShownAsync() /// /// Gets or sets the title. + /// + /// Default value is . + /// /// - /// - /// Default value is null. - /// + [AddedVersion("1.7.0")] + [DefaultValue(null)] + [Description("Gets or sets the title.")] [Parameter] - public string Title { get; set; } = default!; + public string? Title { get; set; } /// /// Gets or sets the title template. + /// + /// Default value is . + /// /// - /// - /// Default value is null. - /// + [AddedVersion("1.7.0")] + [DefaultValue(null)] + [Description("Gets or sets the title template.")] [Parameter] - public RenderFragment TitleTemplate { get; set; } = default!; + public RenderFragment? TitleTemplate { get; set; } = default!; #endregion } diff --git a/blazorbootstrap/Components/Alert/Alert.razor.cs b/blazorbootstrap/Components/Alert/Alert.razor.cs index 392f4888a..ca1ba48b9 100644 --- a/blazorbootstrap/Components/Alert/Alert.razor.cs +++ b/blazorbootstrap/Components/Alert/Alert.razor.cs @@ -18,7 +18,7 @@ protected override async ValueTask DisposeAsyncCore(bool disposing) try { if (IsRenderComplete) - await JSRuntime.InvokeVoidAsync("window.blazorBootstrap.alert.dispose", Id); + await SafeInvokeVoidAsync("window.blazorBootstrap.alert.dispose", Id); } catch (JSDisconnectedException) { @@ -34,7 +34,7 @@ protected override async ValueTask DisposeAsyncCore(bool disposing) protected override async Task OnAfterRenderAsync(bool firstRender) { if (firstRender) - await JSRuntime.InvokeVoidAsync("window.blazorBootstrap.alert.initialize", Id, objRef); + await SafeInvokeVoidAsync("window.blazorBootstrap.alert.initialize", Id, objRef); await base.OnAfterRenderAsync(firstRender); } @@ -55,7 +55,9 @@ protected override async Task OnInitializedAsync() /// /// Closes an alert by removing it from the DOM. /// - public async Task CloseAsync() => await JSRuntime.InvokeVoidAsync("window.blazorBootstrap.alert.close", Id); + [AddedVersion("1.0.0")] + [Description("Closes an alert by removing it from the DOM.")] + public async Task CloseAsync() => await SafeInvokeVoidAsync("window.blazorBootstrap.alert.close", Id); #endregion @@ -69,40 +71,53 @@ protected override async Task OnInitializedAsync() /// /// Gets or sets the content to be rendered within the component. + /// + /// Default value is . + /// /// - /// - /// Default value is null. - /// + [AddedVersion("1.0.0")] + [DefaultValue(null)] + [Description("Gets or sets the content to be rendered within the component.")] [Parameter] public RenderFragment? ChildContent { get; set; } /// /// Gets or sets the alert color. - /// - /// + /// /// Default value is . - /// + /// + /// + [AddedVersion("1.0.0")] + [DefaultValue(AlertColor.None)] + [Description("Gets or sets the alert color.")] [Parameter] public AlertColor Color { get; set; } = AlertColor.None; /// /// If , shows an inline close button. + /// + /// Default value is . + /// /// - /// - /// Default value is false. - /// + [AddedVersion("1.0.0")] + [DefaultValue(false)] + [Description("If true, shows an inline close button.")] [Parameter] public bool Dismissable { get; set; } /// /// Fires immediately when the close instance method is called. /// + [AddedVersion("1.0.0")] + [Description("Fires immediately when the close instance method is called.")] [Parameter] public EventCallback OnClose { get; set; } /// /// Fired when the alert has been closed and CSS transitions have completed. /// + [AddedVersion("1.0.0")] + [Description("Fired when the alert has been closed and CSS transitions have completed.")] [Parameter] public EventCallback OnClosed { get; set; } diff --git a/blazorbootstrap/Components/Badge/Badge.razor.cs b/blazorbootstrap/Components/Badge/Badge.razor.cs index c2f6185f8..2c4065190 100644 --- a/blazorbootstrap/Components/Badge/Badge.razor.cs +++ b/blazorbootstrap/Components/Badge/Badge.razor.cs @@ -15,57 +15,75 @@ public partial class Badge : BlazorBootstrapComponentBase /// /// Gets or sets the content to be rendered within the component. + /// + /// Default value is . + /// /// - /// - /// Default value is null. - /// + [AddedVersion("1.7.0")] + [DefaultValue(null)] + [Description("Gets or sets the content to be rendered within the component.")] [Parameter] - public RenderFragment ChildContent { get; set; } = default!; + public RenderFragment? ChildContent { get; set; } /// /// Gets or sets the badge color. - /// - /// + /// /// Default value is . - /// + /// + /// + [AddedVersion("1.7.0")] + [DefaultValue(BadgeColor.Secondary)] + [Description("Gets or sets the badge color.")] [Parameter] public BadgeColor Color { get; set; } = BadgeColor.Secondary; /// /// Gets or sets the badge indicator. - /// - /// + /// /// Default value is . - /// + /// + /// + [AddedVersion("1.7.0")] + [DefaultValue(BadgeIndicatorType.None)] + [Description("Gets or sets the badge indicator.")] [Parameter] public BadgeIndicatorType IndicatorType { get; set; } = BadgeIndicatorType.None; /// /// Gets or sets the badge placement. - /// - /// + /// /// Default value is . - /// + /// + /// + [AddedVersion("1.7.0")] + [DefaultValue(BadgePlacement.None)] + [Description("Gets or sets the badge placement.")] [Parameter] public BadgePlacement Placement { get; set; } = BadgePlacement.None; /// /// Gets or sets the badge position. - /// - /// + /// /// Default value is . - /// + /// + /// + [AddedVersion("1.7.0")] + [DefaultValue(Position.None)] + [Description("Gets or sets the badge position.")] [Parameter] public Position Position { get; set; } = Position.None; /// /// Gets or sets the visually hidden text. + /// + /// Default value is . + /// /// - /// - /// Default value is null. - /// + [AddedVersion("1.7.0")] + [DefaultValue(null)] + [Description("Gets or sets the visually hidden text.")] [Parameter] - public string VisuallyHiddenText { get; set; } = default!; + public string? VisuallyHiddenText { get; set; } #endregion } diff --git a/blazorbootstrap/Components/Breadcrumb/Breadcrumb.razor.cs b/blazorbootstrap/Components/Breadcrumb/Breadcrumb.razor.cs index d6f85617e..6d332bb83 100644 --- a/blazorbootstrap/Components/Breadcrumb/Breadcrumb.razor.cs +++ b/blazorbootstrap/Components/Breadcrumb/Breadcrumb.razor.cs @@ -37,16 +37,20 @@ private void OnNotify(List items) #region Properties, Indexers - [Inject] private BreadcrumbService BreadcrumbService { get; set; } = default!; + [Inject] + private BreadcrumbService BreadcrumbService { get; set; } = default!; /// /// Gets or sets the items. /// /// - /// Default value is null. + /// Default value is . /// + [AddedVersion("1.0.0")] + [DefaultValue(null)] + [Description("Gets or sets the items.")] [Parameter] - public List Items { get; set; } = default!; + public List? Items { get; set; } #endregion } diff --git a/blazorbootstrap/Components/Button/Button.razor.cs b/blazorbootstrap/Components/Button/Button.razor.cs index 151931a8e..43968a69e 100644 --- a/blazorbootstrap/Components/Button/Button.razor.cs +++ b/blazorbootstrap/Components/Button/Button.razor.cs @@ -4,7 +4,7 @@ public partial class Button : BlazorBootstrapComponentBase { #region Fields and Constants - private bool isFirstRenderComplete = false; + private bool isFirstRenderComplete; private bool previousActive; @@ -14,15 +14,15 @@ public partial class Button : BlazorBootstrapComponentBase private Target previousTarget; - private string? previousTo = default!; + private string? previousTo; - private TooltipColor previousTooltipColor = default!; + private TooltipColor previousTooltipColor; - private string previousTooltipTitle = default!; + private string? previousTooltipTitle; private ButtonType previousType; - private bool setButtonAttributesAgain = false; + private bool setButtonAttributesAgain; #endregion @@ -143,6 +143,8 @@ protected override async Task OnParametersSetAsync() /// /// Hides the loading state and enables the button. /// + [AddedVersion("1.0.0")] + [Description("Hides the loading state and enables the button.")] public void HideLoading() { Loading = false; @@ -154,6 +156,8 @@ public void HideLoading() /// Shows the loading state and disables the button. /// /// + [AddedVersion("1.0.0")] + [Description("Shows the loading state and disables the button.")] public void ShowLoading(string text = "") { LoadingText = text; @@ -296,19 +300,25 @@ private void SetAttributes() /// /// Gets or sets the button active state. + /// + /// Default value is . + /// /// - /// - /// Default value is false. - /// + [AddedVersion("1.0.0")] + [DefaultValue(false)] + [Description("Gets or sets the button active state.")] [Parameter] public bool Active { get; set; } /// /// Gets or sets the block level button. + /// + /// Default value is . + /// /// - /// - /// Default value is false. - /// + [AddedVersion("1.0.0")] + [DefaultValue(false)] + [Description("Gets or sets the block level button.")] [Parameter] public bool Block { get; set; } @@ -316,147 +326,194 @@ private void SetAttributes() /// /// Gets or sets the content to be rendered within the component. + /// + /// Default value is . + /// /// - /// - /// Default value is null. - /// + [AddedVersion("1.0.0")] + [DefaultValue(null)] + [Description("Gets or sets the content to be rendered within the component.")] [Parameter] - public RenderFragment ChildContent { get; set; } = default!; + public RenderFragment? ChildContent { get; set; } /// /// Gets or sets the button color. - /// - /// + /// /// Default value is . - /// + /// + /// + [AddedVersion("1.0.0")] + [DefaultValue(ButtonColor.None)] + [Description("Gets or sets the button color.")] [Parameter] public ButtonColor Color { get; set; } = ButtonColor.None; /// /// Gets or sets the button disabled state. + /// + /// Default value is . + /// /// - /// - /// Default value is false. - /// + [AddedVersion("1.0.0")] + [DefaultValue(false)] + [Description("Gets or sets the button disabled state.")] [Parameter] public bool Disabled { get; set; } /// /// If , shows the loading spinner or a . + /// + /// Default value is . + /// /// - /// - /// Default value is false. - /// + [AddedVersion("1.0.0")] + [DefaultValue(false)] + [Description("If true, shows the loading spinner or a LoadingTemplate.")] [Parameter] public bool Loading { get; set; } /// /// Gets or sets the button loading template. + /// + /// Default value is . + /// /// - /// - /// Default value is null. - /// + [AddedVersion("1.0.0")] + [DefaultValue(null)] + [Description("Gets or sets the button loading template.")] [Parameter] - public RenderFragment LoadingTemplate { get; set; } = default!; + public RenderFragment? LoadingTemplate { get; set; } /// - /// Gets or sets the loading text. - /// takes precedence. - /// - /// + /// Gets or sets the loading text. takes precedence. + /// /// Default value is 'Loading...'. - /// + /// + /// + [AddedVersion("1.0.0")] + [DefaultValue("Loading...")] + [Description("Gets or sets the loading text. LoadingTemplate takes precedence.")] [Parameter] public string LoadingText { get; set; } = "Loading..."; /// /// Gets or sets the button outline. + /// + /// Default value is . + /// /// - /// - /// Default value is false. - /// + [AddedVersion("1.0.0")] + [DefaultValue(false)] + [Description("Gets or sets the button outline.")] [Parameter] public bool Outline { get; set; } /// /// Gets or sets the position. /// Use to modify a and position it in the corner of a link or button. - /// - /// + /// /// Default value is . - /// + /// + /// + [AddedVersion("1.0.0")] + [DefaultValue(Position.None)] + [Description("Gets or sets the position. Use Position to modify a Badge and position it in the corner of a link or button.")] [Parameter] public Position Position { get; set; } = Position.None; /// /// Gets or sets the button size. - /// - /// + /// /// Default value is . - /// + /// + /// + [AddedVersion("1.0.0")] + [DefaultValue(ButtonSize.None)] + [Description("Gets or sets the button size.")] [Parameter] public ButtonSize Size { get; set; } = ButtonSize.None; /// /// Gets or sets the button tab index. + /// + /// Default value is . + /// /// - /// - /// Default value is null. - /// + [AddedVersion("1.0.0")] + [DefaultValue(null)] + [Description("Gets or sets the button tab index.")] [Parameter] public int? TabIndex { get; set; } /// /// Gets or sets the link button target. - /// - /// + /// /// Default value is - /// + /// + /// + [AddedVersion("1.0.0")] + [DefaultValue(Target.None)] + [Description("Gets or sets the link button target.")] [Parameter] public Target Target { get; set; } = Target.None; /// /// Gets or sets the link button href attribute. + /// + /// Default value is . + /// /// - /// - /// Default value is null. - /// + [AddedVersion("1.0.0")] + [DefaultValue(null)] + [Description("Gets or sets the link button href attribute.")] [Parameter] public string? To { get; set; } /// /// Gets or sets the button tooltip color. - /// - /// + /// /// Default value is . - /// + /// + /// + [AddedVersion("1.10.0")] + [DefaultValue(TooltipColor.None)] + [Description("Gets or sets the button tooltip color.")] [Parameter] public TooltipColor TooltipColor { get; set; } = TooltipColor.None; /// /// Gets or sets the button tooltip placement. - /// - /// + /// /// Default value is . - /// + /// + /// + [AddedVersion("1.0.0")] + [DefaultValue(TooltipPlacement.Top)] + [Description("Gets or sets the button tooltip placement.")] [Parameter] public TooltipPlacement TooltipPlacement { get; set; } = TooltipPlacement.Top; /// /// Gets or sets the button tooltip title. + /// + /// Default value is . + /// /// - /// - /// Default value is null. - /// + [AddedVersion("1.0.0")] + [DefaultValue(null)] + [Description("Gets or sets the button tooltip title.")] [Parameter] - public string TooltipTitle { get; set; } = default!; + public string? TooltipTitle { get; set; } /// /// Gets or sets the button type. - /// - /// + /// /// Default value is . - /// + /// + /// + [AddedVersion("1.0.0")] + [DefaultValue(ButtonType.Button)] + [Description("Gets or sets the button type.")] [Parameter] public ButtonType Type { get; set; } = ButtonType.Button; diff --git a/blazorbootstrap/Components/Callout/Callout.razor.cs b/blazorbootstrap/Components/Callout/Callout.razor.cs index ba887cc60..1f716ba20 100644 --- a/blazorbootstrap/Components/Callout/Callout.razor.cs +++ b/blazorbootstrap/Components/Callout/Callout.razor.cs @@ -46,8 +46,11 @@ private IconName GetIconName() => /// Gets or sets the content to be rendered within the component. /// /// - /// Default value is null. + /// Default value is . /// + [AddedVersion("1.0.0")] + [DefaultValue(null)] + [Description("Gets or sets the content to be rendered within the component.")] [Parameter] public RenderFragment? ChildContent { get; set; } @@ -57,6 +60,9 @@ private IconName GetIconName() => /// /// Default value is . /// + [AddedVersion("1.0.0")] + [DefaultValue(CalloutColor.Default)] + [Description("Gets or sets the callout color.")] [Parameter] public CalloutColor Color { get; set; } = CalloutColor.Default; @@ -66,8 +72,11 @@ private IconName GetIconName() => /// Gets or sets the callout heading. /// /// - /// Default value is null. + /// Default value is . /// + [AddedVersion("1.0.0")] + [DefaultValue(null)] + [Description("Gets or sets the callout heading.")] [Parameter] public string? Heading { get; set; } @@ -75,8 +84,11 @@ private IconName GetIconName() => /// Gets or sets a value indicating whether to hide the callout heading. /// /// - /// Default value is false. + /// Default value is . /// + [AddedVersion("1.0.0")] + [DefaultValue(false)] + [Description("Gets or sets a value indicating whether to hide the callout heading.")] [Parameter] public bool HideHeading { get; set; } diff --git a/blazorbootstrap/Components/Card/Card.razor.cs b/blazorbootstrap/Components/Card/Card.razor.cs index 5a70e24d4..a7b369bbf 100644 --- a/blazorbootstrap/Components/Card/Card.razor.cs +++ b/blazorbootstrap/Components/Card/Card.razor.cs @@ -12,28 +12,37 @@ public partial class Card : BlazorBootstrapComponentBase /// /// Gets or sets the content to be rendered within the component. + /// + /// Default value is . + /// /// - /// - /// Default value is null. - /// + [AddedVersion("1.10.0")] + [DefaultValue(null)] + [Description("Gets or sets the content to be rendered within the component.")] [Parameter] - public RenderFragment ChildContent { get; set; } = default!; + public RenderFragment? ChildContent { get; set; } /// /// Gets or sets the card color. - /// - /// + /// /// Default value is . - /// + /// + /// + [AddedVersion("1.10.0")] + [DefaultValue(CardColor.None)] + [Description("Gets or sets the card color.")] [Parameter] public CardColor Color { get; set; } = CardColor.None; /// /// Gets or sets the text alignment of the card. - /// - /// + /// /// Default value is . - /// + /// + /// + [AddedVersion("1.10.0")] + [DefaultValue(Alignment.None)] + [Description("Gets or sets the text alignment of the card.")] [Parameter] public Alignment TextAlignment { get; set; } = Alignment.None; diff --git a/blazorbootstrap/Components/Card/CardBody.razor.cs b/blazorbootstrap/Components/Card/CardBody.razor.cs index 7a51b799e..b7c31045b 100644 --- a/blazorbootstrap/Components/Card/CardBody.razor.cs +++ b/blazorbootstrap/Components/Card/CardBody.razor.cs @@ -9,12 +9,15 @@ public partial class CardBody : BlazorBootstrapComponentBase /// /// Gets or sets the content to be rendered within the component. + /// + /// Default value is . + /// /// - /// - /// Default value is null. - /// + [AddedVersion("1.10.0")] + [DefaultValue(null)] + [Description("Gets or sets the content to be rendered within the component.")] [Parameter] - public RenderFragment ChildContent { get; set; } = default!; + public RenderFragment? ChildContent { get; set; } #endregion } diff --git a/blazorbootstrap/Components/Card/CardFooter.razor.cs b/blazorbootstrap/Components/Card/CardFooter.razor.cs index 44164ddc4..eb23d021c 100644 --- a/blazorbootstrap/Components/Card/CardFooter.razor.cs +++ b/blazorbootstrap/Components/Card/CardFooter.razor.cs @@ -9,12 +9,15 @@ public partial class CardFooter : BlazorBootstrapComponentBase /// /// Gets or sets the content to be rendered within the component. + /// + /// Default value is . + /// /// - /// - /// Default value is null. - /// + [AddedVersion("1.10.0")] + [DefaultValue(null)] + [Description("Gets or sets the content to be rendered within the component.")] [Parameter] - public RenderFragment ChildContent { get; set; } = default!; + public RenderFragment? ChildContent { get; set; } #endregion } diff --git a/blazorbootstrap/Components/Card/CardGroup.razor.cs b/blazorbootstrap/Components/Card/CardGroup.razor.cs index c9c2c0b9c..f271b7cea 100644 --- a/blazorbootstrap/Components/Card/CardGroup.razor.cs +++ b/blazorbootstrap/Components/Card/CardGroup.razor.cs @@ -9,12 +9,15 @@ public partial class CardGroup : BlazorBootstrapComponentBase /// /// Gets or sets the content to be rendered within the component. + /// + /// Default value is . + /// /// - /// - /// Default value is null. - /// + [AddedVersion("1.10.0")] + [DefaultValue(null)] + [Description("Gets or sets the content to be rendered within the component.")] [Parameter] - public RenderFragment ChildContent { get; set; } = default!; + public RenderFragment? ChildContent { get; set; } #endregion } diff --git a/blazorbootstrap/Components/Card/CardHeader.razor.cs b/blazorbootstrap/Components/Card/CardHeader.razor.cs index 33721e8af..ab4cc7f7a 100644 --- a/blazorbootstrap/Components/Card/CardHeader.razor.cs +++ b/blazorbootstrap/Components/Card/CardHeader.razor.cs @@ -11,16 +11,25 @@ public partial class CardHeader : BlazorBootstrapComponentBase /// /// Gets or sets the content to be rendered within the component. + /// + /// Default value is . + /// /// + [AddedVersion("1.10.0")] + [DefaultValue(null)] + [Description("Gets or sets the content to be rendered within the component.")] [Parameter] - public RenderFragment ChildContent { get; set; } = default!; + public RenderFragment? ChildContent { get; set; } /// /// Gets or sets the card header color. - /// - /// + /// /// Default value is . - /// + /// + /// + [AddedVersion("1.10.0")] + [DefaultValue(CardColor.None)] + [Description("Gets or sets the card header color.")] [Parameter] public CardColor Color { get; set; } = CardColor.None; diff --git a/blazorbootstrap/Components/Card/CardLink.razor.cs b/blazorbootstrap/Components/Card/CardLink.razor.cs index fb5c509e0..992db65fc 100644 --- a/blazorbootstrap/Components/Card/CardLink.razor.cs +++ b/blazorbootstrap/Components/Card/CardLink.razor.cs @@ -113,25 +113,37 @@ private void SetAttributes() /// /// Gets or sets the content to be rendered within the component. + /// + /// Default value is . + /// /// + [AddedVersion("1.10.0")] + [DefaultValue(null)] + [Description("Gets or sets the content to be rendered within the component.")] [Parameter] - public RenderFragment ChildContent { get; set; } = default!; + public RenderFragment? ChildContent { get; set; } /// /// If , disables the card link. /// - /// - /// Default value is false. - /// + /// + /// Default value is . + /// + [AddedVersion("1.10.0")] + [DefaultValue(false)] + [Description("If true, disables the card link.")] [Parameter] public bool Disabled { get; set; } /// /// Gets or sets the card link tab index. /// - /// - /// Default value is null. - /// + /// + /// Default value is . + /// + [AddedVersion("1.10.0")] + [DefaultValue(null)] + [Description("Gets or sets the card link tab index.")] [Parameter] public int? TabIndex { get; set; } @@ -141,6 +153,9 @@ private void SetAttributes() /// /// Default value is . /// + [AddedVersion("1.10.0")] + [DefaultValue(Target.None)] + [Description("Gets or sets the card link target.")] [Parameter] public Target Target { get; set; } = Target.None; @@ -148,8 +163,11 @@ private void SetAttributes() /// Gets or sets the link href attribute. /// /// - /// Default value is null. + /// Default value is . /// + [AddedVersion("1.10.0")] + [DefaultValue(null)] + [Description("Gets or sets the link href attribute.")] [Parameter] public string? To { get; set; } diff --git a/blazorbootstrap/Components/Card/CardSubTitle.razor.cs b/blazorbootstrap/Components/Card/CardSubTitle.razor.cs index 4dd642cb5..206f98bed 100644 --- a/blazorbootstrap/Components/Card/CardSubTitle.razor.cs +++ b/blazorbootstrap/Components/Card/CardSubTitle.razor.cs @@ -9,9 +9,15 @@ public partial class CardSubTitle : BlazorBootstrapComponentBase /// /// Gets or sets the content to be rendered within the component. + /// + /// Default value is . + /// /// + [AddedVersion("1.10.0")] + [DefaultValue(null)] + [Description("Gets or sets the content to be rendered within the component.")] [Parameter] - public RenderFragment ChildContent { get; set; } = default!; + public RenderFragment? ChildContent { get; set; } /// /// Gets or sets the card sub title size. @@ -19,6 +25,9 @@ public partial class CardSubTitle : BlazorBootstrapComponentBase /// /// Default value is . /// + [AddedVersion("1.10.0")] + [DefaultValue(HeadingSize.H6)] + [Description("Gets or sets the card sub title size.")] [Parameter] public HeadingSize Size { get; set; } = HeadingSize.H6; diff --git a/blazorbootstrap/Components/Card/CardText.razor.cs b/blazorbootstrap/Components/Card/CardText.razor.cs index 1e83a8a3e..206f3cdb0 100644 --- a/blazorbootstrap/Components/Card/CardText.razor.cs +++ b/blazorbootstrap/Components/Card/CardText.razor.cs @@ -9,9 +9,15 @@ public partial class CardText : BlazorBootstrapComponentBase /// /// Gets or sets the content to be rendered within the component. + /// + /// Default value is . + /// /// + [AddedVersion("1.10.0")] + [DefaultValue(null)] + [Description("Gets or sets the content to be rendered within the component.")] [Parameter] - public RenderFragment ChildContent { get; set; } = default!; + public RenderFragment? ChildContent { get; set; } #endregion } diff --git a/blazorbootstrap/Components/Card/CardTitle.razor.cs b/blazorbootstrap/Components/Card/CardTitle.razor.cs index 724bca063..928f3a201 100644 --- a/blazorbootstrap/Components/Card/CardTitle.razor.cs +++ b/blazorbootstrap/Components/Card/CardTitle.razor.cs @@ -9,9 +9,15 @@ public partial class CardTitle : BlazorBootstrapComponentBase /// /// Gets or sets the content to be rendered within the component. + /// + /// Default value is . + /// /// + [AddedVersion("1.10.0")] + [DefaultValue(null)] + [Description("Gets or sets the content to be rendered within the component.")] [Parameter] - public RenderFragment ChildContent { get; set; } = default!; + public RenderFragment? ChildContent { get; set; } /// /// Gets or sets the card title size. @@ -19,6 +25,9 @@ public partial class CardTitle : BlazorBootstrapComponentBase /// /// Default value is . /// + [AddedVersion("1.10.0")] + [DefaultValue(HeadingSize.H5)] + [Description("Gets or sets the card title size.")] [Parameter] public HeadingSize Size { get; set; } = HeadingSize.H5; diff --git a/blazorbootstrap/Components/Carousel/Carousel.razor.cs b/blazorbootstrap/Components/Carousel/Carousel.razor.cs index 83effeea5..bbf5fff67 100644 --- a/blazorbootstrap/Components/Carousel/Carousel.razor.cs +++ b/blazorbootstrap/Components/Carousel/Carousel.razor.cs @@ -30,7 +30,7 @@ protected override async ValueTask DisposeAsyncCore(bool disposing) try { if (IsRenderComplete) - await JSRuntime.InvokeVoidAsync(CarouselInterop.Dispose, Id); + await SafeInvokeVoidAsync(CarouselInterop.Dispose, Id); } catch (JSDisconnectedException) { @@ -48,7 +48,7 @@ protected override async Task OnAfterRenderAsync(bool firstRender) if (firstRender) { CarouselOptions options = new() { Interval = Interval, Keyboard = Keyboard, Ride = Autoplay.ToCarouselAutoPlayString(), Touch = Touch }; - await JSRuntime.InvokeVoidAsync(CarouselInterop.Initialize, Id, options, objRef); + await SafeInvokeVoidAsync(CarouselInterop.Initialize, Id, options, objRef); StateHasChanged(); // Required } @@ -80,12 +80,14 @@ public async Task bslide(CarouselEventArgs args) /// Shows by index. /// /// + [AddedVersion("3.0.0")] + [Description("Shows CarouselItem by index.")] public ValueTask ShowItemByIndexAsync(int index) { if (!isDefaultActiveCarouselItemSet) isDefaultActiveCarouselItemSet = true; - return JSRuntime.InvokeVoidAsync(CarouselInterop.To, Id, index); + return new(SafeInvokeVoidAsync(CarouselInterop.To, Id, index)); } internal void AddItem(CarouselItem carouselItem) @@ -99,28 +101,34 @@ internal void AddItem(CarouselItem carouselItem) /// /// Shows next . /// - public ValueTask PauseCarouselAsync() => JSRuntime.InvokeVoidAsync(CarouselInterop.Pause, Id); + [AddedVersion("3.0.0")] + [Description("Shows next CarouselItem.")] + public ValueTask PauseCarouselAsync() => new(SafeInvokeVoidAsync(CarouselInterop.Pause, Id)); /// /// Shows next . /// + [AddedVersion("3.0.0")] + [Description("Shows next CarouselItem.")] public ValueTask ShowNextItemAsync() { var nextIndex = activeIndex + 1; activeIndex = nextIndex > items.Count - 1 ? 0 : nextIndex; - return JSRuntime.InvokeVoidAsync(CarouselInterop.Next, Id); + return new(SafeInvokeVoidAsync(CarouselInterop.Next, Id)); } /// /// Shows previous . /// + [AddedVersion("3.0.0")] + [Description("Shows previous CarouselItem.")] public ValueTask ShowPreviousItemAsync() { var previousIndex = activeIndex - 1; activeIndex = previousIndex < 0 ? items.Count - 1 : previousIndex; - return JSRuntime.InvokeVoidAsync(CarouselInterop.Previous, Id); + return new(SafeInvokeVoidAsync(CarouselInterop.Previous, Id)); } #endregion @@ -137,28 +145,37 @@ public ValueTask ShowPreviousItemAsync() /// /// Controls the autoplay behavior of the carousel. - /// - /// + /// /// Default value is . - /// + /// + /// + [AddedVersion("3.0.0")] + [DefaultValue(CarouselAutoPlay.None)] + [Description("Controls the autoplay behavior of the carousel.")] [Parameter] public CarouselAutoPlay Autoplay { get; set; } = CarouselAutoPlay.None; /// /// Gets or sets the content to be rendered within the component. + /// + /// Default value is . + /// /// - /// - /// Default value is null. - /// + [AddedVersion("3.0.0")] + [DefaultValue(null)] + [Description("Gets or sets the content to be rendered within the component.")] [Parameter] public RenderFragment? ChildContent { get; set; } /// /// Determines whether to use a crossfade effect when transitioning between slides. - /// - /// + /// /// Default value is . - /// + /// + /// + [AddedVersion("3.0.0")] + [DefaultValue(false)] + [Description("Determines whether to use a crossfade effect when transitioning between slides.")] [Parameter] public bool Crossfade { get; set; } @@ -166,61 +183,80 @@ public ValueTask ShowPreviousItemAsync() /// /// The amount of time to delay between automatically cycling an item. - /// - /// + /// /// Default value is 5000 milliseconds. - /// + /// + /// + [AddedVersion("3.0.0")] + [DefaultValue(5000)] + [Description("The amount of time to delay between automatically cycling an item.")] [Parameter] - public int? Interval { get; set; } = 5000; + public int Interval { get; set; } = 5000; private int ItemCount => items.Count; /// /// Whether the carousel should react to keyboard events. - /// - /// + /// /// Default value is . - /// + /// + /// + [AddedVersion("3.0.0")] + [DefaultValue(true)] + [Description("Whether the carousel should react to keyboard events.")] [Parameter] public bool Keyboard { get; set; } = true; /// /// Fired when the carousel has completed its slide transition. /// + [AddedVersion("3.0.0")] + [Description("Fired when the carousel has completed its slide transition.")] [Parameter] public EventCallback Onslid { get; set; } /// /// Fires immediately when the slide instance method is invoked. /// + [AddedVersion("3.0.0")] + [Description("Fires immediately when the slide instance method is invoked.")] [Parameter] public EventCallback Onslide { get; set; } /// /// Indicates whether to show indicators (dots) below the carousel to navigate between slides. - /// - /// + /// /// Default value is . - /// + /// + /// + [AddedVersion("3.0.0")] + [DefaultValue(false)] + [Description("Indicates whether to show indicators (dots) below the carousel to navigate between slides.")] [Parameter] public bool ShowIndicators { get; set; } /// /// Specifies whether to display the previous and next controls (arrows) for navigating slides. - /// - /// + /// /// Default value is . - /// + /// + /// + [AddedVersion("3.0.0")] + [DefaultValue(true)] + [Description("Specifies whether to display the previous and next controls (arrows) for navigating slides.")] [Parameter] public bool ShowPreviousNextControls { get; set; } = true; /// /// Carousels support swiping left/right on touchscreen devices to move between slides. /// This can be disabled by setting the parameter to . - /// - /// + /// /// Default value is . - /// + /// + /// + [AddedVersion("3.0.0")] + [DefaultValue(true)] + [Description("Carousels support swiping left/right on touchscreen devices to move between slides. This can be disabled by setting the Touch parameter to false.")] [Parameter] public bool Touch { get; set; } = true; diff --git a/blazorbootstrap/Components/Carousel/CarouselCaption.razor.cs b/blazorbootstrap/Components/Carousel/CarouselCaption.razor.cs index fc1959f09..f17fc0c49 100644 --- a/blazorbootstrap/Components/Carousel/CarouselCaption.razor.cs +++ b/blazorbootstrap/Components/Carousel/CarouselCaption.razor.cs @@ -14,10 +14,13 @@ public partial class CarouselCaption : BlazorBootstrapComponentBase /// /// Gets or sets the content to be rendered within the component. - /// - /// + /// /// Default value is . - /// + /// + /// + [AddedVersion("3.0.0")] + [DefaultValue(null)] + [Description("Gets or sets the content to be rendered within the component.")] [Parameter] public RenderFragment? ChildContent { get; set; } diff --git a/blazorbootstrap/Components/Carousel/CarouselItem.razor.cs b/blazorbootstrap/Components/Carousel/CarouselItem.razor.cs index 14a21c0b1..8892c33b5 100644 --- a/blazorbootstrap/Components/Carousel/CarouselItem.razor.cs +++ b/blazorbootstrap/Components/Carousel/CarouselItem.razor.cs @@ -24,34 +24,49 @@ protected override async Task OnInitializedAsync() /// /// Gets or sets the active state. - /// - /// + /// /// Default value is . - /// + /// + /// + [AddedVersion("3.0.0")] + [DefaultValue(false)] + [Description("Gets or sets the active state.")] [Parameter] public bool Active { get; set; } /// /// Gets or sets the content to be rendered within the component. - /// - /// + /// /// Default value is . - /// + /// + /// + [AddedVersion("3.0.0")] + [DefaultValue(null)] + [Description("Gets or sets the content to be rendered within the component.")] [Parameter] public RenderFragment? ChildContent { get; set; } /// /// The amount of time to delay between automatically cycling an item. + /// + /// Default value is 5000 milliseconds. + /// /// - /// - /// Default value is 5000. - /// + [AddedVersion("3.0.0")] + [DefaultValue(5000)] + [Description("The amount of time to delay between automatically cycling an item.")] [Parameter] - public int? Interval { get; set; } = 5000; + public int Interval { get; set; } = 5000; /// /// Gets or sets the aria-label. + /// + /// Default value is . + /// /// + [AddedVersion("3.0.0")] + [DefaultValue(null)] + [Description("Gets or sets the aria-label.")] [Parameter] public string? Label { get; set; } diff --git a/blazorbootstrap/Components/Charts/BarChart.razor b/blazorbootstrap/Components/Charts/BarChart.razor deleted file mode 100644 index da05c573a..000000000 --- a/blazorbootstrap/Components/Charts/BarChart.razor +++ /dev/null @@ -1,6 +0,0 @@ -@namespace BlazorBootstrap -@inherits BlazorBootstrapChart - -
    - -
    diff --git a/blazorbootstrap/Components/Charts/BarChart.razor.cs b/blazorbootstrap/Components/Charts/BarChart.razor.cs deleted file mode 100644 index c48a934f2..000000000 --- a/blazorbootstrap/Components/Charts/BarChart.razor.cs +++ /dev/null @@ -1,129 +0,0 @@ -namespace BlazorBootstrap; - -public partial class BarChart : BlazorBootstrapChart -{ - #region Fields and Constants - - private const string _jsObjectName = "window.blazorChart.bar"; - - #endregion - - #region Constructors - - public BarChart() - { - chartType = ChartType.Bar; - } - - #endregion - - #region Methods - - public override async Task AddDataAsync(ChartData chartData, string dataLabel, IChartDatasetData data) - { - if (chartData is null) - throw new ArgumentNullException(nameof(chartData)); - - if (chartData.Datasets is null) - throw new ArgumentNullException(nameof(chartData.Datasets)); - - if (data is null) - throw new ArgumentNullException(nameof(data)); - - foreach (var dataset in chartData.Datasets) - if (dataset is BarChartDataset barChartDataset && barChartDataset.Label == dataLabel) - if (data is BarChartDatasetData barChartDatasetData) - barChartDataset.Data?.Add(barChartDatasetData.Data as double?); - - await JSRuntime.InvokeVoidAsync($"{_jsObjectName}.addDatasetData", Id, dataLabel, data); - - return chartData; - } - - public override async Task AddDataAsync(ChartData chartData, string dataLabel, IReadOnlyCollection data) - { - if (chartData is null) - throw new ArgumentNullException(nameof(chartData)); - - if (chartData.Datasets is null) - throw new ArgumentNullException(nameof(chartData.Datasets)); - - if (chartData.Labels is null) - throw new ArgumentNullException(nameof(chartData.Labels)); - - if (dataLabel is null) - throw new ArgumentNullException(nameof(dataLabel)); - - if (string.IsNullOrWhiteSpace(dataLabel)) - throw new Exception($"{nameof(dataLabel)} cannot be empty."); - - if (data is null) - throw new ArgumentNullException(nameof(data)); - - if (!data.Any()) - throw new Exception($"{nameof(data)} cannot be empty."); - - if (chartData.Datasets.Count != data.Count) - throw new InvalidDataException("The chart dataset count and the new data points count do not match."); - - if (chartData.Labels.Contains(dataLabel)) - throw new Exception($"{dataLabel} already exists."); - - chartData.Labels.Add(dataLabel); - - foreach (var dataset in chartData.Datasets) - if (dataset is BarChartDataset barChartDataset) - { - var chartDatasetData = data.FirstOrDefault(x => x is BarChartDatasetData barChartDatasetData && barChartDatasetData.DatasetLabel == barChartDataset.Label); - - if (chartDatasetData is BarChartDatasetData barChartDatasetData) - barChartDataset.Data?.Add(barChartDatasetData.Data as double?); - } - - await JSRuntime.InvokeVoidAsync($"{_jsObjectName}.addDatasetsData", Id, dataLabel, data?.Select(x => (BarChartDatasetData)x)); - - return chartData; - } - - public override async Task AddDatasetAsync(ChartData chartData, IChartDataset chartDataset, IChartOptions chartOptions) - { - if (chartData is null) - throw new ArgumentNullException(nameof(chartData)); - - if (chartData.Datasets is null) - throw new ArgumentNullException(nameof(chartData.Datasets)); - - if (chartDataset is null) - throw new ArgumentNullException(nameof(chartDataset)); - - if (chartDataset is BarChartDataset) - { - chartData.Datasets.Add(chartDataset); - await JSRuntime.InvokeVoidAsync($"{_jsObjectName}.addDataset", Id, (BarChartDataset)chartDataset); - } - - return chartData; - } - - public override async Task InitializeAsync(ChartData chartData, IChartOptions chartOptions, string[]? plugins = null) - { - if (chartData is not null && chartData.Datasets is not null) - { - var datasets = chartData.Datasets.OfType(); - var data = new { chartData.Labels, Datasets = datasets }; - await JSRuntime.InvokeVoidAsync($"{_jsObjectName}.initialize", Id, GetChartType(), data, (BarChartOptions)chartOptions, plugins); - } - } - - public override async Task UpdateAsync(ChartData chartData, IChartOptions chartOptions) - { - if (chartData is not null && chartData.Datasets is not null) - { - var datasets = chartData.Datasets.OfType(); - var data = new { chartData.Labels, Datasets = datasets }; - await JSRuntime.InvokeVoidAsync($"{_jsObjectName}.update", Id, GetChartType(), data, (BarChartOptions)chartOptions); - } - } - - #endregion -} diff --git a/blazorbootstrap/Components/Charts/BlazorBootstrapChart.cs b/blazorbootstrap/Components/Charts/BlazorBootstrapChart.cs deleted file mode 100644 index 0bfa8781d..000000000 --- a/blazorbootstrap/Components/Charts/BlazorBootstrapChart.cs +++ /dev/null @@ -1,213 +0,0 @@ -namespace BlazorBootstrap; - -public class BlazorBootstrapChart : BlazorBootstrapComponentBase, IDisposable, IAsyncDisposable -{ - #region Fields and Constants - - internal ChartType chartType; - - #endregion - - #region Methods - - //public async Task Stop() { } - - //public async Task ToBase64Image() { } - - //public async Task ToBase64Image(string type, double quality) { } - - public virtual async Task AddDataAsync(ChartData chartData, string dataLabel, IChartDatasetData data) => await Task.FromResult(chartData); - - public virtual async Task AddDataAsync(ChartData chartData, string dataLabel, IReadOnlyCollection data) => await Task.FromResult(chartData); - - public virtual async Task AddDatasetAsync(ChartData chartData, IChartDataset chartDataset, IChartOptions chartOptions) => await Task.FromResult(chartData); - - /// - public new virtual void Dispose() => Dispose(true); - - /// - public new virtual async ValueTask DisposeAsync() - { - await DisposeAsyncCore(true); - Dispose(false); - } - - //public async Task Clear() { } - - /// - /// Initialize Bar Chart. - /// - /// - /// - /// - public virtual async Task InitializeAsync(ChartData chartData, IChartOptions chartOptions, string[]? plugins = null) - { - if (chartData is not null && chartData.Datasets is not null && chartData.Datasets.Any()) - { - var _data = GetChartDataObject(chartData); - - if (chartType == ChartType.Bar) - await JSRuntime.InvokeVoidAsync("window.blazorChart.bar.initialize", Id, GetChartType(), _data, (BarChartOptions)chartOptions, plugins); - else if (chartType == ChartType.Line) - await JSRuntime.InvokeVoidAsync("window.blazorChart.line.initialize", Id, GetChartType(), _data, (LineChartOptions)chartOptions, plugins); - else - await JSRuntime.InvokeVoidAsync("window.blazorChart.initialize", Id, GetChartType(), _data, chartOptions, plugins); - } - } - - //public async Task Render() { } - - //public async Task Reset() { } - - /// - /// Resize the chart. - /// - /// - /// - /// - /// - public async Task ResizeAsync(int width, int height, Unit widthUnit = Unit.Px, Unit heightUnit = Unit.Px) - { - var widthWithUnit = $"width:{width.ToString(CultureInfo.InvariantCulture)}{widthUnit.ToCssString()}"; - var heightWithUnit = $"height:{height.ToString(CultureInfo.InvariantCulture)}{heightUnit.ToCssString()}"; - await JSRuntime.InvokeVoidAsync("window.blazorChart.resize", Id, widthWithUnit, heightWithUnit); - } - - /// - /// Update chart by reapplying all chart data and options. - /// If animation is enabled, this will animate the datasets from scratch. - /// - /// - /// - public virtual async Task UpdateAsync(ChartData chartData, IChartOptions chartOptions) - { - if (chartData is not null && chartData.Datasets is not null && chartData.Datasets.Any()) - { - var data = GetChartDataObject(chartData); - - if (chartType == ChartType.Bar) - await JSRuntime.InvokeVoidAsync("window.blazorChart.bar.update", Id, GetChartType(), data, (BarChartOptions)chartOptions); - else if (chartType == ChartType.Line) - await JSRuntime.InvokeVoidAsync("window.blazorChart.line.update", Id, GetChartType(), data, (LineChartOptions)chartOptions); - else - await JSRuntime.InvokeVoidAsync("window.blazorChart.update", Id, GetChartType(), data, chartOptions); - } - } - - /// - /// Update only data labels and values. If animation is enabled, this will animate the datapoints. - /// Changes to the options will not be applied. - /// - /// The updated chart data. Only dataset labels and values will be applied. - public virtual async Task UpdateValuesAsync(ChartData chartData) - { - if (chartData is not null && chartData.Datasets is not null && chartData.Datasets.Any()) - { - var data = GetChartDataObject(chartData); - - if (chartType == ChartType.Bar) - await JSRuntime.InvokeVoidAsync("window.blazorChart.bar.updateDataValues", Id, data); - else if (chartType == ChartType.Line) - await JSRuntime.InvokeVoidAsync("window.blazorChart.line.updateDataValues", Id, data); - else - await JSRuntime.InvokeVoidAsync("window.blazorChart.updateDataValues", Id, data); - } - } - - protected string GetChartType() => - chartType switch - { - ChartType.Bar => "bar", - ChartType.Bubble => "bubble", - ChartType.Doughnut => "doughnut", - ChartType.Line => "line", - ChartType.Pie => "pie", - ChartType.PolarArea => "polarArea", - ChartType.Radar => "radar", - ChartType.Scatter => "scatter", - _ => "line" // default - }; - - private string GetChartContainerSizeAsStyle() - { - var style = ""; - - if (Width > 0) - style += $"width:{Width.Value.ToString(CultureInfo.InvariantCulture)}{WidthUnit.ToCssString()};"; - - if (Height > 0) - style += $"height:{Height.Value.ToString(CultureInfo.InvariantCulture)}{HeightUnit.ToCssString()};"; - - return style; - } - - private object GetChartDataObject(ChartData chartData) - { - var datasets = new List(); - - if (chartData?.Datasets?.Any() ?? false) - foreach (var dataset in chartData.Datasets) - if (dataset is BarChartDataset) - datasets.Add((BarChartDataset)dataset); - else if (dataset is DoughnutChartDataset) - datasets.Add((DoughnutChartDataset)dataset); - else if (dataset is LineChartDataset) - datasets.Add((LineChartDataset)dataset); - else if (dataset is PieChartDataset) - datasets.Add((PieChartDataset)dataset); - else if (dataset is PolarAreaChartDataset) - datasets.Add((PolarAreaChartDataset)dataset); - - var data = new { chartData?.Labels, Datasets = datasets }; - - return data; - } - - #endregion - - #region Properties, Indexers - - internal string ContainerStyle => GetChartContainerSizeAsStyle(); - - /// - /// Gets or sets chart container height. - /// The default unit of measure is . - /// To change the unit of measure see . - /// - /// - /// Default value is null. - /// - [Parameter] - public int? Height { get; set; } - - /// - /// Gets or sets chart container height unit of measure. - /// - /// - /// Default value is . - /// - [Parameter] - public Unit HeightUnit { get; set; } = Unit.Px; - - /// - /// Get or sets chart container width. - /// The default unit of measure is . - /// To change the unit of measure see . - /// - /// - /// Default value is null. - /// - [Parameter] - public int? Width { get; set; } - - /// - /// Gets or sets chart container width unit of measure. - /// - /// - /// Default value is . - /// - [Parameter] - public Unit WidthUnit { get; set; } = Unit.Px; - - #endregion -} diff --git a/blazorbootstrap/Components/Charts/DoughnutChart.razor b/blazorbootstrap/Components/Charts/DoughnutChart.razor deleted file mode 100644 index da05c573a..000000000 --- a/blazorbootstrap/Components/Charts/DoughnutChart.razor +++ /dev/null @@ -1,6 +0,0 @@ -@namespace BlazorBootstrap -@inherits BlazorBootstrapChart - -
    - -
    diff --git a/blazorbootstrap/Components/Charts/DoughnutChart.razor.cs b/blazorbootstrap/Components/Charts/DoughnutChart.razor.cs deleted file mode 100644 index 6119d6da7..000000000 --- a/blazorbootstrap/Components/Charts/DoughnutChart.razor.cs +++ /dev/null @@ -1,135 +0,0 @@ -namespace BlazorBootstrap; - -public partial class DoughnutChart : BlazorBootstrapChart -{ - #region Fields and Constants - - private const string _jsObjectName = "window.blazorChart.doughnut"; - - #endregion - - #region Constructors - - public DoughnutChart() - { - chartType = ChartType.Doughnut; - } - - #endregion - - #region Methods - - public override async Task AddDataAsync(ChartData chartData, string dataLabel, IChartDatasetData data) - { - if (chartData is null) - throw new ArgumentNullException(nameof(chartData)); - - if (chartData.Datasets is null) - throw new ArgumentNullException(nameof(chartData.Datasets)); - - if (data is null) - throw new ArgumentNullException(nameof(data)); - - foreach (var dataset in chartData.Datasets) - if (dataset is DoughnutChartDataset doughnutChartDataset && doughnutChartDataset.Label == dataLabel) - if (data is DoughnutChartDatasetData doughnutChartDatasetData) - { - doughnutChartDataset.Data?.Add(doughnutChartDatasetData.Data as double?); - doughnutChartDataset.BackgroundColor?.Add(doughnutChartDatasetData.BackgroundColor!); - } - - await JSRuntime.InvokeVoidAsync($"{_jsObjectName}.addDatasetData", Id, dataLabel, data); - - return chartData; - } - - public override async Task AddDataAsync(ChartData chartData, string dataLabel, IReadOnlyCollection data) - { - if (chartData is null) - throw new ArgumentNullException(nameof(chartData)); - - if (chartData.Datasets is null) - throw new ArgumentNullException(nameof(chartData.Datasets)); - - if (chartData.Labels is null) - throw new ArgumentNullException(nameof(chartData.Labels)); - - if (dataLabel is null) - throw new ArgumentNullException(nameof(dataLabel)); - - if (string.IsNullOrWhiteSpace(dataLabel)) - throw new Exception($"{nameof(dataLabel)} cannot be empty."); - - if (data is null) - throw new ArgumentNullException(nameof(data)); - - if (!data.Any()) - throw new Exception($"{nameof(data)} cannot be empty."); - - if (chartData.Datasets.Count != data.Count) - throw new InvalidDataException("The chart dataset count and the new data points count do not match."); - - if (chartData.Labels.Contains(dataLabel)) - throw new Exception($"{dataLabel} already exists."); - - chartData.Labels.Add(dataLabel); - - foreach (var dataset in chartData.Datasets) - if (dataset is DoughnutChartDataset doughnutChartDataset) - { - var chartDatasetData = data.FirstOrDefault(x => x is DoughnutChartDatasetData doughnutChartDatasetData && doughnutChartDatasetData.DatasetLabel == doughnutChartDataset.Label); - - if (chartDatasetData is DoughnutChartDatasetData doughnutChartDatasetData) - { - doughnutChartDataset.Data?.Add(doughnutChartDatasetData.Data as double?); - doughnutChartDataset.BackgroundColor?.Add(doughnutChartDatasetData.BackgroundColor!); - } - } - - await JSRuntime.InvokeVoidAsync($"{_jsObjectName}.addDatasetsData", Id, dataLabel, data?.Select(x => (DoughnutChartDatasetData)x)); - - return chartData; - } - - public override async Task AddDatasetAsync(ChartData chartData, IChartDataset chartDataset, IChartOptions chartOptions) - { - if (chartData is null) - throw new ArgumentNullException(nameof(chartData)); - - if (chartData.Datasets is null) - throw new ArgumentNullException(nameof(chartData.Datasets)); - - if (chartDataset is null) - throw new ArgumentNullException(nameof(chartDataset)); - - if (chartDataset is DoughnutChartDataset doughnutChartDataset) - { - chartData.Datasets.Add(doughnutChartDataset); - await JSRuntime.InvokeVoidAsync($"{_jsObjectName}.addDataset", Id, doughnutChartDataset); - } - - return chartData; - } - - public override async Task InitializeAsync(ChartData chartData, IChartOptions chartOptions, string[]? plugins = null) - { - if (chartData is not null && chartData.Datasets is not null) - { - var datasets = chartData.Datasets.OfType(); - var data = new { chartData.Labels, Datasets = datasets }; - await JSRuntime.InvokeVoidAsync($"{_jsObjectName}.initialize", Id, GetChartType(), data, (DoughnutChartOptions)chartOptions, plugins); - } - } - - public override async Task UpdateAsync(ChartData chartData, IChartOptions chartOptions) - { - if (chartData is not null && chartData.Datasets is not null) - { - var datasets = chartData.Datasets.OfType(); - var data = new { chartData.Labels, Datasets = datasets }; - await JSRuntime.InvokeVoidAsync($"{_jsObjectName}.update", Id, GetChartType(), data, (DoughnutChartOptions)chartOptions); - } - } - - #endregion -} diff --git a/blazorbootstrap/Components/Charts/LineChart.razor b/blazorbootstrap/Components/Charts/LineChart.razor deleted file mode 100644 index da05c573a..000000000 --- a/blazorbootstrap/Components/Charts/LineChart.razor +++ /dev/null @@ -1,6 +0,0 @@ -@namespace BlazorBootstrap -@inherits BlazorBootstrapChart - -
    - -
    diff --git a/blazorbootstrap/Components/Charts/LineChart.razor.cs b/blazorbootstrap/Components/Charts/LineChart.razor.cs deleted file mode 100644 index 765fa000e..000000000 --- a/blazorbootstrap/Components/Charts/LineChart.razor.cs +++ /dev/null @@ -1,135 +0,0 @@ -namespace BlazorBootstrap; - -public partial class LineChart : BlazorBootstrapChart -{ - #region Constructors - - public LineChart() - { - chartType = ChartType.Line; - } - - #endregion - - #region Methods - - public override async Task AddDataAsync(ChartData chartData, string dataLabel, IChartDatasetData data) - { - if (chartData is null) - throw new ArgumentNullException(nameof(chartData)); - - if (chartData.Datasets is null) - throw new ArgumentNullException(nameof(chartData.Datasets)); - - if (data is null) - throw new ArgumentNullException(nameof(data)); - - foreach (var dataset in chartData.Datasets) - if (dataset is LineChartDataset lineChartDataset && lineChartDataset.Label == dataLabel) - if (data is LineChartDatasetData lineChartDatasetData) - lineChartDataset.Data?.Add(lineChartDatasetData.Data as double?); - - await JSRuntime.InvokeVoidAsync("window.blazorChart.line.addDatasetData", Id, dataLabel, data); - - return chartData; - } - - public override async Task AddDataAsync(ChartData chartData, string dataLabel, IReadOnlyCollection data) - { - if (chartData is null) - throw new ArgumentNullException(nameof(chartData)); - - if (chartData.Datasets is null) - throw new ArgumentException("chartData.Datasets must not be null", nameof(chartData)); - - if (chartData.Labels is null) - throw new ArgumentException("chartData.Labels must not be null", nameof(chartData)); - - if (dataLabel is null) - throw new ArgumentNullException(nameof(dataLabel)); - - if (string.IsNullOrWhiteSpace(dataLabel)) - throw new Exception($"{nameof(dataLabel)} cannot be empty."); - - if (data is null) - throw new ArgumentNullException(nameof(data)); - - if (!data.Any()) - throw new ArgumentException($"{nameof(data)} cannot be empty.", nameof(data)); - - if (chartData.Datasets.Count != data.Count) - throw new InvalidDataException("The chart dataset count and the new data points count do not match."); - - if (chartData.Labels.Contains(dataLabel)) - throw new Exception($"{dataLabel} already exists."); - - chartData.Labels.Add(dataLabel); - - foreach (var dataset in chartData.Datasets) - if (dataset is LineChartDataset lineChartDataset) - { - var chartDatasetData = data.FirstOrDefault(x => x is LineChartDatasetData lineChartDatasetData && lineChartDatasetData.DatasetLabel == lineChartDataset.Label); - - if (chartDatasetData is LineChartDatasetData lineChartDatasetData) - lineChartDataset.Data?.Add(lineChartDatasetData.Data as double?); - } - - await JSRuntime.InvokeVoidAsync("window.blazorChart.line.addDatasetsData", Id, dataLabel, data?.Select(x => (LineChartDatasetData)x)); - - return chartData; - } - - public override async Task AddDatasetAsync(ChartData chartData, IChartDataset chartDataset, IChartOptions chartOptions) - { - if (chartData is null) - throw new ArgumentNullException(nameof(chartData)); - - if (chartData.Datasets is null) - throw new ArgumentException("chartData.Datasets must not be null", nameof(chartData)); - - if (chartDataset is null) - throw new ArgumentNullException(nameof(chartDataset)); - - if (chartDataset is LineChartDataset) - { - chartData.Datasets.Add(chartDataset); - await JSRuntime.InvokeVoidAsync("window.blazorChart.line.addDataset", Id, (LineChartDataset)chartDataset); - } - - return chartData; - } - - public override async Task InitializeAsync(ChartData chartData, IChartOptions chartOptions, string[]? plugins = null) - { - if (chartData is null) - throw new ArgumentNullException(nameof(chartData)); - - if (chartData.Datasets is null) - throw new ArgumentException("chartData.Datasets must not be null", nameof(chartData)); - - if (chartOptions is null) - throw new ArgumentNullException(nameof(chartOptions)); - - var datasets = chartData.Datasets.OfType(); - var data = new { chartData.Labels, Datasets = datasets }; - await JSRuntime.InvokeVoidAsync("window.blazorChart.line.initialize", Id, GetChartType(), data, (LineChartOptions)chartOptions, plugins); - } - - public override async Task UpdateAsync(ChartData chartData, IChartOptions chartOptions) - { - if (chartData is null) - throw new ArgumentNullException(nameof(chartData)); - - if (chartData.Datasets is null) - throw new ArgumentException("chartData.Datasets must not be null", nameof(chartData)); - - if (chartOptions is null) - throw new ArgumentNullException(nameof(chartOptions)); - - var datasets = chartData.Datasets.OfType(); - var data = new { chartData.Labels, Datasets = datasets }; - await JSRuntime.InvokeVoidAsync("window.blazorChart.line.update", Id, GetChartType(), data, (LineChartOptions)chartOptions); - } - - #endregion -} diff --git a/blazorbootstrap/Components/Charts/PieChart.razor b/blazorbootstrap/Components/Charts/PieChart.razor deleted file mode 100644 index da05c573a..000000000 --- a/blazorbootstrap/Components/Charts/PieChart.razor +++ /dev/null @@ -1,6 +0,0 @@ -@namespace BlazorBootstrap -@inherits BlazorBootstrapChart - -
    - -
    diff --git a/blazorbootstrap/Components/Charts/PieChart.razor.cs b/blazorbootstrap/Components/Charts/PieChart.razor.cs deleted file mode 100644 index 86a4eeb5e..000000000 --- a/blazorbootstrap/Components/Charts/PieChart.razor.cs +++ /dev/null @@ -1,135 +0,0 @@ -namespace BlazorBootstrap; - -public partial class PieChart : BlazorBootstrapChart -{ - #region Fields and Constants - - private const string _jsObjectName = "window.blazorChart.pie"; - - #endregion - - #region Constructors - - public PieChart() - { - chartType = ChartType.Pie; - } - - #endregion - - #region Methods - - public override async Task AddDataAsync(ChartData chartData, string dataLabel, IChartDatasetData data) - { - if (chartData is null) - throw new ArgumentNullException(nameof(chartData)); - - if (chartData.Datasets is null) - throw new ArgumentNullException(nameof(chartData.Datasets)); - - if (data is null) - throw new ArgumentNullException(nameof(data)); - - foreach (var dataset in chartData.Datasets) - if (dataset is PieChartDataset pieChartDataset && pieChartDataset.Label == dataLabel) - if (data is PieChartDatasetData pieChartDatasetData) - { - pieChartDataset.Data?.Add(pieChartDatasetData.Data as double?); - pieChartDataset.BackgroundColor?.Add(pieChartDatasetData.BackgroundColor!); - } - - await JSRuntime.InvokeVoidAsync($"{_jsObjectName}.addDatasetData", Id, dataLabel, data); - - return chartData; - } - - public override async Task AddDataAsync(ChartData chartData, string dataLabel, IReadOnlyCollection data) - { - if (chartData is null) - throw new ArgumentNullException(nameof(chartData)); - - if (chartData.Datasets is null) - throw new ArgumentNullException(nameof(chartData.Datasets)); - - if (chartData.Labels is null) - throw new ArgumentNullException(nameof(chartData.Labels)); - - if (dataLabel is null) - throw new ArgumentNullException(nameof(dataLabel)); - - if (string.IsNullOrWhiteSpace(dataLabel)) - throw new Exception($"{nameof(dataLabel)} cannot be empty."); - - if (data is null) - throw new ArgumentNullException(nameof(data)); - - if (!data.Any()) - throw new Exception($"{nameof(data)} cannot be empty."); - - if (chartData.Datasets.Count != data.Count) - throw new InvalidDataException("The chart dataset count and the new data points count do not match."); - - if (chartData.Labels.Contains(dataLabel)) - throw new Exception($"{dataLabel} already exists."); - - chartData.Labels.Add(dataLabel); - - foreach (var dataset in chartData.Datasets) - if (dataset is PieChartDataset pieChartDataset) - { - var chartDatasetData = data.FirstOrDefault(x => x is PieChartDatasetData pieChartDatasetData && pieChartDatasetData.DatasetLabel == pieChartDataset.Label); - - if (chartDatasetData is PieChartDatasetData pieChartDatasetData) - { - pieChartDataset.Data?.Add(pieChartDatasetData.Data as double?); - pieChartDataset.BackgroundColor?.Add(pieChartDatasetData.BackgroundColor!); - } - } - - await JSRuntime.InvokeVoidAsync($"{_jsObjectName}.addDatasetsData", Id, dataLabel, data?.Select(x => (PieChartDatasetData)x)); - - return chartData; - } - - public override async Task AddDatasetAsync(ChartData chartData, IChartDataset chartDataset, IChartOptions chartOptions) - { - if (chartData is null) - throw new ArgumentNullException(nameof(chartData)); - - if (chartData.Datasets is null) - throw new ArgumentNullException(nameof(chartData.Datasets)); - - if (chartDataset is null) - throw new ArgumentNullException(nameof(chartDataset)); - - if (chartDataset is PieChartDataset pieChartDataset) - { - chartData.Datasets.Add(pieChartDataset); - await JSRuntime.InvokeVoidAsync($"{_jsObjectName}.addDataset", Id, pieChartDataset); - } - - return chartData; - } - - public override async Task InitializeAsync(ChartData chartData, IChartOptions chartOptions, string[]? plugins = null) - { - if (chartData is not null && chartData.Datasets is not null) - { - var datasets = chartData.Datasets.OfType(); - var data = new { chartData.Labels, Datasets = datasets }; - await JSRuntime.InvokeVoidAsync($"{_jsObjectName}.initialize", Id, GetChartType(), data, (PieChartOptions)chartOptions, plugins); - } - } - - public override async Task UpdateAsync(ChartData chartData, IChartOptions chartOptions) - { - if (chartData is not null && chartData.Datasets is not null) - { - var datasets = chartData.Datasets.OfType(); - var data = new { chartData.Labels, Datasets = datasets }; - await JSRuntime.InvokeVoidAsync($"{_jsObjectName}.update", Id, GetChartType(), data, (PieChartOptions)chartOptions); - } - } - - #endregion -} diff --git a/blazorbootstrap/Components/Charts/PolarAreaChart.razor b/blazorbootstrap/Components/Charts/PolarAreaChart.razor deleted file mode 100644 index a24e57c6f..000000000 --- a/blazorbootstrap/Components/Charts/PolarAreaChart.razor +++ /dev/null @@ -1,6 +0,0 @@ -@namespace BlazorBootstrap -@inherits BlazorBootstrapChart - -
    - -
    diff --git a/blazorbootstrap/Components/Charts/PolarAreaChart.razor.cs b/blazorbootstrap/Components/Charts/PolarAreaChart.razor.cs deleted file mode 100644 index 615c9b624..000000000 --- a/blazorbootstrap/Components/Charts/PolarAreaChart.razor.cs +++ /dev/null @@ -1,130 +0,0 @@ -namespace BlazorBootstrap; - -public partial class PolarAreaChart : BlazorBootstrapChart -{ - #region Fields and Constants - - private const string _jsObjectName = "window.blazorChart.polarArea"; - - #endregion - - #region Constructors - - public PolarAreaChart() - { - chartType = ChartType.PolarArea; - } - - #endregion - - #region Methods - - // TODO: May be this method is not required - public override async Task AddDataAsync(ChartData chartData, string dataLabel, IChartDatasetData data) - { - if (chartData is null) - throw new ArgumentNullException(nameof(chartData)); - - if (chartData.Datasets is null) - throw new ArgumentException("chartData.Datasets must not be null", nameof(chartData)); - - if (data is null) - throw new ArgumentNullException(nameof(data)); - - foreach (var dataset in chartData.Datasets) - if (dataset is PolarAreaChartDataset barChartDataset && barChartDataset.Label == dataLabel) - if (data is PolarAreaChartDatasetData barChartDatasetData) - barChartDataset.Data?.Add(barChartDatasetData.Data as double?); - - await JSRuntime.InvokeVoidAsync($"{_jsObjectName}.addDatasetData", Id, dataLabel, data); - - return chartData; - } - - public override async Task AddDataAsync(ChartData chartData, string dataLabel, IReadOnlyCollection data) - { - if (chartData is null) - throw new ArgumentNullException(nameof(chartData)); - - if (chartData.Datasets is null) - throw new ArgumentException("chartData.Datasets must not be null", nameof(chartData)); - - if (chartData.Labels is null) - throw new ArgumentException("chartData.Labels must not be null", nameof(chartData)); - - if (dataLabel is null) - throw new ArgumentNullException(nameof(dataLabel)); - - if (string.IsNullOrWhiteSpace(dataLabel)) - throw new Exception($"{nameof(dataLabel)} cannot be empty."); - - if (data is null) - throw new ArgumentNullException(nameof(data)); - - if (!data.Any()) - throw new Exception($"{nameof(data)} cannot be empty."); - - if (chartData.Datasets.Count != data.Count) - throw new InvalidDataException("The chart dataset count and the new data points count do not match."); - - if (chartData.Labels.Contains(dataLabel)) - throw new Exception($"{dataLabel} already exists."); - - chartData.Labels.Add(dataLabel); - - foreach (var dataset in chartData.Datasets) - if (dataset is PolarAreaChartDataset barChartDataset) - { - var chartDatasetData = data.FirstOrDefault(x => x is PolarAreaChartDatasetData barChartDatasetData && barChartDatasetData.DatasetLabel == barChartDataset.Label); - - if (chartDatasetData is PolarAreaChartDatasetData barChartDatasetData) - barChartDataset.Data?.Add(barChartDatasetData.Data as double?); - } - - await JSRuntime.InvokeVoidAsync($"{_jsObjectName}.addDatasetsData", Id, dataLabel, data?.Select(x => (PolarAreaChartDatasetData)x)); - - return chartData; - } - - public override async Task AddDatasetAsync(ChartData chartData, IChartDataset chartDataset, IChartOptions chartOptions) - { - if (chartData is null) - throw new ArgumentNullException(nameof(chartData)); - - if (chartData.Datasets is null) - throw new ArgumentException("chartData.Datasets must not be null", nameof(chartData)); - - if (chartDataset is null) - throw new ArgumentNullException(nameof(chartDataset)); - - if (chartDataset is PolarAreaChartDataset) - { - chartData.Datasets.Add(chartDataset); - await JSRuntime.InvokeVoidAsync($"{_jsObjectName}.addDataset", Id, (PolarAreaChartDataset)chartDataset); - } - - return chartData; - } - - public override async Task InitializeAsync(ChartData chartData, IChartOptions chartOptions, string[]? plugins = null) - { - if (chartData is not null && chartData.Datasets is not null) - { - var datasets = chartData.Datasets.OfType(); - var data = new { chartData.Labels, Datasets = datasets }; - await JSRuntime.InvokeVoidAsync($"{_jsObjectName}.initialize", Id, GetChartType(), data, (PolarAreaChartOptions)chartOptions, plugins); - } - } - - public override async Task UpdateAsync(ChartData chartData, IChartOptions chartOptions) - { - if (chartData is not null && chartData.Datasets is not null) - { - var datasets = chartData.Datasets.OfType(); - var data = new { chartData.Labels, Datasets = datasets }; - await JSRuntime.InvokeVoidAsync($"{_jsObjectName}.update", Id, GetChartType(), data, (PolarAreaChartOptions)chartOptions); - } - } - - #endregion -} diff --git a/blazorbootstrap/Components/Charts/RadarChart.razor b/blazorbootstrap/Components/Charts/RadarChart.razor deleted file mode 100644 index a24e57c6f..000000000 --- a/blazorbootstrap/Components/Charts/RadarChart.razor +++ /dev/null @@ -1,6 +0,0 @@ -@namespace BlazorBootstrap -@inherits BlazorBootstrapChart - -
    - -
    diff --git a/blazorbootstrap/Components/Charts/RadarChart.razor.cs b/blazorbootstrap/Components/Charts/RadarChart.razor.cs deleted file mode 100644 index 360607416..000000000 --- a/blazorbootstrap/Components/Charts/RadarChart.razor.cs +++ /dev/null @@ -1,130 +0,0 @@ -namespace BlazorBootstrap; - -public partial class RadarChart : BlazorBootstrapChart -{ - #region Fields and Constants - - private const string _jsObjectName = "window.blazorChart.radar"; - - #endregion - - #region Constructors - - public RadarChart() - { - chartType = ChartType.Radar; - } - - #endregion - - #region Methods - - // TODO: May be this method is not required - public override async Task AddDataAsync(ChartData chartData, string dataLabel, IChartDatasetData data) - { - if (chartData is null) - throw new ArgumentNullException(nameof(chartData)); - - if (chartData.Datasets is null) - throw new ArgumentException("chartData.Datasets must not be null", nameof(chartData)); - - if (data is null) - throw new ArgumentNullException(nameof(data)); - - foreach (var dataset in chartData.Datasets) - if (dataset is RadarChartDataset radarChartDataset && radarChartDataset.Label == dataLabel) - if (data is RadarChartDatasetData radarChartDatasetData) - radarChartDataset.Data?.Add(radarChartDatasetData.Data as double?); - - await JSRuntime.InvokeVoidAsync($"{_jsObjectName}.addDatasetData", Id, dataLabel, data); - - return chartData; - } - - public override async Task AddDataAsync(ChartData chartData, string dataLabel, IReadOnlyCollection data) - { - if (chartData is null) - throw new ArgumentNullException(nameof(chartData)); - - if (chartData.Datasets is null) - throw new ArgumentException("chartData.Datasets must not be null", nameof(chartData)); - - if (chartData.Labels is null) - throw new ArgumentException("chartData.Labels must not be null", nameof(chartData)); - - if (dataLabel is null) - throw new ArgumentNullException(nameof(dataLabel)); - - if (string.IsNullOrWhiteSpace(dataLabel)) - throw new Exception($"{nameof(dataLabel)} cannot be empty."); - - if (data is null) - throw new ArgumentNullException(nameof(data)); - - if (!data.Any()) - throw new Exception($"{nameof(data)} cannot be empty."); - - if (chartData.Datasets.Count != data.Count) - throw new InvalidDataException("The chart dataset count and the new data points count do not match."); - - if (chartData.Labels.Contains(dataLabel)) - throw new Exception($"{dataLabel} already exists."); - - chartData.Labels.Add(dataLabel); - - foreach (var dataset in chartData.Datasets) - if (dataset is RadarChartDataset radarChartDataset) - { - var chartDatasetData = data.FirstOrDefault(x => x is RadarChartDatasetData radarChartDatasetData && radarChartDatasetData.DatasetLabel == radarChartDataset.Label); - - if (chartDatasetData is RadarChartDatasetData radarChartDatasetData) - radarChartDataset.Data?.Add(radarChartDatasetData.Data as double?); - } - - await JSRuntime.InvokeVoidAsync($"{_jsObjectName}.addDatasetsData", Id, dataLabel, data?.Select(x => (RadarChartDatasetData)x)); - - return chartData; - } - - public override async Task AddDatasetAsync(ChartData chartData, IChartDataset chartDataset, IChartOptions chartOptions) - { - if (chartData is null) - throw new ArgumentNullException(nameof(chartData)); - - if (chartData.Datasets is null) - throw new ArgumentException("chartData.Datasets must not be null", nameof(chartData)); - - if (chartDataset is null) - throw new ArgumentNullException(nameof(chartDataset)); - - if (chartDataset is RadarChartDataset) - { - chartData.Datasets.Add(chartDataset); - await JSRuntime.InvokeVoidAsync($"{_jsObjectName}.addDataset", Id, (RadarChartDataset)chartDataset); - } - - return chartData; - } - - public override async Task InitializeAsync(ChartData chartData, IChartOptions chartOptions, string[]? plugins = null) - { - if (chartData is not null && chartData.Datasets is not null) - { - var datasets = chartData.Datasets.OfType(); - var data = new { chartData.Labels, Datasets = datasets }; - await JSRuntime.InvokeVoidAsync($"{_jsObjectName}.initialize", Id, GetChartType(), data, (RadarChartOptions)chartOptions, plugins); - } - } - - public override async Task UpdateAsync(ChartData chartData, IChartOptions chartOptions) - { - if (chartData is not null && chartData.Datasets is not null) - { - var datasets = chartData.Datasets.OfType(); - var data = new { chartData.Labels, Datasets = datasets }; - await JSRuntime.InvokeVoidAsync($"{_jsObjectName}.update", Id, GetChartType(), data, (RadarChartOptions)chartOptions); - } - } - - #endregion -} diff --git a/blazorbootstrap/Components/Charts/ScatterChart.razor b/blazorbootstrap/Components/Charts/ScatterChart.razor deleted file mode 100644 index a24e57c6f..000000000 --- a/blazorbootstrap/Components/Charts/ScatterChart.razor +++ /dev/null @@ -1,6 +0,0 @@ -@namespace BlazorBootstrap -@inherits BlazorBootstrapChart - -
    - -
    diff --git a/blazorbootstrap/Components/Charts/ScatterChart.razor.cs b/blazorbootstrap/Components/Charts/ScatterChart.razor.cs deleted file mode 100644 index 02f22c924..000000000 --- a/blazorbootstrap/Components/Charts/ScatterChart.razor.cs +++ /dev/null @@ -1,142 +0,0 @@ -namespace BlazorBootstrap; - -public partial class ScatterChart : BlazorBootstrapChart -{ - #region Fields and Constants - - private const string _jsObjectName = "window.blazorChart.scatter"; - - #endregion - - #region Constructors - - public ScatterChart() - { - chartType = ChartType.Scatter; - } - - #endregion - - #region Methods - - // TODO: May be this method is not required - public override async Task AddDataAsync(ChartData chartData, string dataLabel, IChartDatasetData data) - { - if (chartData is null) - throw new ArgumentNullException(nameof(chartData)); - - if (chartData.Datasets is null) - throw new ArgumentNullException(nameof(chartData.Datasets)); - - if (data is null) - throw new ArgumentNullException(nameof(data)); - - foreach (var dataset in chartData.Datasets) - if (dataset is ScatterChartDataset scatterChartDataset && scatterChartDataset.Label == dataLabel) - if (data is ScatterChartDatasetData scatterChartDatasetData && scatterChartDatasetData.Data is ScatterChartDataPoint scatterChartDataPoint) - scatterChartDataset.Data?.Add(scatterChartDataPoint); - - await JSRuntime.InvokeVoidAsync($"{_jsObjectName}.addDatasetData", Id, dataLabel, data); - - return chartData; - } - - public override async Task AddDataAsync(ChartData chartData, string dataLabel, IReadOnlyCollection data) - { - if (chartData is null) - throw new ArgumentNullException(nameof(chartData)); - - if (chartData.Datasets is null) - throw new ArgumentException("chartData.Datasets must not be null", nameof(chartData)); - - if (chartData.Labels is null) - throw new ArgumentException("chartData.Labels must not be null", nameof(chartData)); - - if (dataLabel is null) - throw new ArgumentNullException(nameof(dataLabel)); - - if (string.IsNullOrWhiteSpace(dataLabel)) - throw new Exception($"{nameof(dataLabel)} cannot be empty."); - - if (data is null) - throw new ArgumentNullException(nameof(data)); - - if (!data.Any()) - throw new ArgumentException($"{nameof(data)} cannot be empty.", nameof(data)); - - if (chartData.Datasets.Count != data.Count) - throw new InvalidDataException("The chart dataset count and the new data points count do not match."); - - if (chartData.Labels.Contains(dataLabel)) - throw new Exception($"{dataLabel} already exists."); - - chartData.Labels.Add(dataLabel); - - foreach (var dataset in chartData.Datasets) - if (dataset is ScatterChartDataset scatterChartDataset) - { - var chartDatasetData = data.FirstOrDefault(x => x is ScatterChartDatasetData scatterChartDatasetData && scatterChartDatasetData.DatasetLabel == scatterChartDataset.Label); - - if (chartDatasetData is ScatterChartDatasetData scatterChartDatasetData && scatterChartDatasetData.Data is ScatterChartDataPoint scatterChartDataPoint) - scatterChartDataset.Data?.Add(scatterChartDataPoint); - } - - await JSRuntime.InvokeVoidAsync($"{_jsObjectName}.addDatasetsData", Id, dataLabel, data?.Select(x => (ScatterChartDatasetData)x)); - - return chartData; - } - - public override async Task AddDatasetAsync(ChartData chartData, IChartDataset chartDataset, IChartOptions chartOptions) - { - if (chartData is null) - throw new ArgumentNullException(nameof(chartData)); - - if (chartData.Datasets is null) - throw new ArgumentException("chartData.Datasets must not be null", nameof(chartData)); - - if (chartDataset is null) - throw new ArgumentNullException(nameof(chartDataset)); - - if (chartDataset is ScatterChartDataset) - { - chartData.Datasets.Add(chartDataset); - await JSRuntime.InvokeVoidAsync($"{_jsObjectName}.addDataset", Id, (ScatterChartDataset)chartDataset); - } - - return chartData; - } - - public override async Task InitializeAsync(ChartData chartData, IChartOptions chartOptions, string[]? plugins = null) - { - if (chartData is null) - throw new ArgumentNullException(nameof(chartData)); - - if (chartData.Datasets is null) - throw new ArgumentException("chartData.Datasets must not be null", nameof(chartData)); - - if (chartOptions is null) - throw new ArgumentNullException(nameof(chartOptions)); - - var datasets = chartData.Datasets.OfType(); - var data = new { chartData.Labels, Datasets = datasets }; - await JSRuntime.InvokeVoidAsync($"{_jsObjectName}.initialize", Id, GetChartType(), data, (ScatterChartOptions)chartOptions, plugins); - } - - public override async Task UpdateAsync(ChartData chartData, IChartOptions chartOptions) - { - if (chartData is null) - throw new ArgumentNullException(nameof(chartData)); - - if (chartData.Datasets is null) - throw new ArgumentException("chartData.Datasets must not be null", nameof(chartData)); - - if (chartOptions is null) - throw new ArgumentNullException(nameof(chartOptions)); - - var datasets = chartData.Datasets.OfType(); - var data = new { chartData.Labels, Datasets = datasets }; - await JSRuntime.InvokeVoidAsync($"{_jsObjectName}.update", Id, GetChartType(), data, (ScatterChartOptions)chartOptions); - } - - #endregion -} diff --git a/blazorbootstrap/Components/Collapse/Collapse.razor.cs b/blazorbootstrap/Components/Collapse/Collapse.razor.cs index 68ee3e78f..351785540 100644 --- a/blazorbootstrap/Components/Collapse/Collapse.razor.cs +++ b/blazorbootstrap/Components/Collapse/Collapse.razor.cs @@ -18,7 +18,7 @@ protected override async ValueTask DisposeAsyncCore(bool disposing) try { if (IsRenderComplete) - await JSRuntime.InvokeVoidAsync("window.blazorBootstrap.collapse.dispose", Id); + await SafeInvokeVoidAsync("window.blazorBootstrap.collapse.dispose", Id); } catch (JSDisconnectedException) { @@ -34,7 +34,7 @@ protected override async ValueTask DisposeAsyncCore(bool disposing) protected override async Task OnAfterRenderAsync(bool firstRender) { if (firstRender) - await JSRuntime.InvokeVoidAsync("window.blazorBootstrap.collapse.initialize", Id, Parent, Toggle, objRef); + await SafeInvokeVoidAsync("window.blazorBootstrap.collapse.initialize", Id, Parent, Toggle, objRef); await base.OnAfterRenderAsync(firstRender); } @@ -61,17 +61,23 @@ protected override async Task OnInitializedAsync() /// /// Hides a collapsible element. /// - public async Task HideAsync() => await JSRuntime.InvokeVoidAsync("window.blazorBootstrap.collapse.hide", Id); + [AddedVersion("1.7.0")] + [Description("Hides a collapsible element.")] + public async Task HideAsync() => await SafeInvokeVoidAsync("window.blazorBootstrap.collapse.hide", Id); /// /// Shows a collapsible element. /// - public async Task ShowAsync() => await JSRuntime.InvokeVoidAsync("window.blazorBootstrap.collapse.show", Id); + [AddedVersion("1.7.0")] + [Description("Shows a collapsible element.")] + public async Task ShowAsync() => await SafeInvokeVoidAsync("window.blazorBootstrap.collapse.show", Id); /// /// Toggles a collapsible element to shown or hidden. /// - public async Task ToggleAsync() => await JSRuntime.InvokeVoidAsync("window.blazorBootstrap.collapse.toggle", Id); + [AddedVersion("1.7.0")] + [Description("Toggles a collapsible element to shown or hidden.")] + public async Task ToggleAsync() => await SafeInvokeVoidAsync("window.blazorBootstrap.collapse.toggle", Id); #endregion @@ -84,45 +90,58 @@ protected override async Task OnInitializedAsync() /// /// Gets or sets the content to be rendered within the component. + /// + /// Default value is . + /// /// - /// - /// Default value is null. - /// - [Parameter] + [AddedVersion("1.7.0")] + [DefaultValue(null)] + [Description("Gets or sets the content to be rendered within the component.")] [EditorRequired] - public RenderFragment ChildContent { get; set; } = default!; + [Parameter] + public RenderFragment? ChildContent { get; set; } /// /// Gets or sets the horizontal collapsing. + /// + /// Default value is . + /// /// - /// - /// Default value is false. - /// + [AddedVersion("1.7.0")] + [DefaultValue(false)] + [Description("Gets or sets the horizontal collapsing.")] [Parameter] public bool Horizontal { get; set; } /// /// This event is fired when a collapse element has been hidden from the user (will wait for CSS transitions to complete). /// + [AddedVersion("1.7.0")] + [Description("This event is fired when a collapse element has been hidden from the user (will wait for CSS transitions to complete).")] [Parameter] public EventCallback OnHidden { get; set; } /// /// This event is fired immediately when the hide method has been called. /// + [AddedVersion("1.7.0")] + [Description("This event is fired immediately when the hide method has been called.")] [Parameter] public EventCallback OnHiding { get; set; } /// /// This event fires immediately when the show instance method is called. /// + [AddedVersion("1.7.0")] + [Description("This event fires immediately when the show instance method is called.")] [Parameter] public EventCallback OnShowing { get; set; } /// - /// This event is fired when a collapse element has been made visible to the user (will wait for CSS transitions to - /// complete). + /// This event is fired when a collapse element has been made visible to the user (will wait for CSS transitions to complete). /// + [AddedVersion("1.7.0")] + [Description("This event is fired when a collapse element has been made visible to the user (will wait for CSS transitions to complete).")] [Parameter] public EventCallback OnShown { get; set; } @@ -131,18 +150,27 @@ protected override async Task OnInitializedAsync() /// If parent is provided, then all collapsible elements under the specified parent will be closed when this collapsible /// item is shown. (similar to traditional accordion behavior - this is dependent on the card class). /// The attribute has to be set on the target collapsible area. + /// + /// Default value is . + /// /// + [AddedVersion("1.7.0")] + [DefaultValue(null)] + [Description("Gets or sets the parent selector, DOM element. If parent is provided, then all collapsible elements under the specified parent will be closed when this collapsible item is shown. (similar to traditional accordion behavior - this is dependent on the card class). The attribute has to be set on the target collapsible area.")] [Parameter] - public object Parent { get; set; } = default!; + public object? Parent { get; set; } /// /// Toggles the collapsible element on invocation. + /// + /// Default value is . + /// /// - /// - /// Default value is false. - /// + [AddedVersion("1.7.0")] + [DefaultValue(false)] + [Description("Toggles the collapsible element on invocation.")] [Parameter] - public bool Toggle { get; set; } = false; + public bool Toggle { get; set; } #endregion } diff --git a/blazorbootstrap/Components/ConfirmDialog/ConfirmDialog.razor b/blazorbootstrap/Components/ConfirmDialog/ConfirmDialog.razor index 9979dd35f..5c9c3aceb 100644 --- a/blazorbootstrap/Components/ConfirmDialog/ConfirmDialog.razor +++ b/blazorbootstrap/Components/ConfirmDialog/ConfirmDialog.razor @@ -41,7 +41,7 @@ } @if (!string.IsNullOrWhiteSpace(yesButtonText)) { - + } diff --git a/blazorbootstrap/Components/ConfirmDialog/ConfirmDialog.razor.cs b/blazorbootstrap/Components/ConfirmDialog/ConfirmDialog.razor.cs index 163ff00cb..d488ac7d1 100644 --- a/blazorbootstrap/Components/ConfirmDialog/ConfirmDialog.razor.cs +++ b/blazorbootstrap/Components/ConfirmDialog/ConfirmDialog.razor.cs @@ -5,11 +5,9 @@ public partial class ConfirmDialog : BlazorBootstrapComponentBase #region Fields and Constants private Type? childComponent; - private string? dialogCssClass; private bool dismissable; private string? headerCssClass; - private bool isVisible; private string? message1; private string? message2; @@ -18,13 +16,12 @@ public partial class ConfirmDialog : BlazorBootstrapComponentBase private string? noButtonText; private Dictionary? parameters; private string? scrollable; - + private bool shouldAutoFocusYesButton; private bool showBackdrop; - private TaskCompletionSource? taskCompletionSource; - private string? title; private string? verticallyCentered; + private ElementReference yesButtonElement; private string? yesButtonColor; private string? yesButtonText; @@ -32,6 +29,14 @@ public partial class ConfirmDialog : BlazorBootstrapComponentBase #region Methods + protected override async Task OnAfterRenderAsync(bool firstRender) + { + if(isVisible && shouldAutoFocusYesButton) + await yesButtonElement.FocusAsync(); + + await base.OnAfterRenderAsync(firstRender); + } + /// /// Shows confirm dialog. /// @@ -39,6 +44,8 @@ public partial class ConfirmDialog : BlazorBootstrapComponentBase /// message1 for the confirmation dialog. /// options for the confirmation dialog. /// bool + [AddedVersion("1.1.0")] + [Description("Shows confirm dialog.")] public Task ShowAsync(string title, string message1, ConfirmDialogOptions? confirmDialogOptions = null) => Show(title, message1, null, null, null, confirmDialogOptions!); /// @@ -49,6 +56,8 @@ public partial class ConfirmDialog : BlazorBootstrapComponentBase /// message2 for the confirmation dialog. This is optional. /// options for the confirmation dialog. /// bool + [AddedVersion("1.1.0")] + [Description("Shows confirm dialog.")] public Task ShowAsync(string title, string message1, string message2, ConfirmDialogOptions? confirmDialogOptions = null) => Show(title, message1, message2, null, null, confirmDialogOptions!); /// @@ -59,6 +68,8 @@ public partial class ConfirmDialog : BlazorBootstrapComponentBase /// /// /// bool + [AddedVersion("1.1.0")] + [Description("Shows confirm dialog.")] public Task ShowAsync(string title, Dictionary? parameters = null, ConfirmDialogOptions? confirmDialogOptions = null) where T : ComponentBase => Show(title, null, null, typeof(T), parameters, confirmDialogOptions!); /// @@ -71,7 +82,7 @@ private void Hide() StateHasChanged(); - Task.Run(() => JSRuntime.InvokeVoidAsync("window.blazorBootstrap.confirmDialog.hide", Id)); + Task.Run(async () => await SafeInvokeVoidAsync("window.blazorBootstrap.confirmDialog.hide", Id)); } private void OnNoClick() @@ -110,13 +121,13 @@ private Task Show(string title, string? message1, string? message2, Type? modalSize = confirmDialogOptions.Size.ToDialogSizeClass(); yesButtonColor = $"{BootstrapClass.Button} {confirmDialogOptions.YesButtonColor.ToButtonColorClass()}"; yesButtonText = confirmDialogOptions.YesButtonText; - + shouldAutoFocusYesButton = confirmDialogOptions.AutoFocusYesButton; isVisible = true; showBackdrop = true; StateHasChanged(); - Task.Run(() => JSRuntime.InvokeVoidAsync("window.blazorBootstrap.confirmDialog.show", Id)); + Task.Run(async () => await SafeInvokeVoidAsync("window.blazorBootstrap.confirmDialog.show", Id)); return task; } diff --git a/blazorbootstrap/Components/Core/BlazorBootstrapComponentBase.cs b/blazorbootstrap/Components/Core/BlazorBootstrapComponentBase.cs index a8bfe8dfa..d64b40d7b 100644 --- a/blazorbootstrap/Components/Core/BlazorBootstrapComponentBase.cs +++ b/blazorbootstrap/Components/Core/BlazorBootstrapComponentBase.cs @@ -1,6 +1,4 @@ -using Microsoft.Extensions.Configuration; - -namespace BlazorBootstrap; +namespace BlazorBootstrap; public abstract class BlazorBootstrapComponentBase : ComponentBase, IDisposable, IAsyncDisposable { @@ -10,6 +8,10 @@ public abstract class BlazorBootstrapComponentBase : ComponentBase, IDisposable, private bool isDisposed; + private bool isJsRuntimeAvailable = true; + + internal Queue> queuedTasks = new(); + #endregion #region Methods @@ -17,17 +19,38 @@ public abstract class BlazorBootstrapComponentBase : ComponentBase, IDisposable, /// protected override async Task OnAfterRenderAsync(bool firstRender) { - IsRenderComplete = true; + // process queued tasks + while (queuedTasks.TryDequeue(out var taskToExecute)) + await taskToExecute.Invoke(); - await base.OnAfterRenderAsync(firstRender); + IsRenderComplete = true; } /// protected override void OnInitialized() { Id ??= IdUtility.GetNextId(); + } + + protected async Task SafeInvokeVoidAsync(string identifier, params object?[] args) + { + if (!isJsRuntimeAvailable) + return; - base.OnInitialized(); + try + { + await JSRuntime.InvokeVoidAsync(identifier, args); + } + catch (TaskCanceledException) + { + // Component/DOM likely got removed (navigation, conditional render, etc.) + // Treat as benign for focus/value updates; do not mark JS runtime as unavailable. + } + catch (JSDisconnectedException) + { + // JS runtime no longer available (more common on Server, but safe here too). + isJsRuntimeAvailable = false; + } } public static string BuildClassNames(params (string? cssClass, bool when)[] cssClassList) @@ -88,7 +111,7 @@ public static string BuildStyleNames(string? userDefinedCssStyle, params (string } /// - /// + /// public void Dispose() { Dispose(true); @@ -137,23 +160,74 @@ protected virtual ValueTask DisposeAsyncCore(bool disposing) #region Properties, Indexers - [Parameter(CaptureUnmatchedValues = true)] public Dictionary AdditionalAttributes { get; set; } = default!; - - [Parameter] public string? Class { get; set; } + /// + /// Gets or sets additional attributes that will be applied to the component. + /// + /// Default value is . + /// + /// + [AddedVersion("1.0.0")] + [DefaultValue(null)] + [Description("Gets or sets additional attributes that will be applied to the component.")] + [ParameterTypeName("Dictionary")] + [Parameter(CaptureUnmatchedValues = true)] + public Dictionary? AdditionalAttributes { get; set; } + + /// + /// Gets or sets the CSS class name(s) to apply to the component. + /// + /// Default value is . + /// + /// + [AddedVersion("1.0.0")] + [DefaultValue(null)] + [Description("Gets or sets the CSS class name(s) to apply to the component.")] + [ParameterTypeName("string?")] + [Parameter] + public string? Class { get; set; } protected virtual string? ClassNames => Class; - [Inject] protected IConfiguration Configuration { get; set; } = default!; - + /// + /// Gets or sets the associated . + /// + /// May be , if accessed before the component is rendered. + /// + /// + [DisallowNull] public ElementReference Element { get; set; } - [Parameter] public string? Id { get; set; } + /// + /// Gets or sets the ID. If not set, a unique ID will be generated. + /// + /// Default value is . + /// + /// + [AddedVersion("1.0.0")] + [DefaultValue(null)] + [Description("Gets or sets the ID. If not set, a unique ID will be generated.")] + [ParameterTypeName("string?")] + [Parameter] + public string? Id { get; set; } protected bool IsRenderComplete { get; private set; } + protected bool IsJsRuntimeAvailable => isJsRuntimeAvailable; + [Inject] protected IJSRuntime JSRuntime { get; set; } = default!; - [Parameter] public string? Style { get; set; } + /// + /// Gets or sets the CSS style string that defines the inline styles for the component. + /// + /// Default value is . + /// + /// + [AddedVersion("1.0.0")] + [DefaultValue(null)] + [Description("Gets or sets the CSS style string that defines the inline styles for the component.")] + [ParameterTypeName("string?")] + [Parameter] + public string? Style { get; set; } protected virtual string? StyleNames => Style; diff --git a/blazorbootstrap/Components/Core/BlazorBootstrapLayoutComponentBase.cs b/blazorbootstrap/Components/Core/BlazorBootstrapLayoutComponentBase.cs index d4fd797d5..00336fec2 100644 --- a/blazorbootstrap/Components/Core/BlazorBootstrapLayoutComponentBase.cs +++ b/blazorbootstrap/Components/Core/BlazorBootstrapLayoutComponentBase.cs @@ -1,6 +1,4 @@ -using Microsoft.Extensions.Configuration; - -namespace BlazorBootstrap; +namespace BlazorBootstrap; public abstract class BlazorBootstrapLayoutComponentBase : LayoutComponentBase, IDisposable, IAsyncDisposable { @@ -82,7 +80,7 @@ public static string BuildStyleNames(string? userDefinedCssStyle, params (string } /// - /// + /// public void Dispose() { Dispose(true); @@ -132,23 +130,72 @@ protected virtual ValueTask DisposeAsyncCore(bool disposing) #region Properties, Indexers - [Parameter(CaptureUnmatchedValues = true)] public Dictionary AdditionalAttributes { get; set; } = default!; - - [Parameter] public string? Class { get; set; } + /// + /// Gets or sets additional attributes that will be applied to the component. + /// + /// Default value is . + /// + /// + [AddedVersion("1.0.0")] + [DefaultValue(null)] + [Description("Gets or sets additional attributes that will be applied to the component.")] + [Parameter(CaptureUnmatchedValues = true)] + [ParameterTypeName("Dictionary")] + public Dictionary? AdditionalAttributes { get; set; } + + /// + /// Gets or sets the CSS class name(s) to apply to the component. + /// + /// Default value is . + /// + /// + [AddedVersion("1.0.0")] + [DefaultValue(null)] + [Description("Gets or sets the CSS class name(s) to apply to the component.")] + [Parameter] + [ParameterTypeName("string?")] + public string? Class { get; set; } protected virtual string? ClassNames => Class; - [Inject] protected IConfiguration Configuration { get; set; } = default!; - - public ElementReference Element { get; set; } - - [Parameter] public string? Id { get; set; } + /// + /// Gets or sets the associated . + /// + /// May be , if accessed before the component is rendered. + /// + /// + [DisallowNull] + public ElementReference? Element { get; set; } + + /// + /// Gets or sets the ID. If not set, a unique ID will be generated. + /// + /// Default value is . + /// + /// + [AddedVersion("1.0.0")] + [DefaultValue(null)] + [Description("Gets or sets the ID. If not set, a unique ID will be generated.")] + [Parameter] + [ParameterTypeName("string?")] + public string? Id { get; set; } protected bool IsRenderComplete { get; private set; } [Inject] protected IJSRuntime JSRuntime { get; set; } = default!; - [Parameter] public string? Style { get; set; } + /// + /// Gets or sets the CSS style string that defines the inline styles for the component. + /// + /// Default value is . + /// + /// + [AddedVersion("1.0.0")] + [DefaultValue(null)] + [Description("Gets or sets the CSS style string that defines the inline styles for the component.")] + [Parameter] + [ParameterTypeName("string?")] + public string? Style { get; set; } protected virtual string? StyleNames => Style; diff --git a/blazorbootstrap/Components/Core/JsInteropBase.cs b/blazorbootstrap/Components/Core/JsInteropBase.cs new file mode 100644 index 000000000..b172dbcfc --- /dev/null +++ b/blazorbootstrap/Components/Core/JsInteropBase.cs @@ -0,0 +1,85 @@ +namespace BlazorBootstrap; + +public abstract class JsInteropBase : IAsyncDisposable +{ + #region Fields and Constants + + private readonly Lazy> moduleTask; + private bool isJsRuntimeAvailable = true; + + #endregion + + #region Constructors + + protected JsInteropBase(IJSRuntime jsRuntime, string modulePath) + { + moduleTask = new Lazy>(() => + jsRuntime.InvokeAsync("import", modulePath).AsTask()); + } + + #endregion + + #region Methods + + public async ValueTask DisposeAsync() + { + if (!moduleTask.IsValueCreated) + return; + + try + { + var module = await moduleTask.Value; + await module.DisposeAsync(); + } + catch (JSDisconnectedException) + { + // Circuit is gone; ignore cleanup. + } + catch (TaskCanceledException) + { + // Circuit is shutting down; ignore cleanup. + } + } + + protected async Task SafeInvokeAsync(string identifier, params object?[] args) + { + if (!isJsRuntimeAvailable) + return default!; + + try + { + var module = await moduleTask.Value; + return await module.InvokeAsync(identifier, args); + } + catch (JSDisconnectedException) + { + isJsRuntimeAvailable = false; + return default!; + } + catch (TaskCanceledException) + { + return default!; + } + } + protected async Task SafeInvokeVoidAsync(string identifier, params object?[] args) + { + if (!isJsRuntimeAvailable) + return; + + try + { + var module = await moduleTask.Value; + await module.InvokeVoidAsync(identifier, args); + } + catch (JSDisconnectedException) + { + isJsRuntimeAvailable = false; + } + catch (TaskCanceledException) + { + // do nothing + } + } + + #endregion +} diff --git a/blazorbootstrap/Components/Dropdown/Dropdown.razor.cs b/blazorbootstrap/Components/Dropdown/Dropdown.razor.cs index 054956aea..e86fdcf67 100644 --- a/blazorbootstrap/Components/Dropdown/Dropdown.razor.cs +++ b/blazorbootstrap/Components/Dropdown/Dropdown.razor.cs @@ -15,15 +15,8 @@ protected override async ValueTask DisposeAsyncCore(bool disposing) { if (disposing) { - try - { - if (IsRenderComplete) - await JSRuntime.InvokeVoidAsync("window.blazorBootstrap.dropdown.dispose", Id); - } - catch (JSDisconnectedException) - { - // do nothing - } + if (IsRenderComplete) + await SafeInvokeVoidAsync("window.blazorBootstrap.dropdown.dispose", Id); objRef?.Dispose(); } @@ -34,7 +27,7 @@ protected override async ValueTask DisposeAsyncCore(bool disposing) protected override async Task OnAfterRenderAsync(bool firstRender) { if (firstRender) - await JSRuntime.InvokeVoidAsync("window.blazorBootstrap.dropdown.initialize", Id, objRef); + await SafeInvokeVoidAsync("window.blazorBootstrap.dropdown.initialize", Id, objRef); await base.OnAfterRenderAsync(firstRender); } @@ -61,26 +54,34 @@ protected override void OnInitialized() /// /// Hides the dropdown menu of a given navbar or tabbed navigation. /// - /// - public async Task HideAsync() => await JSRuntime.InvokeVoidAsync("window.blazorBootstrap.dropdown.hide", Id); + /// Task + [AddedVersion("1.10.0")] + [Description("Hides the dropdown menu of a given navbar or tabbed navigation.")] + public async Task HideAsync() => await SafeInvokeVoidAsync("window.blazorBootstrap.dropdown.hide", Id); /// /// Shows the dropdown menu of a given navbar or tabbed navigation. /// - /// - public async Task ShowAsync() => await JSRuntime.InvokeVoidAsync("window.blazorBootstrap.dropdown.show", Id); + /// Task + [AddedVersion("1.10.0")] + [Description("Shows the dropdown menu of a given navbar or tabbed navigation.")] + public async Task ShowAsync() => await SafeInvokeVoidAsync("window.blazorBootstrap.dropdown.show", Id); /// /// Toggles the dropdown menu of a given navbar or tabbed navigation. /// - /// - public async Task ToggleAsync() => await JSRuntime.InvokeVoidAsync("window.blazorBootstrap.dropdown.toggle", Id); + /// Task + [AddedVersion("1.10.0")] + [Description("Toggles the dropdown menu of a given navbar or tabbed navigation.")] + public async Task ToggleAsync() => await SafeInvokeVoidAsync("window.blazorBootstrap.dropdown.toggle", Id); /// /// Updates the position of an element’s dropdown. /// - /// - public async Task UpdateAsync() => await JSRuntime.InvokeVoidAsync("window.blazorBootstrap.dropdown.update", Id); + /// Task + [AddedVersion("1.10.0")] + [Description("Updates the position of an element’s dropdown.")] + public async Task UpdateAsync() => await SafeInvokeVoidAsync("window.blazorBootstrap.dropdown.update", Id); #endregion @@ -88,78 +89,102 @@ protected override void OnInitialized() protected override string? ClassNames => BuildClassNames(Class, - (BootstrapClass.ButtonGroup, true), + (BootstrapClass.ButtonGroup, Split), (Direction.ToDropdownDirectionClass(), true)); /// /// If , enables the auto close. - /// - /// + /// /// Default value is true. - /// + /// + /// + [AddedVersion("1.10.0")] + [DefaultValue(true)] + [Description("If true, enables the auto close.")] [Parameter] public bool AutoClose { get; set; } = true; /// /// Gets or sets the auto close behavior of the dropdown. - /// - /// + /// /// Default value is . - /// + /// + /// + [AddedVersion("1.10.0")] + [DefaultValue(DropdownAutoCloseBehavior.Both)] + [Description("Gets or sets the auto close behavior of the dropdown.")] [Parameter] public DropdownAutoCloseBehavior AutoCloseBehavior { get; set; } = DropdownAutoCloseBehavior.Both; /// /// Gets or sets the content to be rendered within the component. + /// + /// Default value is . + /// /// - /// - /// Default value is null. - /// + [AddedVersion("1.10.0")] + [DefaultValue(null)] + [Description("Gets or sets the content to be rendered within the component.")] [Parameter] - public RenderFragment ChildContent { get; set; } = default!; + public RenderFragment? ChildContent { get; set; } /// /// Gets or sets the dropdown color. - /// - /// + /// /// Default value is . - /// + /// + /// + [AddedVersion("3.0.0")] + [DefaultValue(DropdownColor.None)] + [Description("Gets or sets the dropdown color.")] [Parameter] public DropdownColor Color { get; set; } = DropdownColor.None; /// /// Gets or sets the direction of the dropdown menu. - /// - /// + /// /// Default value is . - /// + /// + /// + [AddedVersion("1.10.0")] + [DefaultValue(DropdownDirection.Dropdown)] + [Description("Gets or sets the direction of the dropdown menu.")] [Parameter] public DropdownDirection Direction { get; set; } = DropdownDirection.Dropdown; /// /// If , dropdown will be disabled. + /// + /// Default value is . + /// /// - /// - /// Default value is false. - /// + [AddedVersion("1.10.3")] + [DefaultValue(false)] + [Description("If true, dropdown will be disabled.")] [Parameter] public bool Disabled { get; set; } /// /// This event is fired when an dropdown element has been hidden from the user (will wait for CSS transitions to complete). /// + [AddedVersion("1.10.0")] + [Description("This event is fired when an dropdown element has been hidden from the user (will wait for CSS transitions to complete).")] [Parameter] public EventCallback OnHidden { get; set; } /// /// This event is fired immediately when the hide method has been called. /// + [AddedVersion("1.10.0")] + [Description("This event is fired immediately when the hide method has been called.")] [Parameter] public EventCallback OnHiding { get; set; } /// /// This event fires immediately when the show instance method is called. /// + [AddedVersion("1.10.0")] + [Description("This event fires immediately when the show instance method is called.")] [Parameter] public EventCallback OnShowing { get; set; } @@ -167,24 +192,32 @@ protected override void OnInitialized() /// This event is fired when an dropdown element has been made visible to the user (will wait for CSS transitions to /// complete). /// + [AddedVersion("1.10.0")] + [Description("This event is fired when an dropdown element has been made visible to the user (will wait for CSS transitions to")] [Parameter] public EventCallback OnShown { get; set; } /// /// Gets or sets the dropdown size. - /// - /// + /// /// Default value is . - /// + /// + /// + [AddedVersion("1.10.3")] + [DefaultValue(DropdownSize.None)] + [Description("Gets or sets the dropdown size.")] [Parameter] public DropdownSize Size { get; set; } = DropdownSize.None; /// /// Gets or sets the toggle button split behavior. + /// + /// Default value is . + /// /// - /// - /// Default value is false. - /// + [AddedVersion("1.10.0")] + [DefaultValue(false)] + [Description("Gets or sets the toggle button split behavior.")] [Parameter] public bool Split { get; set; } diff --git a/blazorbootstrap/Components/Dropdown/DropdownActionButton.razor.cs b/blazorbootstrap/Components/Dropdown/DropdownActionButton.razor.cs index 1e7bd7296..c8de8af77 100644 --- a/blazorbootstrap/Components/Dropdown/DropdownActionButton.razor.cs +++ b/blazorbootstrap/Components/Dropdown/DropdownActionButton.razor.cs @@ -26,43 +26,53 @@ protected override void OnInitialized() /// /// Gets or sets the content to be rendered within the component. + /// + /// Default value is . + /// /// + [AddedVersion("1.10.0")] + [DefaultValue(null)] + [Description("Gets or sets the content to be rendered within the component.")] + [EditorRequired] [Parameter] public RenderFragment ChildContent { get; set; } = default!; /// /// Gets or sets the dropdown action button color. - /// - /// + /// /// Default value is . - /// + /// + /// [CascadingParameter(Name = "Color")] public DropdownColor Color { get; set; } = DropdownColor.None; /// /// Gets or sets the disabled. + /// + /// Default value is . + /// /// - /// - /// Default value is false. - /// [CascadingParameter(Name = "Disabled")] public bool Disabled { get; set; } /// /// Gets or sets the dropdown action button size. - /// - /// + /// /// Default value is . - /// + /// + /// [CascadingParameter(Name = "Size")] public DropdownSize Size { get; set; } = DropdownSize.None; /// /// Gets or sets the dropdown action button tab index. + /// + /// Default value is . + /// /// - /// - /// Default value is null. - /// + [AddedVersion("1.10.0")] + [DefaultValue(null)] + [Description("Gets or sets the dropdown action button tab index.")] [Parameter] public int? TabIndex { get; set; } diff --git a/blazorbootstrap/Components/Dropdown/DropdownHeader.razor.cs b/blazorbootstrap/Components/Dropdown/DropdownHeader.razor.cs index b97de1cb4..5f2c47aef 100644 --- a/blazorbootstrap/Components/Dropdown/DropdownHeader.razor.cs +++ b/blazorbootstrap/Components/Dropdown/DropdownHeader.razor.cs @@ -9,9 +9,16 @@ public partial class DropdownHeader : BlazorBootstrapComponentBase /// /// Gets or sets the content to be rendered within the component. + /// + /// Default value is . + /// /// + [AddedVersion("1.10.0")] + [DefaultValue(null)] + [Description("Gets or sets the content to be rendered within the component.")] + [EditorRequired] [Parameter] - public RenderFragment ChildContent { get; set; } = default!; + public RenderFragment? ChildContent { get; set; } #endregion } diff --git a/blazorbootstrap/Components/Dropdown/DropdownItem.razor.cs b/blazorbootstrap/Components/Dropdown/DropdownItem.razor.cs index 16c470bc7..c4bee7731 100644 --- a/blazorbootstrap/Components/Dropdown/DropdownItem.razor.cs +++ b/blazorbootstrap/Components/Dropdown/DropdownItem.razor.cs @@ -171,64 +171,86 @@ private void SetAttributes() /// /// Gets or sets the dropdown item active state. + /// + /// Default value is . + /// /// - /// - /// Default value is false. - /// + [AddedVersion("1.10.0")] + [DefaultValue(false)] + [Description("Gets or sets the dropdown item active state.")] [Parameter] public bool Active { get; set; } /// /// Gets or sets the content to be rendered within the component. + /// + /// Default value is . + /// /// - /// - /// Default value is null. - /// + [AddedVersion("1.10.0")] + [DefaultValue(null)] + [Description("Gets or sets the content to be rendered within the component.")] + [EditorRequired] [Parameter] - public RenderFragment ChildContent { get; set; } = default!; + public RenderFragment? ChildContent { get; set; } /// /// If , dropdown item will be disabled. + /// + /// Default value is . + /// /// - /// - /// Default value is false. - /// + [AddedVersion("1.10.0")] + [DefaultValue(false)] + [Description("If true, dropdown item will be disabled.")] [Parameter] public bool Disabled { get; set; } /// /// Gets or sets the dropdown item tab index. + /// + /// Default value is . + /// /// - /// - /// Default value is null. - /// + [AddedVersion("1.10.0")] + [DefaultValue(null)] + [Description("Gets or sets the dropdown item tab index.")] [Parameter] public int? TabIndex { get; set; } /// /// Gets or sets the target of dropdown item (if the type is link). - /// - /// + /// /// Default value is . - /// + /// + /// + [AddedVersion("1.10.0")] + [DefaultValue(Target.None)] + [Description("Gets or sets the target of dropdown item (if the type is link).")] [Parameter] public Target Target { get; set; } = Target.None; /// /// Get or sets the link href attribute (if the type is link). + /// + /// Default value is . + /// /// - /// - /// Default value is null. - /// + [AddedVersion("1.10.0")] + [DefaultValue(null)] + [Description("Get or sets the link href attribute (if the type is link).")] [Parameter] public string? To { get; set; } /// /// Gets or sets the dropdown item type. - /// - /// + /// /// Default value is . - /// + /// + /// + [AddedVersion("1.10.0")] + [DefaultValue(DropdownItemType.Button)] + [Description("Gets or sets the dropdown item type.")] [Parameter] public DropdownItemType Type { get; set; } = DropdownItemType.Button; diff --git a/blazorbootstrap/Components/Dropdown/DropdownMenu.razor.cs b/blazorbootstrap/Components/Dropdown/DropdownMenu.razor.cs index 4b5bc9d62..ecc6995a3 100644 --- a/blazorbootstrap/Components/Dropdown/DropdownMenu.razor.cs +++ b/blazorbootstrap/Components/Dropdown/DropdownMenu.razor.cs @@ -11,16 +11,26 @@ public partial class DropdownMenu : BlazorBootstrapComponentBase /// /// Gets or sets the content to be rendered within the component. + /// + /// Default value is . + /// /// + [AddedVersion("1.10.0")] + [DefaultValue(null)] + [Description("Gets or sets the content to be rendered within the component.")] + [EditorRequired] [Parameter] public RenderFragment ChildContent { get; set; } = default!; /// /// Gets or sets the dropdown menu position. - /// - /// + /// /// Default value is . - /// + /// + /// + [AddedVersion("1.10.0")] + [DefaultValue(DropdownMenuPosition.Start)] + [Description("Gets or sets the content to be rendered within the component.")] [Parameter] public DropdownMenuPosition Position { get; set; } = DropdownMenuPosition.Start; diff --git a/blazorbootstrap/Components/Dropdown/DropdownToggleButton.razor.cs b/blazorbootstrap/Components/Dropdown/DropdownToggleButton.razor.cs index bf7f823fc..87595c054 100644 --- a/blazorbootstrap/Components/Dropdown/DropdownToggleButton.razor.cs +++ b/blazorbootstrap/Components/Dropdown/DropdownToggleButton.razor.cs @@ -50,55 +50,58 @@ protected override void OnInitialized() /// /// If , enables the auto close. + /// + /// Default value is . + /// /// - /// - /// Default value is false. - /// [CascadingParameter(Name = "AutoClose")] public bool AutoClose { get; set; } /// /// Gets or sets the auto close behavior of the dropdown. - /// - /// + /// /// Default value is . - /// + /// + /// [CascadingParameter(Name = "AutoCloseBehavior")] public DropdownAutoCloseBehavior AutoCloseBehavior { get; set; } = DropdownAutoCloseBehavior.Inside; /// /// Gets or sets the content to be rendered within the component. + /// + /// Default value is . + /// /// - /// - /// Default value is null. - /// + [AddedVersion("1.10.0")] + [DefaultValue(null)] + [Description("Gets or sets the content to be rendered within the component.")] [Parameter] public RenderFragment ChildContent { get; set; } = default!; /// /// Gets or sets the dropdown toggle button color. + /// + /// Default value is . + /// /// - /// - /// Default value is . - /// [CascadingParameter(Name = "Color")] public DropdownColor Color { get; set; } = DropdownColor.None; /// /// Gets or sets the disabled. /// - /// - /// Default value is false. - /// + /// + /// Default value is . + /// [CascadingParameter(Name = "Disabled")] public bool Disabled { get; set; } /// /// Gets or sets the dropdown action button size. /// - /// + /// /// Default value is . - /// + /// [CascadingParameter(Name = "Size")] public DropdownSize Size { get; set; } = DropdownSize.None; @@ -107,9 +110,12 @@ protected override void OnInitialized() /// /// Gets or sets the dropdown toggle button tab index. /// - /// - /// Default value is null. - /// + /// + /// Default value is . + /// + [AddedVersion("1.10.0")] + [DefaultValue(null)] + [Description("Gets or sets the dropdown toggle button tab index.")] [Parameter] public int? TabIndex { get; set; } diff --git a/blazorbootstrap/Components/Form/AutoComplete/AutoComplete.razor.cs b/blazorbootstrap/Components/Form/AutoComplete/AutoComplete.razor.cs index d98eeca0b..91a0e45d0 100644 --- a/blazorbootstrap/Components/Form/AutoComplete/AutoComplete.razor.cs +++ b/blazorbootstrap/Components/Form/AutoComplete/AutoComplete.razor.cs @@ -1,5 +1,6 @@ namespace BlazorBootstrap; +[AddedVersion("1.0.0")] public partial class AutoComplete : BlazorBootstrapComponentBase { #region Fields and Constants @@ -34,7 +35,7 @@ protected override async ValueTask DisposeAsyncCore(bool disposing) try { if (IsRenderComplete) - await JSRuntime.InvokeVoidAsync("window.blazorBootstrap.autocomplete.dispose", Element); // NOTE: Always pass ElementRef + await SafeInvokeVoidAsync("window.blazorBootstrap.autocomplete.dispose", Element); // NOTE: Always pass ElementRef } catch (JSDisconnectedException) { @@ -50,7 +51,7 @@ protected override async ValueTask DisposeAsyncCore(bool disposing) protected override async Task OnAfterRenderAsync(bool firstRender) { if (firstRender) - await JSRuntime.InvokeVoidAsync("window.blazorBootstrap.autocomplete.initialize", Element, objRef); + await SafeInvokeVoidAsync("window.blazorBootstrap.autocomplete.initialize", Element, objRef); await base.OnAfterRenderAsync(firstRender); } @@ -70,6 +71,11 @@ protected override async Task OnInitializedAsync() await base.OnInitializedAsync(); } + /// + /// Handles the autocomplete dropdown hidden notification from JavaScript. + /// + [AddedVersion("1.0.0")] + [Description("Handles the autocomplete dropdown hidden notification from JavaScript.")] [JSInvokable] public void bsHiddenAutocomplete() { @@ -84,34 +90,57 @@ public void bsHiddenAutocomplete() } } + /// + /// Handles the autocomplete dropdown hide notification from JavaScript. + /// + [AddedVersion("1.0.0")] + [Description("Handles the autocomplete dropdown hide notification from JavaScript.")] [JSInvokable] public void bsHideAutocomplete() { } + /// + /// Handles the autocomplete dropdown show notification from JavaScript. + /// + [AddedVersion("1.0.0")] + [Description("Handles the autocomplete dropdown show notification from JavaScript.")] [JSInvokable] public void bsShowAutocomplete() { } + /// + /// Handles the autocomplete dropdown shown notification from JavaScript. + /// + [AddedVersion("1.0.0")] + [Description("Handles the autocomplete dropdown shown notification from JavaScript.")] [JSInvokable] public void bsShownAutocomplete() { } /// /// Disables autocomplete. /// + [AddedVersion("1.0.0")] + [Description("Disables the autocomplete input so users cannot search or change its value.")] public void Disable() => Disabled = true; /// /// Enables autocomplete. /// + [AddedVersion("1.0.0")] + [Description("Enables the autocomplete input so users can search and select a value.")] public void Enable() => Disabled = false; /// /// Refresh the autocomplete data. /// /// Task + [AddedVersion("1.0.0")] + [Description("Refreshes the autocomplete results using the current input value and data provider.")] public async Task RefreshDataAsync() => await FilterDataAsync(); /// /// Resets the autocomplete selection. /// + [AddedVersion("1.0.0")] + [Description("Clears the input and selected item, then notifies bound values and the change callback.")] public async Task ResetAsync() => await ClearInputTextAsync(); /// @@ -198,7 +227,7 @@ private async Task HideAsync() if (AdditionalAttributes is not null && AdditionalAttributes.TryGetValue(BootstrapAttributes.DataBootstrapToggle, out _)) AdditionalAttributes.Remove(BootstrapAttributes.DataBootstrapToggle); - await JSRuntime.InvokeVoidAsync("window.blazorBootstrap.autocomplete.hide", Element); + await SafeInvokeVoidAsync("window.blazorBootstrap.autocomplete.hide", Element); } private async Task OnInputChangedAsync(ChangeEventArgs args) @@ -227,7 +256,7 @@ private async Task OnInputChangedAsync(ChangeEventArgs args) cancellationTokenSource = new CancellationTokenSource(); var token = cancellationTokenSource.Token; - await Task.Delay(300, token); // 300ms timeout for the debouncing + await Task.Delay(300, token); // 300ms timeout for the debouncing await FilterDataAsync(token); closeButton?.HideLoading(); @@ -280,7 +309,7 @@ private async Task ShowAsync() if (AdditionalAttributes is not null && !AdditionalAttributes.TryGetValue(BootstrapAttributes.DataBootstrapToggle, out _)) AdditionalAttributes.Add(BootstrapAttributes.DataBootstrapToggle, "dropdown"); - await JSRuntime.InvokeVoidAsync("window.blazorBootstrap.autocomplete.show", Element); + await SafeInvokeVoidAsync("window.blazorBootstrap.autocomplete.show", Element); } #endregion @@ -294,13 +323,16 @@ private async Task ShowAsync() /// /// Gets or sets the data provider. + /// + /// Default value is . + /// /// - /// - /// Default value is null. - /// - [Parameter] + [AddedVersion("1.0.0")] + [DefaultValue(null)] + [Description("Gets or sets the delegate used to retrieve autocomplete results for the current filter.")] [EditorRequired] - public AutoCompleteDataProviderDelegate DataProvider { get; set; } = null!; + [Parameter] + public AutoCompleteDataProviderDelegate? DataProvider { get; set; } /// /// Gets all Style attributes for the autocomplete delete button. @@ -316,21 +348,28 @@ private async Task ShowAsync() /// /// Gets or sets the disabled state. + /// + /// Default value is . + /// /// - /// - /// Default value is false. - /// + [AddedVersion("1.0.0")] + [DefaultValue(false)] + [Description("Gets or sets whether the autocomplete input is disabled. When true, users cannot search or select a value.")] [Parameter] public bool Disabled { get; set; } - [CascadingParameter] private EditContext EditContext { get; set; } = default!; + [CascadingParameter] + private EditContext EditContext { get; set; } = default!; /// /// Gets or sets the empty text. - /// - /// + /// /// Default value is 'No records found.'. - /// + /// + /// + [AddedVersion("1.0.0")] + [DefaultValue("No records found.")] + [Description("Gets or sets the message displayed when the data provider returns no matching results.")] [Parameter] public string EmptyText { get; set; } = "No records found."; @@ -338,86 +377,124 @@ private async Task ShowAsync() /// /// Gets or sets the loading text. - /// - /// + /// /// Default value is 'Loading...'. - /// + /// + /// + [AddedVersion("1.0.0")] + [DefaultValue("Loading...")] + [Description("Gets or sets the message displayed while autocomplete results are loading.")] [Parameter] public string LoadingText { get; set; } = "Loading..."; /// /// This event fires immediately when the autocomplete selection changes by the user. /// + [AddedVersion("1.0.0")] + [Description("Fires after a user selects an autocomplete item and supplies the selected item.")] [Parameter] public EventCallback OnChanged { get; set; } /// /// Gets or sets the placeholder. + /// + /// Default value is . + /// /// - /// - /// Default value is null. - /// + [AddedVersion("1.0.0")] + [DefaultValue(null)] + [Description("Gets or sets placeholder text displayed when the autocomplete input has no value.")] [Parameter] public string? Placeholder { get; set; } /// /// Gets or sets the property name. + /// + /// Default value is . + /// /// - /// - /// Default value is null. - /// - [Parameter] + [AddedVersion("1.0.0")] + [DefaultValue(null)] + [Description("Gets or sets the TItem property whose text is shown and filtered in the autocomplete input.")] [EditorRequired] - public string PropertyName { get; set; } = null!; + [Parameter] + public string? PropertyName { get; set; } /// /// Gets selected item. /// - public TItem SelectedItem => selectedItem = default!; + [AddedVersion("1.0.0")] + [DefaultValue(null)] + [Description("Gets the item most recently selected by the user, or null when no item is selected.")] + public TItem? SelectedItem => selectedItem; /// /// Gets or sets the autocomplete size. - /// - /// + /// /// Default value is . - /// + /// + /// + [AddedVersion("1.0.0")] + [DefaultValue(AutoCompleteSize.Default)] + [Description("Gets or sets the Bootstrap size of the autocomplete input.")] [Parameter] public AutoCompleteSize Size { get; set; } = AutoCompleteSize.Default; /// /// Gets or sets the StringComparison. - /// - /// + /// /// Default value is . - /// + /// + /// + [AddedVersion("1.0.0")] + [DefaultValue(StringComparison.OrdinalIgnoreCase)] + [Description("Gets or sets the string-comparison rule used when filtering results.")] [Parameter] public StringComparison StringComparison { get; set; } = StringComparison.OrdinalIgnoreCase; /// /// Gets or sets the string filter operator. - /// - /// + /// /// Default value is . - /// + /// + /// + [AddedVersion("1.0.0")] + [DefaultValue(StringFilterOperator.Contains)] + [Description("Gets or sets the operator used to match the input text against PropertyName.")] [Parameter] public StringFilterOperator StringFilterOperator { get; set; } = StringFilterOperator.Contains; /// /// Gets or sets the value. + /// + /// Default value is . + /// /// - /// - /// Default value is null. - /// + [AddedVersion("1.0.0")] + [DefaultValue(null)] + [Description("Gets or sets the current text value bound to the autocomplete input.")] [Parameter] - public string Value { get; set; } = default!; + public string? Value { get; set; } /// /// This is event fires on every user keystroke that changes the textbox value. /// + [AddedVersion("1.0.0")] + [Description("Fires whenever user input changes the autocomplete text value, including changes produced by typing.")] [Parameter] public EventCallback ValueChanged { get; set; } - [Parameter] public Expression> ValueExpression { get; set; } = default!; + /// + /// Gets or sets the value expression. + /// + /// + /// Default value is . + /// + [AddedVersion("1.0.0")] + [DefaultValue(null)] + [Description("Gets or sets the expression that identifies the bound value for validation and EditContext notifications.")] + [Parameter] + public Expression>? ValueExpression { get; set; } #endregion } diff --git a/blazorbootstrap/Components/Form/CheckboxInput/CheckboxInput.razor b/blazorbootstrap/Components/Form/CheckboxInput/CheckboxInput.razor new file mode 100644 index 000000000..2f802c5dc --- /dev/null +++ b/blazorbootstrap/Components/Form/CheckboxInput/CheckboxInput.razor @@ -0,0 +1,20 @@ +@namespace BlazorBootstrap +@inherits BlazorBootstrapComponentBase + +
    + + + @if (!string.IsNullOrWhiteSpace(Label)) + { + + } +
    \ No newline at end of file diff --git a/blazorbootstrap/Components/Form/CheckboxInput/CheckboxInput.razor.cs b/blazorbootstrap/Components/Form/CheckboxInput/CheckboxInput.razor.cs new file mode 100644 index 000000000..dd103654c --- /dev/null +++ b/blazorbootstrap/Components/Form/CheckboxInput/CheckboxInput.razor.cs @@ -0,0 +1,121 @@ +namespace BlazorBootstrap; + +[AddedVersion("3.3.0")] +public partial class CheckboxInput : BlazorBootstrapComponentBase +{ + #region Fields and Constants + + private FieldIdentifier fieldIdentifier; + + #endregion + + #region Methods + + protected override void OnInitialized() + { + AdditionalAttributes ??= new Dictionary(); + + fieldIdentifier = FieldIdentifier.Create(ValueExpression); + + base.OnInitialized(); + } + + /// + /// Disables the checkbox so users cannot change its value. + /// + [AddedVersion("3.3.0")] + [Description("Disables the checkbox so users cannot change its value.")] + public void Disable() => Disabled = true; + + /// + /// Enables the checkbox so users can change its value. + /// + [AddedVersion("3.3.0")] + [Description("Enables the checkbox so users can change its value.")] + public void Enable() => Disabled = false; + + private async Task OnChange(ChangeEventArgs e) + { + var oldValue = Value; + var newValue = e.Value is not null && (bool)e.Value; + + await ValueChanged.InvokeAsync(newValue); + + EditContext?.NotifyFieldChanged(fieldIdentifier); + } + + #endregion + + #region Properties, Indexers + + protected override string? ClassNames => + BuildClassNames( + Class, + (BootstrapClass.FormCheckInput, true), + (EditContext?.FieldCssClass(fieldIdentifier) ?? string.Empty, true) + ); + + /// + /// Gets or sets whether the checkbox is disabled. + /// + /// + /// Default value is false. + /// + [AddedVersion("3.3.0")] + [DefaultValue(false)] + [Description("Gets or sets whether the checkbox is disabled. When true, users cannot change its value.")] + [Parameter] + public bool Disabled { get; set; } + + /// + /// Gets the associated . + /// + [CascadingParameter] + private EditContext? EditContext { get; set; } = default!; + + /// + /// Gets or sets the label. + /// + /// + /// Default value is . + /// + [AddedVersion("3.3.0")] + [DefaultValue(null)] + [Description("Gets or sets the label displayed next to the checkbox.")] + [Parameter] + public string? Label { get; set; } + + /// + /// Gets or sets the value. + /// + /// + /// Default value is . + /// + [AddedVersion("3.3.0")] + [DefaultValue(false)] + [Description("Gets or sets the current checked value bound to the checkbox.")] + [Parameter] + public bool Value { get; set; } + + /// + /// This event fires when the value changes. + /// + [AddedVersion("3.3.0")] + [Description("Fires whenever user interaction changes the checked value.")] + [Parameter] + public EventCallback ValueChanged { get; set; } + + /// + /// Gets or sets an expression that identifies the bound value. + /// + /// + /// Default value is . + /// + [AddedVersion("3.3.0")] + [DefaultValue(null)] + [Description("Gets or sets the expression that identifies the bound value for validation and EditContext notifications.")] + [Parameter] + public Expression> ValueExpression { get; set; } = default!; + + #endregion +} diff --git a/blazorbootstrap/Components/Form/CurrencyInput/CurrencyInput.razor.cs b/blazorbootstrap/Components/Form/CurrencyInput/CurrencyInput.razor.cs index 99881011d..7db328183 100644 --- a/blazorbootstrap/Components/Form/CurrencyInput/CurrencyInput.razor.cs +++ b/blazorbootstrap/Components/Form/CurrencyInput/CurrencyInput.razor.cs @@ -1,5 +1,6 @@ namespace BlazorBootstrap; +[AddedVersion("1.0.0")] public partial class CurrencyInput : BlazorBootstrapComponentBase { #region Fields and Constants @@ -20,7 +21,7 @@ protected override async Task OnAfterRenderAsync(bool firstRender) { if (firstRender) { - await JSRuntime.InvokeVoidAsync("window.blazorBootstrap.currencyInput.initialize", Id, isFloatingNumber(), AllowNegativeNumbers, cultureInfo.NumberFormat.CurrencyDecimalSeparator); + await SafeInvokeVoidAsync("window.blazorBootstrap.currencyInput.initialize", Id, isFloatingNumber(), AllowNegativeNumbers, cultureInfo.NumberFormat.CurrencyDecimalSeparator); var currentValue = Value; // object @@ -93,11 +94,15 @@ protected override async Task OnParametersSetAsync() /// /// Disables currency input. /// + [AddedVersion("1.0.0")] + [Description("Disables the currency input so users cannot change its value.")] public void Disable() => Disabled = true; /// /// Enables currency input. /// + [AddedVersion("1.0.0")] + [Description("Enables the currency input so users can change its value.")] public void Enable() => Disabled = false; private string ExtractValue(object value, CultureInfo cultureInfo) @@ -405,6 +410,9 @@ private bool TryParseValue(object value, out TValue newValue) /// /// Default value is false. /// + [AddedVersion("1.0.0")] + [DefaultValue(false)] + [Description("Gets or sets whether users can enter negative currency values. When false, negative input is rejected during parsing.")] [Parameter] public bool AllowNegativeNumbers { get; set; } @@ -416,6 +424,9 @@ private bool TryParseValue(object value, out TValue newValue) /// /// Default value is false. /// + [AddedVersion("1.0.0")] + [DefaultValue(false)] + [Description("Gets or sets whether browser autocomplete is enabled. When true, the browser may offer saved values for the input.")] [Parameter] public bool AutoComplete { get; set; } @@ -425,6 +436,9 @@ private bool TryParseValue(object value, out TValue newValue) /// /// Default value is . /// + [AddedVersion("1.0.0")] + [DefaultValue(CurrencySign.Standard)] + [Description("Gets or sets how the currency sign is displayed when the value is formatted.")] [Parameter] public CurrencySign CurrencySign { get; set; } = CurrencySign.Standard; @@ -434,10 +448,15 @@ private bool TryParseValue(object value, out TValue newValue) /// /// Default value is false. /// + [AddedVersion("1.0.0")] + [DefaultValue(false)] + [Description("Gets or sets whether the input is disabled. When true, users cannot change its value.")] [Parameter] public bool Disabled { get; set; } + [AddedVersion("1.0.0")] [CascadingParameter] private EditContext EditContext { get; set; } = default!; + [DefaultValue(false)] /// /// Determines whether to restrict the user input to Min and Max range. @@ -446,17 +465,22 @@ private bool TryParseValue(object value, out TValue newValue) /// /// Default value is false. /// + [AddedVersion("1.0.0")] + [Description("Gets or sets whether input is restricted to the configured minimum and maximum values. When true, values outside the range are rejected.")] [Parameter] public bool EnableMinMax { get; set; } private string fieldCssClasses => EditContext?.FieldCssClass(fieldIdentifier) ?? ""; /// - /// Determines whether to hide the currency symbol are not. + /// Gets or sets whether the currency symbol is hidden. /// /// /// Default value is false. /// + [AddedVersion("1.0.0")] + [DefaultValue(false)] + [Description("Gets or sets whether the currency symbol is hidden. When true, formatting omits the symbol while retaining the numeric value.")] [Parameter] public bool HideCurrencySymbol { get; set; } @@ -466,14 +490,18 @@ private bool TryParseValue(object value, out TValue newValue) /// /// Default value is 'en-US'. /// + [AddedVersion("1.0.0")] + [DefaultValue("en-US")] + [Description("Gets or sets the culture name used to format the currency value. It controls decimal separators, grouping, and currency conventions.")] [Parameter] - //[EditorRequired] public string Locale { get; set; } = "en-US"; /// /// Gets or sets the max. /// Max ignored if EnableMinMax="false". /// + [AddedVersion("1.0.0")] + [Description("Gets or sets the maximum permitted value. It is enforced only when EnableMinMax is true.")] [Parameter] public TValue Max { get; set; } = default!; @@ -483,6 +511,9 @@ private bool TryParseValue(object value, out TValue newValue) /// /// Default value is null. /// + [AddedVersion("1.0.0")] + [DefaultValue(null)] + [Description("Gets or sets the maximum number of fraction digits used when formatting the value. Null uses the culture default.")] [Parameter] public byte? MaximumFractionDigits { get; set; } @@ -490,6 +521,8 @@ private bool TryParseValue(object value, out TValue newValue) /// Gets or sets the min. /// Min ignored if EnableMinMax="false". /// + [AddedVersion("1.0.0")] + [Description("Gets or sets the minimum permitted value. It is enforced only when EnableMinMax is true.")] [Parameter] public TValue Min { get; set; } = default!; @@ -499,6 +532,9 @@ private bool TryParseValue(object value, out TValue newValue) /// /// Default value is null. /// + [AddedVersion("1.0.0")] + [DefaultValue(null)] + [Description("Gets or sets the minimum number of fraction digits used when formatting the value. Null uses the culture default.")] [Parameter] public byte? MinimumFractionDigits { get; set; } @@ -509,6 +545,9 @@ private bool TryParseValue(object value, out TValue newValue) /// /// Default value is 1. /// + [AddedVersion("1.0.0")] + [DefaultValue(1)] + [Description("Gets or sets the minimum number of integer digits used when formatting. Values with fewer digits are left-padded with zeros.")] [Parameter] public byte MinimumIntegerDigits { get; set; } = 1; @@ -518,6 +557,9 @@ private bool TryParseValue(object value, out TValue newValue) /// /// Default value is null. /// + [AddedVersion("1.0.0")] + [DefaultValue(null)] + [Description("Gets or sets placeholder text displayed when the input has no value.")] [Parameter] public string? Placeholder { get; set; } @@ -527,22 +569,39 @@ private bool TryParseValue(object value, out TValue newValue) /// /// Default value is . /// + [AddedVersion("1.0.0")] + [DefaultValue(Alignment.None)] + [Description("Gets or sets the horizontal alignment of the formatted input value.")] [Parameter] public Alignment TextAlignment { get; set; } = Alignment.None; /// /// Gets or sets the value. /// + [AddedVersion("1.0.0")] + [Description("Gets or sets the current currency value bound to the input.")] [Parameter] public TValue Value { get; set; } = default!; /// /// This event fired on every user keystroke that changes the CurrencyInput value. /// + [AddedVersion("1.0.0")] + [Description("Fires whenever user input changes the currency value, including changes produced by typing.")] [Parameter] public EventCallback ValueChanged { get; set; } - [Parameter] public Expression> ValueExpression { get; set; } = default!; + /// + /// Gets or sets an expression that identifies the bound value. + /// + /// + /// Default value is . + /// + [AddedVersion("1.0.0")] + [DefaultValue(null)] + [Description("Gets or sets the expression that identifies the bound value for validation and EditContext notifications.")] + [Parameter] + public Expression> ValueExpression { get; set; } = default!; #endregion } diff --git a/blazorbootstrap/Components/Form/DateInput/DateInput.razor.cs b/blazorbootstrap/Components/Form/DateInput/DateInput.razor.cs index 181d4239b..8952d080b 100644 --- a/blazorbootstrap/Components/Form/DateInput/DateInput.razor.cs +++ b/blazorbootstrap/Components/Form/DateInput/DateInput.razor.cs @@ -1,5 +1,6 @@ namespace BlazorBootstrap; +[AddedVersion("1.5.0")] public partial class DateInput : BlazorBootstrapComponentBase { #region Fields and Constants @@ -116,13 +117,17 @@ protected override async Task OnParametersSetAsync() } /// - /// Disables currency input. + /// Disables the date input so users cannot change its value. /// + [AddedVersion("1.5.0")] + [Description("Disables the date input so users cannot change its value.")] public void Disable() => Disabled = true; /// - /// Enables currency input. + /// Enables the date input so users can change its value. /// + [AddedVersion("1.5.0")] + [Description("Enables the date input so users can change its value.")] public void Enable() => Disabled = false; private string GetFormattedValue(object value) @@ -230,7 +235,7 @@ private async Task SetValueAsync(TValue oldValue, object? newValue) formattedValue = GetFormattedValue(Value!); if (oldValue!.Equals(Value)) - await JSRuntime.InvokeVoidAsync("window.blazorBootstrap.dateInput.setValue", Id, formattedValue); + await SafeInvokeVoidAsync("window.blazorBootstrap.dateInput.setValue", Id, formattedValue); await ValueChanged.InvokeAsync(Value); @@ -286,75 +291,102 @@ private bool TryParseValue(object value, out TValue newValue) private string autoComplete => AutoComplete ? "true" : "false"; /// - /// If , DateInput can complete the values automatically by the browser. + /// Gets or sets whether browser autocomplete is enabled for the date input. /// /// /// Default value is false. /// + [AddedVersion("1.5.0")] + [DefaultValue(false)] + [Description("Gets or sets whether browser autocomplete is enabled. When true, the browser may offer saved dates for the input.")] [Parameter] public bool AutoComplete { get; set; } /// - /// Gets or sets the disabled state. + /// Gets or sets whether the date input is disabled. /// /// /// Default value is false. /// + [AddedVersion("1.5.0")] + [DefaultValue(false)] + [Description("Gets or sets whether the date input is disabled. When true, users cannot change its value.")] [Parameter] public bool Disabled { get; set; } - [CascadingParameter] private EditContext EditContext { get; set; } = default!; + [AddedVersion("1.5.0")] + [DefaultValue(false)] + [CascadingParameter] + private EditContext EditContext { get; set; } = default!; /// - /// Determines whether to restrict the user input to Min and Max range. - /// If , restricts the user input between the Min and Max range. Else accepts the user input. + /// Gets or sets whether input is restricted to the configured minimum and maximum dates. + /// /// /// /// Default value is false. /// + [Description("Gets or sets whether input is restricted to the configured minimum and maximum dates. When true, dates outside the range are rejected.")] [Parameter] public bool EnableMinMax { get; set; } private string fieldCssClasses => EditContext?.FieldCssClass(fieldIdentifier) ?? ""; /// - /// Gets or sets the max. - /// Allowed format is yyyy-mm-dd. + /// Gets or sets the maximum permitted date. + /// /// + [AddedVersion("1.5.0")] + [Description("Gets or sets the maximum permitted date. It is enforced only when EnableMinMax is true.")] [Parameter] public TValue Max { get; set; } = default!; /// - /// Gets or sets the min. - /// Allowed format is yyyy-mm-dd. + /// Gets or sets the minimum permitted date. + /// /// + [AddedVersion("1.5.0")] + [Description("Gets or sets the minimum permitted date. It is enforced only when EnableMinMax is true.")] [Parameter] public TValue Min { get; set; } = default!; /// - /// Gets or sets the placeholder. + /// Gets or sets placeholder text displayed when the input has no value. /// /// /// Default value is null. /// + [AddedVersion("1.5.0")] + [DefaultValue(null)] + [Description("Gets or sets placeholder text displayed when the input has no value.")] [Parameter] public string? Placeholder { get; set; } /// - /// Gets or sets the value. + /// Gets or sets the current date value bound to the input. /// + [AddedVersion("1.5.0")] + [Description("Gets or sets the current date value bound to the input.")] [Parameter] public TValue Value { get; set; } = default!; /// - /// This event fired on every user keystroke that changes the DateInput value. + /// Occurs whenever user input changes the date value, including changes produced by typing. /// + [AddedVersion("1.5.0")] + [Description("Fires whenever user input changes the date value, including changes produced by typing.")] [Parameter] public EventCallback ValueChanged { get; set; } /// - /// Gets or sets the expression. + /// Gets or sets the expression that identifies the bound value for validation and EditContext notifications. /// + /// + /// Default value is . + /// + [AddedVersion("1.5.0")] + [DefaultValue(null)] + [Description("Gets or sets the expression that identifies the bound value for validation and EditContext notifications.")] [Parameter] public Expression> ValueExpression { get; set; } = default!; diff --git a/blazorbootstrap/Components/Form/DragAndDropFileInput/DragAndDropFileInput.razor b/blazorbootstrap/Components/Form/DragAndDropFileInput/DragAndDropFileInput.razor new file mode 100644 index 000000000..6206d7c19 --- /dev/null +++ b/blazorbootstrap/Components/Form/DragAndDropFileInput/DragAndDropFileInput.razor @@ -0,0 +1,50 @@ +@namespace BlazorBootstrap +@inherits FileInputBase + +
    +
    + + +
    + + @if (files.Any()) + { +
      + @foreach (var file in files) + { +
    • + @file.Name + +
    • + } +
    + } + + @if (validationErrors.Any()) + { + + } +
    diff --git a/blazorbootstrap/Components/Form/DragAndDropFileInput/DragAndDropFileInput.razor.cs b/blazorbootstrap/Components/Form/DragAndDropFileInput/DragAndDropFileInput.razor.cs new file mode 100644 index 000000000..5315d7173 --- /dev/null +++ b/blazorbootstrap/Components/Form/DragAndDropFileInput/DragAndDropFileInput.razor.cs @@ -0,0 +1,55 @@ +namespace BlazorBootstrap; + +public partial class DragAndDropFileInput : FileInputBase +{ + #region Fields and Constants + + private int dragDepth; + + #endregion + + #region Methods + + #region Protected Methods + + protected void OnDragEnter(DragEventArgs _) + { + dragDepth++; + StateHasChanged(); + } + + protected void OnDragLeave(DragEventArgs _) + { + dragDepth = Math.Max(0, dragDepth - 1); + StateHasChanged(); + } + + protected void OnDrop(DragEventArgs _) + { + dragDepth = 0; + StateHasChanged(); + } + + #endregion + + #endregion + + #region Properties, Indexers + + /// + /// Gets or sets the contextual background color of the drag-and-drop area. + /// + [AddedVersion("4.0.0")] + [DefaultValue(BackgroundColor.None)] + [Description("Gets or sets the Bootstrap contextual background color of the drop area. The color is applied while the area is not using its default background.")] + [Parameter] + public BackgroundColor BackgroundColor { get; set; } = BackgroundColor.None; + + protected override string? ClassNames => + BuildClassNames(Class, + ("bb-drag-and-drop-file-input", true), + (BackgroundColor.ToBackgroundClass(), BackgroundColor != BackgroundColor.None), + ("bb-drag-and-drop-file-input--dragging", dragDepth > 0)); + + #endregion +} diff --git a/blazorbootstrap/Components/Form/DragAndDropFileInput/DragAndDropFileInput.razor.css b/blazorbootstrap/Components/Form/DragAndDropFileInput/DragAndDropFileInput.razor.css new file mode 100644 index 000000000..16dfd3ba7 --- /dev/null +++ b/blazorbootstrap/Components/Form/DragAndDropFileInput/DragAndDropFileInput.razor.css @@ -0,0 +1,43 @@ +.bb-drag-and-drop-file-input { + position: relative; + min-height: 9rem; + overflow: hidden; + border: 2px dashed var(--bs-border-color); + border-radius: var(--bs-border-radius); +} + +.bb-drag-and-drop-file-input--dragging { + border-color: var(--bs-primary); + background-color: var(--bs-primary-bg-subtle); +} + +::deep .bb-drag-and-drop-file-input__native-input { + position: absolute; + inset: 0; + z-index: 1; + width: 100%; + height: 100%; + cursor: pointer; + opacity: 0; +} + +.bb-drag-and-drop-file-input__content { + display: flex; + min-height: 9rem; + flex-direction: column; + align-items: center; + justify-content: center; + gap: .25rem; + padding: 1rem; + text-align: center; + pointer-events: none; +} + +.bb-drag-and-drop-file-input__title { + font-weight: 500; +} + +.bb-drag-and-drop-file-input__hint { + color: var(--bs-secondary-color); + font-size: .875em; +} diff --git a/blazorbootstrap/Components/Form/EnumInput/EnumInput.razor b/blazorbootstrap/Components/Form/EnumInput/EnumInput.razor new file mode 100644 index 000000000..1d40a16bf --- /dev/null +++ b/blazorbootstrap/Components/Form/EnumInput/EnumInput.razor @@ -0,0 +1,22 @@ +@namespace BlazorBootstrap +@inherits BlazorBootstrapComponentBase +@typeparam TEnum + + diff --git a/blazorbootstrap/Components/Form/EnumInput/EnumInput.razor.cs b/blazorbootstrap/Components/Form/EnumInput/EnumInput.razor.cs new file mode 100644 index 000000000..940719a56 --- /dev/null +++ b/blazorbootstrap/Components/Form/EnumInput/EnumInput.razor.cs @@ -0,0 +1,176 @@ +namespace BlazorBootstrap; + +[AddedVersion("3.5.0")] +public partial class EnumInput : BlazorBootstrapComponentBase where TEnum : Enum +{ + #region Fields and Constants + + private FieldIdentifier fieldIdentifier = default!; + + private List? items; + + #endregion + + #region Methods + + protected override void OnInitialized() + { + items = EnumUtility.GetEnumItems(); + + AdditionalAttributes ??= new Dictionary(); + + base.OnInitialized(); + } + + protected override void OnParametersSet() + { + if (TextExpression is not null) + fieldIdentifier = FieldIdentifier.Create(TextExpression); + + if (ValueExpression is not null) + fieldIdentifier = FieldIdentifier.Create(ValueExpression!); + } + + /// + /// Disables the . + /// + [AddedVersion("3.5.0")] + [Description("Disables the enum input so users cannot change its selection.")] + public void Disable() => Disabled = true; + + /// + /// Enables the . + /// + [AddedVersion("3.5.0")] + [Description("Enables the enum input so users can change its selection.")] + public void Enable() => Disabled = false; + + private void OnChange(ChangeEventArgs e) + { + if (e.Value is null) + { + Value = default!; + return; + } + + var newValue = int.TryParse(e.Value.ToString(), out int _value) ? _value : default!; + + // Value + if (ValueChanged.HasDelegate) + ValueChanged.InvokeAsync(newValue); + else + Value = newValue; + + // Text + if (TextChanged.HasDelegate) + TextChanged.InvokeAsync(items?.FirstOrDefault(i => i.Value == newValue)?.Text ?? string.Empty); + else + Text = items?.FirstOrDefault(i => i.Value == newValue)?.Text ?? string.Empty; + } + + #endregion + + #region Properties, Indexers + + protected override string? ClassNames => + BuildClassNames( + Class, + (BootstrapClass.FormSelect, true), + (Size.ToEnumIputSizeClass(), (Size != EnumInputSize.None && Size != EnumInputSize.Normal)) + ); + + /// + /// Gets or sets the disabled state. + /// + /// Default value is false. + /// + /// + [AddedVersion("3.5.0")] + [DefaultValue(false)] + [Description("Gets or sets whether the enum input is disabled. When true, users cannot change its selection.")] + [Parameter] + public bool Disabled { get; set; } = false; + + [CascadingParameter] + private EditContext EditContext { get; set; } = default!; + + private string FieldCssClasses => EditContext?.FieldCssClass(fieldIdentifier) ?? ""; + + /// + /// Gets or sets the size. + /// + /// Default value is . + /// + /// + [AddedVersion("3.5.0")] + [DefaultValue(EnumInputSize.None)] + [Description("Gets or sets the Bootstrap size of the enum select input.")] + [Parameter] + public EnumInputSize Size { get; set; } = EnumInputSize.None; + + /// + /// Gets or sets the text. + /// + /// Default value is . + /// + /// + [AddedVersion("3.5.0")] + [DefaultValue(null)] + [Description("Gets or sets the display text of the selected enum value.")] + [Parameter] + public string Text { get; set; } = default!; + + /// + /// This event fires when the text changes. + /// + [AddedVersion("3.5.0")] + [Description("Fires whenever selection changes the display text of the selected enum value.")] + [Parameter] + public EventCallback TextChanged { get; set; } + + /// + /// Gets or sets the expression. + /// + /// + /// Default value is . + /// + [AddedVersion("3.5.0")] + [DefaultValue(null)] + [Description("Gets or sets the expression that identifies the bound value for validation and EditContext notifications.")] + [Parameter] + public Expression> TextExpression { get; set; } = default!; + + /// + /// Gets or sets the value. + /// + /// Default value is 0. + /// + /// + [AddedVersion("3.5.0")] + [DefaultValue(0)] + [Description("Gets or sets the numeric value of the selected enum member.")] + [Parameter] + public int Value { get; set; } + + /// + /// This event fires when the value changes. + /// + [AddedVersion("3.5.0")] + [Description("Fires whenever selection changes the numeric value of the selected enum member.")] + [Parameter] + public EventCallback ValueChanged { get; set; } + + /// + /// Gets or sets the expression. + /// + /// + /// Default value is . + /// + [AddedVersion("3.5.0")] + [DefaultValue(null)] + [Description("Gets or sets the expression that identifies the bound value for validation and EditContext notifications.")] + [Parameter] + public Expression> ValueExpression { get; set; } = default!; + + #endregion +} diff --git a/blazorbootstrap/Components/Form/FileInput/FileInput.razor b/blazorbootstrap/Components/Form/FileInput/FileInput.razor new file mode 100644 index 000000000..cbd8cab3e --- /dev/null +++ b/blazorbootstrap/Components/Form/FileInput/FileInput.razor @@ -0,0 +1,40 @@ +@namespace BlazorBootstrap +@inherits FileInputBase + +
    + + + @if (files.Any()) + { +
      + @foreach (var file in files) + { +
    • + @file.Name + +
    • + } +
    + } + + @if (validationErrors.Any()) + { + + } + + @if (!string.IsNullOrWhiteSpace(HintText)) + { +
    @HintText
    + } +
    diff --git a/blazorbootstrap/Components/Form/FileInput/FileInput.razor.cs b/blazorbootstrap/Components/Form/FileInput/FileInput.razor.cs new file mode 100644 index 000000000..2fffec072 --- /dev/null +++ b/blazorbootstrap/Components/Form/FileInput/FileInput.razor.cs @@ -0,0 +1,22 @@ +namespace BlazorBootstrap; + +public partial class FileInput : FileInputBase +{ + #region Properties, Indexers + + /// + /// Gets or sets the component size. + /// + [AddedVersion("4.0.0")] + [DefaultValue(FileInputSize.Default)] + [Description("Gets or sets the Bootstrap size used to render the file picker.")] + [Parameter] + public FileInputSize Size { get; set; } = FileInputSize.Default; + + protected override string? ClassNames => + BuildClassNames(Class, + (BootstrapClass.FormControl, true), + (Size.ToFileInputSizeClass(), Size != FileInputSize.Default)); + + #endregion +} diff --git a/blazorbootstrap/Components/Form/FileInput/FileInputBase.cs b/blazorbootstrap/Components/Form/FileInput/FileInputBase.cs new file mode 100644 index 000000000..16e66e850 --- /dev/null +++ b/blazorbootstrap/Components/Form/FileInput/FileInputBase.cs @@ -0,0 +1,229 @@ +namespace BlazorBootstrap; + +public abstract class FileInputBase : BlazorBootstrapComponentBase +{ + #region Fields and Constants + + private const string AllowedFileTypesToken = "{AllowedFileTypes}"; + private const string DefaultInvalidFileTypeErrorMessage = "{FileName}: the file extension is not allowed."; + private const string DefaultMaxFileCountErrorMessage = "{FileName}: the maximum number of files has been reached."; + private const string DefaultMaxFileSizeErrorMessage = "{FileName}: the file exceeds the maximum allowed size."; + private const string DefaultSingleFileErrorMessage = "Only one file can be selected."; + private const string FileNameToken = "{FileName}"; + private const string MaxFileCountToken = "{MaxFileCount}"; + private const string MaxFileSizeToken = "{MaxFileSize}"; + + protected readonly List files = new(); + + protected readonly List validationErrors = new(); + + #endregion + + #region Methods + + #region Protected Methods + + protected string GetFileValidationError(IBrowserFile file) + { + if (MaxFileSize.HasValue && file.Size > MaxFileSize.Value) + return FormatValidationMessage(MaxFileSizeErrorMessage, + (FileNameToken, file.Name), + (MaxFileSizeToken, MaxFileSize.Value.ToString())); + + if (NormalizedAllowedFileTypes.Count > 0 && !NormalizedAllowedFileTypes.Contains(NormalizeExtension(Path.GetExtension(file.Name)))) + return FormatValidationMessage(InvalidFileTypeErrorMessage, + (AllowedFileTypesToken, Accept), + (FileNameToken, file.Name)); + + return string.Empty; + } + + protected async Task OnInputFileChangedAsync(InputFileChangeEventArgs e) + { + validationErrors.Clear(); + + var selectedFiles = Multiple ? e.GetMultipleFiles(int.MaxValue) : new List { e.File }; + var hasChanged = false; + + if (!Multiple) + { + files.Clear(); + hasChanged = true; + + if (e.FileCount > 1) + validationErrors.Add(SingleFileErrorMessage); + } + + foreach (var selectedFile in selectedFiles) + { + if (MaxFileCount.HasValue && files.Count >= MaxFileCount.Value) + { + validationErrors.Add(FormatValidationMessage(MaxFileCountErrorMessage, + (FileNameToken, selectedFile.Name), + (MaxFileCountToken, MaxFileCount.Value.ToString()))); + continue; + } + + var validationError = GetFileValidationError(selectedFile); + if (!string.IsNullOrEmpty(validationError)) + { + validationErrors.Add(validationError); + continue; + } + + files.Add(selectedFile); + hasChanged = true; + } + + if (hasChanged) + await FilesChanged.InvokeAsync(files.AsReadOnly()); + } + + protected string NormalizeExtension(string? extension) => extension?.Trim().TrimStart('.').ToUpperInvariant() ?? string.Empty; + + protected async Task RemoveFileAsync(IBrowserFile file) + { + if (!files.Remove(file)) + return; + + await FilesChanged.InvokeAsync(files.AsReadOnly()); + } + + #endregion + + #region Private Methods + + private static string FormatValidationMessage(string template, params (string Token, string Value)[] tokens) + { + foreach (var token in tokens) + template = template.Replace(token.Token, token.Value, StringComparison.Ordinal); + + return template; + } + + #endregion + + #endregion + + #region Properties, Indexers + + protected string Accept => string.Join(',', NormalizedAllowedFileTypes.Select(fileType => $".{fileType.ToLowerInvariant()}")); + + protected HashSet NormalizedAllowedFileTypes => + AllowedFileTypes? + .Select(NormalizeExtension) + .Where(fileType => !string.IsNullOrWhiteSpace(fileType)) + .ToHashSet(StringComparer.OrdinalIgnoreCase) + ?? new HashSet(StringComparer.OrdinalIgnoreCase); + + /// + /// Gets or sets the allowed file extensions. + /// An empty collection allows all extensions. Values may include a leading dot and are matched without regard to case. + /// + [AddedVersion("4.0.0")] + [DefaultValue(null)] + [Description("Gets or sets the file extensions accepted by the picker. Null or an empty collection permits every extension.")] + [Parameter] + public IEnumerable? AllowedFileTypes { get; set; } + + /// + /// Gets or sets the accessible label for the file selection area. + /// + [AddedVersion("4.0.0")] + [DefaultValue("Select files")] + [Description("Gets or sets the accessible label for the file selection area.")] + [Parameter] + public string AriaLabel { get; set; } = "Select files"; + + /// + /// This event fires when the selected files change. + /// + [AddedVersion("4.0.0")] + [Description("Fires after accepted files are added or removed and supplies the current read-only file list.")] + [Parameter] + public EventCallback> FilesChanged { get; set; } + + /// + /// Gets or sets the hint text displayed below the component. + /// + [AddedVersion("4.0.0")] + [DefaultValue(null)] + [Description("Gets or sets supplementary text displayed below the file selection area.")] + [Parameter] + public string? HintText { get; set; } + + /// + /// Gets or sets the invalid file type validation message template. + /// Supported tokens: {FileName} and {AllowedFileTypes}. + /// + [AddedVersion("4.0.0")] + [DefaultValue(DefaultInvalidFileTypeErrorMessage)] + [Description("Gets or sets the message template used when a selected file extension is not allowed. Supports {FileName} and {AllowedFileTypes} tokens.")] + [Parameter] + public string InvalidFileTypeErrorMessage { get; set; } = DefaultInvalidFileTypeErrorMessage; + + /// + /// Gets or sets the maximum number of selected files. + /// + [AddedVersion("4.0.0")] + [DefaultValue(null)] + [Description("Gets or sets the maximum number of accepted files. Null does not impose a file-count limit.")] + [Parameter] + public int? MaxFileCount { get; set; } + + /// + /// Gets or sets the maximum file count validation message template. + /// Supported tokens: {FileName} and {MaxFileCount}. + /// + [AddedVersion("4.0.0")] + [DefaultValue(DefaultMaxFileCountErrorMessage)] + [Description("Gets or sets the message template used when a file exceeds the configured file-count limit. Supports {FileName} and {MaxFileCount} tokens.")] + [Parameter] + public string MaxFileCountErrorMessage { get; set; } = DefaultMaxFileCountErrorMessage; + + /// + /// Gets or sets the maximum allowed file size in bytes. + /// + [AddedVersion("4.0.0")] + [DefaultValue(null)] + [Description("Gets or sets the maximum accepted file size in bytes. Null does not impose a size limit.")] + [Parameter] + public long? MaxFileSize { get; set; } + + /// + /// Gets or sets the maximum file size validation message template. + /// Supported tokens: {FileName} and {MaxFileSize}. + /// + [AddedVersion("4.0.0")] + [DefaultValue(DefaultMaxFileSizeErrorMessage)] + [Description("Gets or sets the message template used when a file exceeds the configured size limit. Supports {FileName} and {MaxFileSize} tokens.")] + [Parameter] + public string MaxFileSizeErrorMessage { get; set; } = DefaultMaxFileSizeErrorMessage; + + /// + /// Gets or sets whether multiple files can be selected. + /// + [AddedVersion("4.0.0")] + [DefaultValue(false)] + [Description("Gets or sets whether users can select multiple files. When false, selecting a file replaces the current selection.")] + [Parameter] + public bool Multiple { get; set; } + + /// + /// Gets the currently selected files. + /// + [AddedVersion("4.0.0")] + [Description("Gets a read-only list of files currently accepted by the component.")] + public IReadOnlyList SelectedFiles => files.AsReadOnly(); + + /// + /// Gets or sets the single-file selection validation message template. + /// + [AddedVersion("4.0.0")] + [DefaultValue(DefaultSingleFileErrorMessage)] + [Description("Gets or sets the message shown when users select multiple files while Multiple is false.")] + [Parameter] + public string SingleFileErrorMessage { get; set; } = DefaultSingleFileErrorMessage; + + #endregion +} diff --git a/blazorbootstrap/Components/Form/NumberInput/NumberInput.razor.cs b/blazorbootstrap/Components/Form/NumberInput/NumberInput.razor.cs index 74c2ca9a9..d4cd82f86 100644 --- a/blazorbootstrap/Components/Form/NumberInput/NumberInput.razor.cs +++ b/blazorbootstrap/Components/Form/NumberInput/NumberInput.razor.cs @@ -1,5 +1,6 @@ namespace BlazorBootstrap; +[AddedVersion("1.0.0")] public partial class NumberInput : BlazorBootstrapComponentBase { #region Fields and Constants @@ -18,7 +19,7 @@ protected override async Task OnAfterRenderAsync(bool firstRender) { if (firstRender) { - await JSRuntime.InvokeVoidAsync("window.blazorBootstrap.numberInput.initialize", Id, isFloatingNumber(), AllowNegativeNumbers, cultureInfo.NumberFormat.NumberDecimalSeparator); + await SafeInvokeVoidAsync("window.blazorBootstrap.numberInput.initialize", Id, isFloatingNumber(), AllowNegativeNumbers, cultureInfo.NumberFormat.NumberDecimalSeparator); var currentValue = Value; // object @@ -78,13 +79,17 @@ protected override async Task OnInitializedAsync() } /// - /// Disables number input. + /// Disables the number input so users cannot change its value. /// + [AddedVersion("1.0.0")] + [Description("Disables the number input so users cannot change its value.")] public void Disable() => Disabled = true; /// - /// Enables number input. + /// Enables the number input so users can change its value. /// + [AddedVersion("1.0.0")] + [Description("Enables the number input so users can change its value.")] public void Enable() => Disabled = false; private string GetInvariantNumber(TValue value) @@ -261,7 +266,7 @@ private async Task OnChange(ChangeEventArgs e) Value = value; if (oldValue!.Equals(Value)) - await JSRuntime.InvokeVoidAsync("window.blazorBootstrap.numberInput.setValue", Id, Value); + await SafeInvokeVoidAsync("window.blazorBootstrap.numberInput.setValue", Id, Value); await ValueChanged.InvokeAsync(Value); @@ -356,107 +361,147 @@ private bool TryParseValue(object value, out TValue newValue) /// /// Default value is false. /// + [AddedVersion("1.0.0")] + [DefaultValue(false)] + [Description("Gets or sets whether users can enter negative numbers. When false, negative input is rejected during parsing.")] [Parameter] public bool AllowNegativeNumbers { get; set; } private string autoComplete => AutoComplete ? "true" : "false"; /// - /// If , NumberInput can complete the values automatically by the browser. + /// Gets or sets whether browser autocomplete is enabled for the number input. /// /// /// Default value is false. /// + [AddedVersion("1.0.0")] + [DefaultValue(false)] + [Description("Gets or sets whether browser autocomplete is enabled. When true, the browser may offer saved values for the input.")] [Parameter] public bool AutoComplete { get; set; } /// - /// Gets or sets the disabled state . + /// Gets or sets whether the input is disabled. /// /// /// Default value is false. /// + [AddedVersion("1.0.0")] + [DefaultValue(false)] + [Description("Gets or sets whether the input is disabled. When true, users cannot change its value.")] [Parameter] public bool Disabled { get; set; } + [AddedVersion("1.0.0")] [CascadingParameter] private EditContext EditContext { get; set; } = default!; + [DefaultValue(false)] /// - /// Determines whether to restrict the user input to Min and Max range. - /// If , restricts the user input between the Min and Max range. Else accepts the user input. + /// Gets or sets whether input is restricted to the configured minimum and maximum values. + /// /// /// /// Default value is false. /// + [Description("Gets or sets whether input is restricted to the configured minimum and maximum values. When true, values outside the range are rejected.")] [Parameter] public bool EnableMinMax { get; set; } private string fieldCssClasses => EditContext?.FieldCssClass(fieldIdentifier) ?? ""; /// - /// Gets or sets the locale. Default locale is 'en-US'. + /// Gets or sets the culture name used to parse and format the number. /// /// /// Default value is 'en-US'. /// [Parameter] //[EditorRequired] + [AddedVersion("1.0.0")] public string Locale { get; set; } = "en-US"; /// - /// Gets or sets the max. - /// Max ignored if EnableMinMax="false". + /// Gets or sets the maximum permitted value. + /// /// + [AddedVersion("1.0.0")] + [Description("Gets or sets the maximum permitted value. It is enforced only when EnableMinMax is true.")] [Parameter] public TValue Max { get; set; } = default!; /// - /// Gets or sets the min. - /// Min ignored if EnableMinMax="false". + /// Gets or sets the minimum permitted value. + /// /// + [AddedVersion("1.0.0")] + [Description("Gets or sets the minimum permitted value. It is enforced only when EnableMinMax is true.")] [Parameter] public TValue Min { get; set; } = default!; /// - /// Gets or sets the placeholder. + /// Gets or sets placeholder text displayed when the input has no value. /// /// /// Default value is null. /// + [AddedVersion("1.0.0")] + [DefaultValue(null)] + [Description("Gets or sets placeholder text displayed when the input has no value.")] [Parameter] public string? Placeholder { get; set; } /// - /// Gets or sets the step. + /// Gets or sets the increment used by the browser's number input controls. /// /// /// Default value is null. /// + [AddedVersion("1.0.0")] + [DefaultValue(null)] + [Description("Gets or sets the increment used by the browser's number input controls.")] [Parameter] public double? Step { get; set; } /// - /// Gets or sets the text alignment. + /// Gets or sets the horizontal alignment of the input value. /// /// /// Default value is . /// + [AddedVersion("1.0.0")] + [DefaultValue(Alignment.None)] + [Description("Gets or sets the horizontal alignment of the input value.")] [Parameter] public Alignment TextAlignment { get; set; } = Alignment.None; /// - /// Gets or sets the value. + /// Gets or sets the current numeric value bound to the input. /// + [AddedVersion("1.0.0")] + [Description("Gets or sets the current numeric value bound to the input.")] [Parameter] public TValue Value { get; set; } = default!; /// - /// This event fired on every user keystroke that changes the NumberInput value. + /// Occurs whenever user input changes the number value, including changes produced by typing. /// + [AddedVersion("1.0.0")] + [Description("Occurs whenever user input changes the number value, including changes produced by typing.")] [Parameter] public EventCallback ValueChanged { get; set; } - [Parameter] public Expression> ValueExpression { get; set; } = default!; + /// + /// Gets or sets the expression that identifies the bound value for validation and EditContext notifications. + /// + /// + /// Default value is . + /// + [AddedVersion("1.0.0")] + [DefaultValue(null)] + [Description("Gets or sets the expression that identifies the bound value for validation and EditContext notifications.")] + [Parameter] + public Expression> ValueExpression { get; set; } = default!; #endregion } diff --git a/blazorbootstrap/Components/Form/OTPInput/OTPInput.razor b/blazorbootstrap/Components/Form/OTPInput/OTPInput.razor new file mode 100644 index 000000000..a9958dc7e --- /dev/null +++ b/blazorbootstrap/Components/Form/OTPInput/OTPInput.razor @@ -0,0 +1,20 @@ +@namespace BlazorBootstrap +@inherits BlazorBootstrapComponentBase + +
    + @for (int i = 0; i < Length; i++) + { + var index = i; + var inputId = GetInputId(index); + + + } +
    \ No newline at end of file diff --git a/blazorbootstrap/Components/Form/OTPInput/OTPInput.razor.cs b/blazorbootstrap/Components/Form/OTPInput/OTPInput.razor.cs new file mode 100644 index 000000000..aa5bed813 --- /dev/null +++ b/blazorbootstrap/Components/Form/OTPInput/OTPInput.razor.cs @@ -0,0 +1,234 @@ +namespace BlazorBootstrap; + +public partial class OTPInput : BlazorBootstrapComponentBase +{ + #region Fields and Constants + + private string[] otpValues = Array.Empty(); + + #endregion + + #region Methods + + // Auto focus + // Color + + protected override void OnParametersSet() + { + if (otpValues.Length != Length) + { + otpValues = new string[Length]; + Array.Fill(otpValues, string.Empty); + } + } + + /// + /// Clears the OTP input fields. + /// + [AddedVersion("4.0.0")] + [Description("Clears every OTP digit, raises the change callback, and returns focus to the first field.")] + public async Task ClearAsync() + { + otpValues = new string[Length]; + Array.Fill(otpValues, string.Empty); + await NotifyChangesAsync(); + + if (Length > 0) + await SafeInvokeVoidAsync(JsInteropUtils.FocusInputElement, GetInputId(0)); + + await InvokeAsync(StateHasChanged); + } + + private string GetInputId(int index) => $"{Id}-otp-input-{index}"; + + private async Task NotifyChangesAsync() + { + Console.WriteLine(">> NotifyChangesAsync called"); + var otpValue = string.Join(string.Empty, otpValues); + Console.WriteLine($">> otpValue: {otpValue}"); + await OnOTPChanged.InvokeAsync(otpValue); + + if (otpValue.Length == Length && !otpValues.Any(string.IsNullOrWhiteSpace)) + await OnOTPCompleted.InvokeAsync(otpValue); + } + + private async Task OnInput(ChangeEventArgs e, int index) + { + var rawValue = e.Value?.ToString(); + var numericValue = new string(rawValue?.Where(char.IsDigit).ToArray()); + + if (string.IsNullOrEmpty(numericValue)) + { + otpValues[index] = string.Empty; + + // Clear the input element if it contained invalid characters + if (!string.IsNullOrEmpty(rawValue)) + { + await SafeInvokeVoidAsync(JsInteropUtils.SetInputElementValue, GetInputId(index), string.Empty); + } + + await NotifyChangesAsync(); + return; + } + + // If multiple digits were entered (e.g. paste), distribute them across the input fields + if (numericValue.Length > 1) + { + var digits = numericValue.ToCharArray(); + var currentInputLength = digits.Length; + + for (int i = 0; i < currentInputLength; i++) + { + var targetIndex = index + i; + if (targetIndex < Length) + { + otpValues[targetIndex] = digits[i].ToString(); + + // Update the UI value for the current input and subsequent inputs + await SafeInvokeVoidAsync(JsInteropUtils.SetInputElementValue, GetInputId(targetIndex), otpValues[targetIndex]); + } + } + + // Move focus to the next input field after the last pasted digit + var nextIndex = index + currentInputLength; + if (nextIndex < Length) + await SafeInvokeVoidAsync(JsInteropUtils.FocusInputElement, GetInputId(nextIndex)); + else + await SafeInvokeVoidAsync(JsInteropUtils.FocusInputElement, GetInputId(Length - 1)); + + await NotifyChangesAsync(); + return; + } + + var digit = numericValue; + + otpValues[index] = digit; + + // Reset the input value on the client side if it doesn't match the sanitized digit + if (rawValue != digit) + { + await SafeInvokeVoidAsync(JsInteropUtils.SetInputElementValue, GetInputId(index), digit); + } + + // Move focus to the next input field + if (index < Length - 1) + { + await SafeInvokeVoidAsync(JsInteropUtils.FocusInputElement, GetInputId(index + 1)); + } + + await NotifyChangesAsync(); + } + + private async Task OnKeyUp(KeyboardEventArgs e, int index) + { + // Handle backspace key to clear the current input and focus on the previous one + if (e.Key == "Backspace" && index > 0) + { + otpValues[index] = string.Empty; + await SafeInvokeVoidAsync(JsInteropUtils.FocusInputElement, GetInputId(index - 1)); + + // Notify changes + await NotifyChangesAsync(); + } + + // Handle left arrow key to focus on the previous input + if (e.Key == "ArrowLeft" && index > 0) + await SafeInvokeVoidAsync(JsInteropUtils.FocusInputElement, GetInputId(index - 1)); + + // Handle right arrow key to focus on the next input + if (e.Key == "ArrowRight" && index < Length - 1) + await SafeInvokeVoidAsync(JsInteropUtils.FocusInputElement, GetInputId(index + 1)); + } + + #endregion + + #region Properties, Indexers + + protected override string? ClassNames => + BuildClassNames( + Class, + (BootstrapClass.FormControl, true), + (BootstrapClass.TextCenter, true), + (BootstrapClass.MarginEnd2, true) + ); + + protected override string? StyleNames => + BuildClassNames( + Style, + ("width:40px;", true), + ("height:40px;", true) + ); + + private string? ContainerClassNames => + BuildClassNames( + ContainerCssClass, + (BootstrapClass.Flex, true), + (BootstrapClass.FlexRow, true) + ); + + /// + /// Gets or sets the CSS class for the container element. + /// + /// Default value is . + /// + /// + [AddedVersion("4.0.0")] + [DefaultValue(null)] + [Description("Gets or sets CSS classes applied to the element that contains the OTP fields.")] + [Parameter] + public string? ContainerCssClass { get; set; } + + /// + /// Gets or sets the CSS style for the container element. + /// + /// Default value is . + /// + /// + [AddedVersion("4.0.0")] + [DefaultValue(null)] + [Description("Gets or sets inline CSS styles applied to the element that contains the OTP fields.")] + [Parameter] + public string? ContainerCssStyle { get; set; } + + private string? ContainerStyleNames => + BuildClassNames( + ContainerCssStyle + ); + + /// + /// Gets or sets the OTP input length. + /// + /// Default value is 6. + /// + /// + [AddedVersion("4.0.0")] + [DefaultValue(6)] + [Description("Gets or sets the number of digit fields rendered for the one-time password.")] + [Parameter] + public int Length { get; set; } = 6; + + /// + /// This event fires when the OTP input value changes. + /// + [AddedVersion("4.0.0")] + [Description("Fires whenever an OTP digit changes and supplies the current combined value.")] + [Parameter] + public EventCallback OnOTPChanged { get; set; } + + // Disabled + // Divider + + /// + /// This event fires when the OTP input is completed. + /// + [AddedVersion("4.0.0")] + [Description("Fires when every OTP field contains a digit and supplies the completed one-time password.")] + [Parameter] + public EventCallback OnOTPCompleted { get; set; } + + #endregion + + // Size + // Style + // Width +} diff --git a/blazorbootstrap/Components/Form/PasswordInput/PasswordInput.razor b/blazorbootstrap/Components/Form/PasswordInput/PasswordInput.razor new file mode 100644 index 000000000..8980ff17c --- /dev/null +++ b/blazorbootstrap/Components/Form/PasswordInput/PasswordInput.razor @@ -0,0 +1,19 @@ +@namespace BlazorBootstrap +@inherits BlazorBootstrapComponentBase +@preservewhitespace true + +
    + + + +
    diff --git a/blazorbootstrap/Components/Form/PasswordInput/PasswordInput.razor.cs b/blazorbootstrap/Components/Form/PasswordInput/PasswordInput.razor.cs new file mode 100644 index 000000000..94ec5cbbb --- /dev/null +++ b/blazorbootstrap/Components/Form/PasswordInput/PasswordInput.razor.cs @@ -0,0 +1,150 @@ +namespace BlazorBootstrap; + +[AddedVersion("3.3.0")] +public partial class PasswordInput : BlazorBootstrapComponentBase +{ + #region Fields and Constants + + private FieldIdentifier fieldIdentifier; + + private string? oldValue; + + private bool showPassword = false; + + #endregion + + #region Methods + + protected override async Task OnInitializedAsync() + { + oldValue = Value; + + AdditionalAttributes ??= new Dictionary(); + + fieldIdentifier = FieldIdentifier.Create(ValueExpression); + + await base.OnInitializedAsync(); + } + + protected override async Task OnParametersSetAsync() + { + if (oldValue != Value) + { + await ValueChanged.InvokeAsync(Value); + + EditContext?.NotifyFieldChanged(fieldIdentifier); + + oldValue = Value; + } + } + + /// + /// Disables the password input so users cannot change its value. + /// + [AddedVersion("3.3.0")] + [Description("Disables the password input so users cannot change its value.")] + public void Disable() => Disabled = true; + + /// + /// Enables the password input so users can change its value. + /// + [AddedVersion("3.3.0")] + [Description("Enables the password input so users can change its value.")] + public void Enable() => Disabled = false; + + /// + /// This event is triggered only when the user changes the selection from the UI. + /// + /// + private async Task OnChange(ChangeEventArgs args) + { + oldValue = Value; + + Value = args.Value?.ToString() ?? string.Empty; // object + + await ValueChanged.InvokeAsync(Value); + + EditContext?.NotifyFieldChanged(fieldIdentifier); + } + + private void ShowHidePassword() => showPassword = !showPassword; + + #endregion + + #region Properties, Indexers + + protected override string? ClassNames => + BuildClassNames( + Class, + (BootstrapClass.FormControl, true), + (EditContext?.FieldCssClass(fieldIdentifier) ?? string.Empty, true) + ); + + /// + /// Gets or sets whether the password input is disabled. + /// + /// + /// Default value is false. + /// + [AddedVersion("3.3.0")] + [DefaultValue(false)] + [Description("Gets or sets whether the password input is disabled. When true, users cannot change its value.")] + [Parameter] + public bool Disabled { get; set; } + + /// + /// Gets the associated . + /// + [CascadingParameter] + private EditContext EditContext { get; set; } = default!; + + private string InputTextType => showPassword ? "text" : "password"; + + /// + /// Gets or sets the show/hide password button CSS class. + /// + /// + /// Default value is `btn btn-primary btn-sm`. + /// + [AddedVersion("3.3.0")] + [DefaultValue("btn border-top border-end border-bottom border border-start-0")] + [Description("Gets or sets CSS classes applied to the button that reveals or hides the password.")] + [Parameter] + public string? ShowHidePasswordButtonCssClass { get; set; } = "btn border-top border-end border-bottom border border-start-0"; //""btn btn-light border"; + + private string ShowHidePasswordButtonIcon => showPassword ? "bi bi-eye-fill" : "bi bi-eye-slash-fill"; + + /// + /// Gets or sets the value. + /// + /// + /// Default value is null. + /// + [AddedVersion("3.3.0")] + [DefaultValue(null)] + [Description("Gets or sets the current password value bound to the input.")] + [Parameter] + public string? Value { get; set; } + + /// + /// This event is fired when the PasswordInput value changes. + /// + [AddedVersion("3.3.0")] + [Description("Fires whenever user input changes the password value.")] + [Parameter] + public EventCallback ValueChanged { get; set; } + + /// + /// Gets or sets an expression that identifies the bound value. + /// + /// + /// Default value is . + /// + [AddedVersion("3.3.0")] + [DefaultValue(null)] + [Description("Gets or sets the expression that identifies the bound value for validation and EditContext notifications.")] + [Parameter] + public Expression> ValueExpression { get; set; } = default!; + + #endregion +} diff --git a/blazorbootstrap/Components/Form/RadioInput/RadioInput.razor b/blazorbootstrap/Components/Form/RadioInput/RadioInput.razor new file mode 100644 index 000000000..8560d0872 --- /dev/null +++ b/blazorbootstrap/Components/Form/RadioInput/RadioInput.razor @@ -0,0 +1,19 @@ +@namespace BlazorBootstrap +@inherits BlazorBootstrapComponentBase + +
    + + + @if (!string.IsNullOrWhiteSpace(Label)) + { + + } +
    \ No newline at end of file diff --git a/blazorbootstrap/Components/Form/RadioInput/RadioInput.razor.cs b/blazorbootstrap/Components/Form/RadioInput/RadioInput.razor.cs new file mode 100644 index 000000000..467eecd9d --- /dev/null +++ b/blazorbootstrap/Components/Form/RadioInput/RadioInput.razor.cs @@ -0,0 +1,152 @@ +namespace BlazorBootstrap; + +[AddedVersion("3.3.0")] +public partial class RadioInput : BlazorBootstrapComponentBase +{ + #region Fields and Constants + + private FieldIdentifier fieldIdentifier; + + private DotNetObjectReference objRef = default!; + + #endregion + + #region Methods + + protected override async Task OnAfterRenderAsync(bool firstRender) + { + if (firstRender) + { + await SafeInvokeVoidAsync("window.blazorBootstrap.radioInput.initialize", Id, Name, objRef); + } + + await base.OnAfterRenderAsync(firstRender); + } + + protected override void OnInitialized() + { + objRef ??= DotNetObjectReference.Create(this); + + AdditionalAttributes ??= new Dictionary(); + + fieldIdentifier = FieldIdentifier.Create(ValueExpression); + + base.OnInitialized(); + } + + /// + /// Updates the radio input value from the JavaScript change handler. + /// + [AddedVersion("3.3.0")] + [Description("Updates the radio input value from the JavaScript change handler.")] + [JSInvokable] + public async Task OnChangeJS(bool newValue) + { + Value = newValue; + + await ValueChanged.InvokeAsync(Value); + + EditContext?.NotifyFieldChanged(fieldIdentifier); + } + + /// + /// Disables the radio input so users cannot select it. + /// + [AddedVersion("3.3.0")] + [Description("Disables the radio input so users cannot select it.")] + public void Disable() => Disabled = true; + + /// + /// Enables the radio input so users can select it. + /// + [AddedVersion("3.3.0")] + [Description("Enables the radio input so users can select it.")] + public void Enable() => Disabled = false; + + #endregion + + #region Properties, Indexers + + protected override string? ClassNames => + BuildClassNames( + Class, + (BootstrapClass.FormCheckInput, true), + (EditContext?.FieldCssClass(fieldIdentifier) ?? string.Empty, true) + ); + + /// + /// Gets or sets whether the radio input is disabled. + /// + /// + /// Default value is false. + /// + [AddedVersion("3.3.0")] + [DefaultValue(false)] + [Description("Gets or sets whether the radio input is disabled. When true, users cannot select it.")] + [Parameter] + public bool Disabled { get; set; } + + /// + /// Gets the associated . + /// + [CascadingParameter] + private EditContext EditContext { get; set; } = default!; + + /// + /// Gets or sets the label. + /// + /// + /// Default value is . + /// + [AddedVersion("3.3.0")] + [DefaultValue(null)] + [Description("Gets or sets the label displayed next to the radio input.")] + [Parameter] + public string? Label { get; set; } + + /// + /// Gets or sets the name. + /// + /// + /// Default value is . + /// + [AddedVersion("3.3.0")] + [DefaultValue(null)] + [Description("Gets or sets the HTML name used to group related radio inputs.")] + [Parameter] + public string? Name { get; set; } + + /// + /// Gets or sets the value. + /// + /// + /// Default value is . + /// + [AddedVersion("3.3.0")] + [DefaultValue(false)] + [Description("Gets or sets the current value represented by this radio input.")] + [Parameter] + public bool Value { get; set; } = default!; + + /// + /// This event fired on every user keystroke that changes the NumberInput value. + /// + [AddedVersion("3.3.0")] + [Description("Fires whenever user interaction selects this radio input.")] + [Parameter] + public EventCallback ValueChanged { get; set; } + + /// + /// Gets or sets an expression that identifies the bound value. + /// + /// + /// Default value is . + /// + [AddedVersion("3.3.0")] + [DefaultValue(null)] + [Description("Gets or sets the expression that identifies the bound value for validation and EditContext notifications.")] + [Parameter] + public Expression> ValueExpression { get; set; } = default!; + + #endregion +} diff --git a/blazorbootstrap/Components/Form/RangeInput/RangeInput.razor.cs b/blazorbootstrap/Components/Form/RangeInput/RangeInput.razor.cs index f112e4511..717b59fe3 100644 --- a/blazorbootstrap/Components/Form/RangeInput/RangeInput.razor.cs +++ b/blazorbootstrap/Components/Form/RangeInput/RangeInput.razor.cs @@ -8,6 +8,7 @@ /// Supported types for TValue: sbyte, sbyte?, short, short?, int, int?, long, long?, float, float?, double, double?, /// decimal, decimal? /// +[AddedVersion("1.10.6")] public partial class RangeInput : BlazorBootstrapComponentBase { #region Fields and Constants @@ -28,7 +29,7 @@ protected override async Task OnAfterRenderAsync(bool firstRender) { if (firstRender) { - await JSRuntime.InvokeVoidAsync("window.blazorBootstrap.rangeInput.initialize", Id, objRef); + await SafeInvokeVoidAsync("window.blazorBootstrap.rangeInput.initialize", Id, objRef); var currentValue = Value; // object @@ -80,6 +81,11 @@ protected override async Task OnInitializedAsync() await base.OnInitializedAsync(); } + /// + /// Updates the range input value from JavaScript. + /// + [AddedVersion("1.10.6")] + [Description("Updates the range input value from the JavaScript change handler.")] [JSInvokable] public async Task bsOnInput(object? newValue) { @@ -90,11 +96,15 @@ public async Task bsOnInput(object? newValue) /// /// Disables the range input. /// + [AddedVersion("1.10.6")] + [Description("Disables the range input.")] public void Disable() => Disabled = true; /// /// Enables the range input. /// + [AddedVersion("1.10.6")] + [Description("Enables the range input.")] public void Enable() => Disabled = false; private string GetInvariantNumber(TValue value) @@ -377,6 +387,9 @@ private bool TryParseValue(object value, out TValue newValue) /// /// Default value is false. /// + [AddedVersion("1.10.6")] + [DefaultValue(false)] + [Description("Gets or sets whether the range input is disabled. When true, users cannot change its value.")] [Parameter] public bool Disabled { get; set; } @@ -387,12 +400,16 @@ private bool TryParseValue(object value, out TValue newValue) /// /// Gets or sets the maximum value of the range input. /// + [AddedVersion("1.10.6")] + [Description("Gets or sets the maximum value selectable with the range input.")] [Parameter] public TValue Max { get; set; } = default!; /// /// Gets or sets the minimum value of the range input. /// + [AddedVersion("1.10.6")] + [Description("Gets or sets the minimum value selectable with the range input.")] [Parameter] public TValue Min { get; set; } = default!; @@ -404,6 +421,9 @@ private bool TryParseValue(object value, out TValue newValue) /// /// Default value is 1. /// + [AddedVersion("1.10.6")] + [DefaultValue(1)] + [Description("Gets or sets the increment between selectable range values.")] [Parameter] public double Step { get; set; } = 1; @@ -413,22 +433,39 @@ private bool TryParseValue(object value, out TValue newValue) /// /// Default value is null. /// + [AddedVersion("1.10.6")] + [DefaultValue(null)] + [Description("Gets or sets tick marks displayed along the range input.")] [Parameter] public IEnumerable TickMarks { get; set; } = default!; /// /// Gets or sets the value of the range input. /// + [AddedVersion("1.10.6")] + [Description("Gets or sets the current value bound to the range input.")] [Parameter] public TValue Value { get; set; } = default!; /// /// This event fires when the user specifies a numeric value. /// + [AddedVersion("1.10.6")] + [Description("Fires whenever user interaction changes the range value.")] [Parameter] public EventCallback ValueChanged { get; set; } - [Parameter] public Expression> ValueExpression { get; set; } = default!; + /// + /// Gets or sets an expression that identifies the bound value. + /// + /// + /// Default value is . + /// + [AddedVersion("1.10.6")] + [DefaultValue(null)] + [Description("Gets or sets the expression that identifies the bound value for validation and EditContext notifications.")] + [Parameter] + public Expression> ValueExpression { get; set; } = default!; #endregion } diff --git a/blazorbootstrap/Components/Form/RichTextEditor/RichTextEditor.razor b/blazorbootstrap/Components/Form/RichTextEditor/RichTextEditor.razor new file mode 100644 index 000000000..88cf1a59f --- /dev/null +++ b/blazorbootstrap/Components/Form/RichTextEditor/RichTextEditor.razor @@ -0,0 +1,275 @@ +@namespace BlazorBootstrap +@inherits BlazorBootstrapComponentBase + + +
    +
    + @if (ShouldRenderToolbar) + { +
    + @if (Disabled) + { + + + + } + +
    + } + +
    + @((MarkupString)Value) +
    + +
    + + @if (ShowFooter) + { +
    +
    +
    + Paragraph + Inter, 14 px + Left aligned +
    +
    + + +
    +
    +
    + } +
    + + @if (isLinkModalMounted) + { + + } + @if (isImageModalMounted) + { + + } + @if (isTableModalMounted) + { + + } + +
    \ No newline at end of file diff --git a/blazorbootstrap/Components/Form/RichTextEditor/RichTextEditor.razor.cs b/blazorbootstrap/Components/Form/RichTextEditor/RichTextEditor.razor.cs new file mode 100644 index 000000000..aea7935c2 --- /dev/null +++ b/blazorbootstrap/Components/Form/RichTextEditor/RichTextEditor.razor.cs @@ -0,0 +1,607 @@ +namespace BlazorBootstrap; + +/// +/// Provides a dependency-free rich-text editing control with a grouped Bootstrap toolbar. +/// +public partial class RichTextEditor : BlazorBootstrapComponentBase +{ + #region Fields and Constants + + private const string disabledToolbarOverlayStyle = "cursor: not-allowed; z-index: 1;"; + private const string disabledTooltipTitle = "Editing is disabled"; + + private static readonly string[] defaultAllowedImageFileTypes = { "jpg", "jpeg", "png", "gif", "webp" }; + private static readonly HashSet fontFamilies = new(StringComparer.Ordinal) { "Inter", "Arial", "Georgia", "Courier New" }; + private static readonly IReadOnlyDictionary fontSizes = new Dictionary(StringComparer.Ordinal) + { + ["2"] = "12 px", + ["3"] = "14 px", + ["4"] = "16 px", + ["5"] = "18 px", + ["6"] = "24 px" + }; + private static readonly HashSet safeImageFileTypes = new(StringComparer.OrdinalIgnoreCase) { "jpg", "jpeg", "png", "gif", "webp" }; + private FieldIdentifier fieldIdentifier; + private string? imageUploadError; + private bool isImageModalMounted; + private bool isImageUploadInProgress; + private bool isLinkModalMounted; + private bool isTableModalMounted; + private DotNetObjectReference? objRef; + private RichTextEditorToolbarItem? pendingModalItem; + private string? pendingToolbarElementId; + private string selectedFontFamily = "Inter"; + private string selectedFontSize = "14 px"; + private CancellationTokenSource uploadCancellationTokenSource = new(); + + #endregion + + #region Methods + + #region Protected Override Methods + + protected override async ValueTask DisposeAsyncCore(bool disposing) + { + if (disposing) + { + uploadCancellationTokenSource.Cancel(); + uploadCancellationTokenSource.Dispose(); + + if (Id is not null) + await RichTextEditorJsInterop.DisposeAsync(objRef!, Id); + + objRef?.Dispose(); + } + + await base.DisposeAsyncCore(disposing); + } + + protected override async Task OnAfterRenderAsync(bool firstRender) + { + if (firstRender) + { + objRef ??= DotNetObjectReference.Create(this); + await RichTextEditorJsInterop.InitializeAsync(objRef!, Id!, AllowedLinkDomains, AllowedImageDomains); + } + + if (pendingModalItem is RichTextEditorToolbarItem item && pendingToolbarElementId is not null) + { + var toolbarElementId = pendingToolbarElementId; + pendingModalItem = null; + pendingToolbarElementId = null; + + if (IsToolbarItemVisible(item) && IsModalMounted(item)) + await RichTextEditorJsInterop.ExecuteAsync(objRef!, Id!, toolbarElementId, item.ToCommandName()!, string.Empty); + } + + await base.OnAfterRenderAsync(firstRender); + } + + protected override void OnInitialized() + { + AdditionalAttributes ??= new Dictionary(); + + if (ValueExpression is not null) + fieldIdentifier = FieldIdentifier.Create(ValueExpression); + + base.OnInitialized(); + } + + /// + protected override async Task OnParametersSetAsync() + { + if (objRef is not null && Id is not null) + { + await HideModalIfUnavailableAsync(RichTextEditorToolbarItem.Link, "insert-link-modal"); + await HideModalIfUnavailableAsync(RichTextEditorToolbarItem.Image, "insert-image-modal"); + await HideModalIfUnavailableAsync(RichTextEditorToolbarItem.Table, "insert-table-modal"); + } + + await base.OnParametersSetAsync(); + } + + #endregion + + #region Public Methods + + /// + /// Clears the editor content. + /// + [AddedVersion("4.0.0")] + [Description("Clears the editor HTML content through the editor module.")] + public Task ClearAsync() => RichTextEditorJsInterop.ClearAsync(objRef!, Id!); + + /// + /// Focuses the editable area. + /// + [AddedVersion("4.0.0")] + [Description("Moves keyboard focus to the editable area.")] + public Task FocusAsync() => RichTextEditorJsInterop.FocusAsync(objRef!, Id!); + + /// + /// Handles a browser notification after a lazily rendered editor modal has closed. + /// + /// The closed modal identifier. + [AddedVersion("4.0.0")] + [Description("Handles a browser notification after a lazily rendered editor modal has closed.")] + [JSInvokable] + public Task OnEditorModalClosedAsync(string modalName) + { + switch (modalName) + { + case "link": + isLinkModalMounted = false; + break; + case "image": + isImageModalMounted = false; + isImageUploadInProgress = false; + imageUploadError = null; + ResetImageUploadCancellation(); + break; + case "table": + isTableModalMounted = false; + break; + } + + return InvokeAsync(StateHasChanged); + } + + + + /// + /// Raises the transient editor status callback. + /// + [AddedVersion("4.0.0")] + [Description("Raises the transient editor status callback.")] + [JSInvokable] + public Task OnEditorStatusChangedAsync(string status) => StatusChanged.InvokeAsync(status); + + /// + /// Raises the committed editor value callback using the same normalized text and metrics shown in the editor footer. + /// + [AddedVersion("4.0.0")] + [Description("Raises the committed editor value callback with the normalized text and metrics shown in the editor footer.")] + [JSInvokable] + public async Task OnEditorValueChangedAsync(string html, string text, int characterCount, int wordCount) + { + imageUploadError = null; + await ValueChanged.InvokeAsync(new RichTextEditorChange(html, text, characterCount, wordCount)); + + if (ValueExpression is not null) + EditContext?.NotifyFieldChanged(fieldIdentifier); + } + + /// + /// Executes a command requested by a child toolbar button. + /// + /// The invoking toolbar element identifier. + /// The toolbar item to execute. + [AddedVersion("4.0.0")] + [Description("Executes a command requested by a child toolbar button.")] + public async Task OnToolbarButtonClickAsync(string toolbarElementId, RichTextEditorToolbarItem item) + { + if (Disabled) + return; + + if (IsModalToolbarItem(item)) + { + if (!IsToolbarItemVisible(item)) + return; + + MountModal(item); + pendingModalItem = item; + pendingToolbarElementId = toolbarElementId; + await InvokeAsync(StateHasChanged); + return; + } + + await RichTextEditorJsInterop.ExecuteAsync(objRef!, Id!, toolbarElementId, item.ToCommandName()!, string.Empty); + } + + #endregion + + #region Internal Methods + + internal bool IsAnyToolbarItemVisible(params RichTextEditorToolbarItem[] items) => ToolbarItems is null || items.Any(IsToolbarItemVisible); + + internal bool IsToolbarItemVisible(RichTextEditorToolbarItem item) => ToolbarItems is null || ToolbarItems.Contains(item); + + #endregion + + #region Private Methods + + private static bool HasExpectedImageContentType(string? contentType, string extension) => + extension switch + { + "jpg" or "jpeg" => string.Equals(contentType, "image/jpeg", StringComparison.OrdinalIgnoreCase), + "png" => string.Equals(contentType, "image/png", StringComparison.OrdinalIgnoreCase), + "gif" => string.Equals(contentType, "image/gif", StringComparison.OrdinalIgnoreCase), + "webp" => string.Equals(contentType, "image/webp", StringComparison.OrdinalIgnoreCase), + _ => false + }; + + private static async Task HasExpectedImageSignatureAsync(IBrowserFile file, string extension, CancellationToken cancellationToken) + { + var header = new byte[12]; + await using var stream = file.OpenReadStream(file.Size, cancellationToken); + var bytesRead = await stream.ReadAsync(header.AsMemory(), cancellationToken); + + return extension switch + { + "jpg" or "jpeg" => bytesRead >= 3 && header[0] == 0xFF && header[1] == 0xD8 && header[2] == 0xFF, + "png" => bytesRead >= 8 && header[0] == 0x89 && header[1] == 0x50 && header[2] == 0x4E && header[3] == 0x47 && header[4] == 0x0D && header[5] == 0x0A && header[6] == 0x1A && header[7] == 0x0A, + "gif" => bytesRead >= 6 && header[0] == 0x47 && header[1] == 0x49 && header[2] == 0x46 && header[3] == 0x38 && (header[4] == 0x37 || header[4] == 0x39) && header[5] == 0x61, + "webp" => bytesRead >= 12 && header[0] == 0x52 && header[1] == 0x49 && header[2] == 0x46 && header[3] == 0x46 && header[8] == 0x57 && header[9] == 0x45 && header[10] == 0x42 && header[11] == 0x50, + _ => false + }; + } + + /// + /// Closes a mounted modal when its associated toolbar item is no longer available. + /// + /// The toolbar item associated with the modal. + /// The editor-scoped modal identifier. + private async Task HideModalIfUnavailableAsync(RichTextEditorToolbarItem item, string modalId) + { + if (IsToolbarItemVisible(item) || !IsModalMounted(item)) + return; + + await RichTextEditorJsInterop.HideModalAsync(Id!, modalId); + } + + private bool IsAllowedHttpsImageUrl(string value) + { + if (!Uri.TryCreate(value, UriKind.Absolute, out var uri) + || uri.Scheme != Uri.UriSchemeHttps + || !string.IsNullOrEmpty(uri.UserInfo) + || string.IsNullOrWhiteSpace(uri.Host)) + return false; + + var configuredDomains = AllowedImageDomains?.Where(domain => !string.IsNullOrWhiteSpace(domain)).ToArray() ?? Array.Empty(); + if (configuredDomains.Length == 0) + return true; + + var host = uri.Host.TrimEnd('.'); + return configuredDomains + .Select(NormalizeDomain) + .Where(domain => domain is not null) + .Any(domain => host.Equals(domain, StringComparison.OrdinalIgnoreCase) || host.EndsWith($".{domain}", StringComparison.OrdinalIgnoreCase)); + } + + /// + /// Determines whether the modal associated with a toolbar item is currently rendered. + /// + /// The toolbar item to evaluate. + /// when the associated modal is mounted; otherwise, . + private bool IsModalMounted(RichTextEditorToolbarItem item) => item switch + { + RichTextEditorToolbarItem.Link => isLinkModalMounted, + RichTextEditorToolbarItem.Image => isImageModalMounted, + RichTextEditorToolbarItem.Table => isTableModalMounted, + _ => false + }; + + /// + /// Determines whether a toolbar item opens a lazily rendered modal. + /// + /// The toolbar item to evaluate. + /// when the item opens a modal; otherwise, . + private static bool IsModalToolbarItem(RichTextEditorToolbarItem item) => item is RichTextEditorToolbarItem.Link or RichTextEditorToolbarItem.Image or RichTextEditorToolbarItem.Table; + + /// + /// Marks the modal associated with a toolbar item for rendering. + /// + /// The toolbar item whose modal should be mounted. + private void MountModal(RichTextEditorToolbarItem item) + { + switch (item) + { + case RichTextEditorToolbarItem.Link: + isLinkModalMounted = true; + break; + case RichTextEditorToolbarItem.Image: + isImageModalMounted = true; + break; + case RichTextEditorToolbarItem.Table: + isTableModalMounted = true; + break; + } + } + + private static string? NormalizeDomain(string domain) + { + var candidate = domain.Trim().TrimEnd('.'); + if (candidate.StartsWith("*.", StringComparison.Ordinal)) + candidate = candidate[2..]; + if (Uri.TryCreate(candidate, UriKind.Absolute, out var uri)) + candidate = uri.Host; + return Uri.CheckHostName(candidate) is UriHostNameType.Dns or UriHostNameType.IPv4 or UriHostNameType.IPv6 ? candidate : null; + } + + private async Task OnFontFamilyClickAsync(string fontFamily) + { + if (Disabled || !fontFamilies.Contains(fontFamily)) + return; + + selectedFontFamily = fontFamily; + await RichTextEditorJsInterop.ExecuteAsync(objRef!, Id!, FontFamilyButtonId, RichTextEditorToolbarItem.FontFamily.ToCommandName()!, fontFamily); + } + + private async Task OnFontSizeClickAsync(string fontSize) + { + if (Disabled || !fontSizes.TryGetValue(fontSize, out var fontSizeLabel)) + return; + + selectedFontSize = fontSizeLabel; + await RichTextEditorJsInterop.ExecuteAsync(objRef!, Id!, FontSizeButtonId, RichTextEditorToolbarItem.FontSize.ToCommandName()!, fontSize); + } + + private async Task OnImageFileChangedAsync(InputFileChangeEventArgs e) + { + imageUploadError = null; + var cancellationToken = ResetImageUploadCancellation(); + await SetImageUploadInProgressAsync(true); + + try + { + var file = e.File; + + if (ImageUploadHandler is null) + { + await SetImageUploadErrorAsync("An image upload handler is not configured."); + return; + } + + if (MaxImageFileSize <= 0) + { + await SetImageUploadErrorAsync("The maximum image size must be greater than zero."); + return; + } + + var extension = Path.GetExtension(file.Name).TrimStart('.').ToLowerInvariant(); + if (!NormalizedAllowedImageFileTypes.Contains(extension)) + { + await SetImageUploadErrorAsync("The selected image type is not allowed."); + return; + } + + if (file.Size == 0 || file.Size > MaxImageFileSize) + { + await SetImageUploadErrorAsync("The selected image exceeds the maximum allowed size."); + return; + } + + if (!HasExpectedImageContentType(file.ContentType, extension)) + { + await SetImageUploadErrorAsync("The selected file does not have the expected image content type."); + return; + } + + if (!await HasExpectedImageSignatureAsync(file, extension, cancellationToken)) + { + await SetImageUploadErrorAsync("The selected file content does not match its image type."); + return; + } + + var request = new RichTextEditorImageUploadRequest(file, string.Empty, cancellationToken); + var result = await ImageUploadHandler.Invoke(request); + + if (cancellationToken.IsCancellationRequested || !isImageModalMounted) + return; + + if (result is null || !IsAllowedHttpsImageUrl(result.Url)) + { + await SetImageUploadErrorAsync("The upload did not return a permitted HTTPS image URL."); + return; + } + + if (cancellationToken.IsCancellationRequested || !isImageModalMounted) + return; + + if (!await RichTextEditorJsInterop.PrepareUploadedImageAsync(Id!, result.Url)) + { + await SetImageUploadErrorAsync("The uploaded image could not be loaded."); + return; + } + + if (!cancellationToken.IsCancellationRequested && isImageModalMounted) + await OnEditorStatusChangedAsync("Image uploaded. Review its accessibility options, then insert it."); + } + catch (OperationCanceledException) + { + // A newer upload or disposal cancelled this request. + } + catch (Exception) + { + await SetImageUploadErrorAsync("The image could not be uploaded."); + } + finally + { + if (!cancellationToken.IsCancellationRequested && isImageModalMounted) + await SetImageUploadInProgressAsync(false); + } + } + /// + /// Cancels the current image upload and creates a token for the next upload. + /// + /// A cancellation token for the next image upload. + private CancellationToken ResetImageUploadCancellation() + { + uploadCancellationTokenSource.Cancel(); + uploadCancellationTokenSource.Dispose(); + uploadCancellationTokenSource = new CancellationTokenSource(); + return uploadCancellationTokenSource.Token; + } + + private async Task SetImageUploadErrorAsync(string message) + { + imageUploadError = message; + await RichTextEditorJsInterop.ShowImageUploadErrorAsync(Id!, message); + await OnEditorStatusChangedAsync(message); + } + + private Task SetImageUploadInProgressAsync(bool value) + { + isImageUploadInProgress = value; + return InvokeAsync(StateHasChanged); + } + + #endregion + + #endregion + + #region Properties, Indexers + + private string Accept => string.Join(',', NormalizedAllowedImageFileTypes.Select(fileType => $".{fileType}")); + + /// Gets or sets the permitted HTTPS image domains. Subdomains are also permitted. + /// + /// Default value is . + /// + [AddedVersion("4.0.0")] + [DefaultValue(null)] + [Description("Gets or sets the HTTPS domains permitted for uploaded-image URLs. Subdomains of configured domains are also permitted.")] + [Parameter] + public IEnumerable? AllowedImageDomains { get; set; } + + /// Gets or sets the permitted image file extensions. + /// + /// Default value is . + /// + [AddedVersion("4.0.0")] + [DefaultValue(null)] + [Description("Gets or sets image file extensions accepted by the upload dialog. Null uses the built-in safe image types.")] + [Parameter] + public IEnumerable? AllowedImageFileTypes { get; set; } + + /// Gets or sets the permitted HTTP(S) link domains. Subdomains are also permitted. + /// + /// Default value is . + /// + [AddedVersion("4.0.0")] + [DefaultValue(null)] + [Description("Gets or sets the HTTP(S) domains permitted for inserted links. Subdomains of configured domains are also permitted.")] + [Parameter] + public IEnumerable? AllowedLinkDomains { get; set; } + + /// Gets or sets the accessible label for the editor. + [AddedVersion("4.0.0")] + [DefaultValue("Rich text editor")] + [Description("Gets or sets the accessible name announced for the editor by assistive technologies.")] + [Parameter] + public string AriaLabel { get; set; } = "Rich text editor"; + + /// Gets or sets the delay, in milliseconds, before editor changes are raised. + [AddedVersion("4.0.0")] + [DefaultValue(300)] + [Description("Gets or sets the debounce delay, in milliseconds, before editor content changes are raised to ValueChanged.")] + [Parameter] + public int DebounceInterval { get; set; } = 300; + + /// Gets or sets whether the editor is disabled. + [AddedVersion("4.0.0")] + [DefaultValue(false)] + [Description("Gets or sets whether editing is disabled. When true, users cannot change content or invoke toolbar commands.")] + [Parameter] + public bool Disabled { get; set; } + + [CascadingParameter] + private EditContext? EditContext { get; set; } + + private string EditorId => $"{Id}-editor"; + + private string FontFamilyButtonId => $"{Id}-font-family"; + + private string FontSizeButtonId => $"{Id}-font-size"; + + private string ImageInputId => $"{Id}-image-upload-file"; + + /// Gets or sets the image upload handler. + [AddedVersion("4.0.0")] + [DefaultValue(null)] + [Description("Gets or sets the delegate that uploads a validated image and returns its HTTPS URL for insertion.")] + [Parameter] + public RichTextEditorImageUploadDelegate? ImageUploadHandler { get; set; } + + private string InsertTableButtonId => $"{Id}-insert-table"; + + /// Gets or sets the maximum allowed image size in bytes. + [AddedVersion("4.0.0")] + [DefaultValue(5242880)] + [Description("Gets or sets the maximum accepted image-upload size in bytes. Larger files are rejected before upload.")] + [Parameter] + public long MaxImageFileSize { get; set; } = 5 * 1024 * 1024; + + /// Gets or sets the maximum plain-text character count. + [AddedVersion("4.0.0")] + [DefaultValue(null)] + [Description("Gets or sets the maximum plain-text character count. Null does not impose a character limit.")] + [Parameter] + public int? MaxLength { get; set; } + + private HashSet NormalizedAllowedImageFileTypes => + (AllowedImageFileTypes ?? defaultAllowedImageFileTypes) + .Select(fileType => fileType.Trim().TrimStart('.').ToLowerInvariant()) + .Where(fileType => safeImageFileTypes.Contains(fileType)) + .ToHashSet(StringComparer.OrdinalIgnoreCase); + + /// Gets or sets the placeholder text. + [AddedVersion("4.0.0")] + [DefaultValue(null)] + [Description("Gets or sets placeholder text displayed when the editor has no content.")] + [Parameter] + public string? Placeholder { get; set; } + + [Inject] + private RichTextEditorJsInterop RichTextEditorJsInterop { get; set; } = default!; + + /// Gets or sets whether the editor footer is displayed. + [AddedVersion("4.0.0")] + [DefaultValue(true)] + [Description("Gets or sets whether the footer displaying editor metrics is rendered.")] + [Parameter] + public bool ShowFooter { get; set; } = true; + + private bool ShouldRenderToolbar => ToolbarItems is null || ToolbarItems.Length > 0; + + + /// Fires for transient editor activity and error status. + [AddedVersion("4.0.0")] + [Description("Fires for transient editor activity and error status, such as image-upload progress or validation failures.")] + [Parameter] + public EventCallback StatusChanged { get; set; } + + /// + /// Gets or sets the toolbar items. + /// + [AddedVersion("4.0.0")] + [DefaultValue(null)] + [Description("Gets or sets the toolbar commands available to users. Null displays the complete built-in toolbar.")] + [Parameter] + public RichTextEditorToolbarItem[]? ToolbarItems { get; set; } + + /// Gets or sets the HTML value. + [AddedVersion("4.0.0")] + [DefaultValue(null)] + [Description("Gets or sets the editor HTML content bound to the component.")] + [Parameter] + public string Value { get; set; } = string.Empty; + + /// Fires after the editor commits a content change. + [AddedVersion("4.0.0")] + [Description("Fires after debounced editor content changes and supplies HTML, normalized text, and character metrics.")] + [Parameter] + public EventCallback ValueChanged { get; set; } + + /// Gets or sets the expression that identifies the bound value. + /// + /// Default value is . + /// + [AddedVersion("4.0.0")] + [DefaultValue(null)] + [Description("Gets or sets the expression that identifies the bound value for validation and EditContext notifications.")] + [Parameter] + public Expression>? ValueExpression { get; set; } + + #endregion +} diff --git a/blazorbootstrap/Components/Form/RichTextEditor/RichTextEditorJsInterop.cs b/blazorbootstrap/Components/Form/RichTextEditor/RichTextEditorJsInterop.cs new file mode 100644 index 000000000..8d0ea1f67 --- /dev/null +++ b/blazorbootstrap/Components/Form/RichTextEditor/RichTextEditorJsInterop.cs @@ -0,0 +1,102 @@ +namespace BlazorBootstrap; + +internal sealed class RichTextEditorJsInterop : JsInteropBase +{ + #region Fields and Constants + + public const string Clear = "clear"; + public const string Dispose = "dispose"; + public const string Execute = "execute"; + public const string Focus = "focus"; + public const string HideModal = "hideModal"; + public const string Initialize = "initialize"; + public const string PrepareUploadedImage = "prepareUploadedImage"; + public const string ShowImageUploadError = "showImageUploadError"; + + #endregion + + #region Constructors and Finalizers + + public RichTextEditorJsInterop(IJSRuntime jsRuntime) + : base(jsRuntime, "./_content/Blazor.Bootstrap/blazor.bootstrap.rich-text-editor.js") + { + } + + #endregion + + #region Methods + + #region Public Methods + + /// Clears the editor content through the rich-text editor JavaScript module. + [AddedVersion("4.0.0")] + [Description("Clears the editor content through the rich-text editor JavaScript module.")] + public async Task ClearAsync(object objRef, string editorId) + { + await SafeInvokeVoidAsync(Execute, objRef, editorId, null, "clear", null); + } + + /// Disposes the editor instance through the rich-text editor JavaScript module. + [AddedVersion("4.0.0")] + [Description("Disposes the editor instance through the rich-text editor JavaScript module.")] + public async Task DisposeAsync(object objRef, string editorId) + { + await SafeInvokeVoidAsync(Dispose, objRef, editorId); + } + + /// Executes an editor command through the rich-text editor JavaScript module. + [AddedVersion("4.0.0")] + [Description("Executes an editor command through the rich-text editor JavaScript module.")] + public async Task ExecuteAsync(object objRef, string editorId, string elementId, string command, string value) + { + await SafeInvokeVoidAsync(Execute, objRef, editorId, elementId, command, value); + } + + /// Focuses the editor through the rich-text editor JavaScript module. + [AddedVersion("4.0.0")] + [Description("Focuses the editor through the rich-text editor JavaScript module.")] + public async Task FocusAsync(object objRef, string editorId) + { + await SafeInvokeVoidAsync(Focus, objRef, editorId); + } + + /// + /// Hides a rendered editor modal so its close handler can dispose and unmount it. + /// + /// The editor identifier. + /// The editor-scoped modal identifier. + [AddedVersion("4.0.0")] + [Description("Hides a rendered editor modal so its close handler can dispose and unmount it.")] + public async Task HideModalAsync(string editorId, string modalId) + { + await SafeInvokeVoidAsync(HideModal, editorId, modalId); + } + + /// Initializes the editor through the rich-text editor JavaScript module. + [AddedVersion("4.0.0")] + [Description("Initializes the editor through the rich-text editor JavaScript module.")] + public async Task InitializeAsync(object objRef, string editorId, IEnumerable? allowedLinkDomains, IEnumerable? allowedImageDomains) + { + await SafeInvokeVoidAsync(Initialize, objRef, editorId, allowedLinkDomains, allowedImageDomains); + } + + /// Prepares an uploaded image for insertion through the rich-text editor JavaScript module. + [AddedVersion("4.0.0")] + [Description("Prepares an uploaded image for insertion through the rich-text editor JavaScript module.")] + public async Task PrepareUploadedImageAsync(string editorId, string imageUrl) + { + return await SafeInvokeAsync(PrepareUploadedImage, editorId, imageUrl); + } + + /// Shows an image-upload error through the rich-text editor JavaScript module. + [AddedVersion("4.0.0")] + [Description("Shows an image-upload error through the rich-text editor JavaScript module.")] + public async Task ShowImageUploadErrorAsync(string editorId, string message) + { + await SafeInvokeVoidAsync(ShowImageUploadError, editorId, message); + } + + #endregion + + #endregion +} diff --git a/blazorbootstrap/Components/Form/RichTextEditor/RichTextEditorToolbarButton.razor b/blazorbootstrap/Components/Form/RichTextEditor/RichTextEditorToolbarButton.razor new file mode 100644 index 000000000..1e26e2356 --- /dev/null +++ b/blazorbootstrap/Components/Form/RichTextEditor/RichTextEditorToolbarButton.razor @@ -0,0 +1,9 @@ +@namespace BlazorBootstrap +@inherits BlazorBootstrapComponentBase + +@if (Parent?.IsToolbarItemVisible(Item) ?? true) +{ + +} \ No newline at end of file diff --git a/blazorbootstrap/Components/Form/RichTextEditor/RichTextEditorToolbarButton.razor.cs b/blazorbootstrap/Components/Form/RichTextEditor/RichTextEditorToolbarButton.razor.cs new file mode 100644 index 000000000..300b7033f --- /dev/null +++ b/blazorbootstrap/Components/Form/RichTextEditor/RichTextEditorToolbarButton.razor.cs @@ -0,0 +1,51 @@ +namespace BlazorBootstrap; + +public partial class RichTextEditorToolbarButton : BlazorBootstrapComponentBase +{ + #region Methods + + private async Task OnClickAsync() + { + if (Disabled) + return; + + await Parent?.OnToolbarButtonClickAsync(Id!, Item)!; + } + + #endregion + + #region Properties, Indexers + + private IconName iconName => Item.ToIconName(); + + private string? label => Item.ToIconLabel(); + + /// + /// Gets or sets a value indicating whether the button is disabled. + /// + /// Default is false. + /// + /// + [AddedVersion("4.0.0")] + [DefaultValue(false)] + [Description("Gets or sets whether the toolbar button is disabled. When true, its command cannot be invoked.")] + [Parameter] + public bool Disabled { get; set; } + + /// + /// Gets or sets the toolbar item associated with the button. + /// + /// Default is . + /// + /// + [AddedVersion("4.0.0")] + [DefaultValue(RichTextEditorToolbarItem.None)] + [Description("Gets or sets the toolbar command represented by this button.")] + [EditorRequired, Parameter] + public RichTextEditorToolbarItem Item { get; set; } = RichTextEditorToolbarItem.None; + + [CascadingParameter(Name = "RichTextEditor")] + private RichTextEditor? Parent { get; set; } + + #endregion +} diff --git a/blazorbootstrap/Components/Form/SelectInput/SelectInput.razor b/blazorbootstrap/Components/Form/SelectInput/SelectInput.razor new file mode 100644 index 000000000..9e3df9654 --- /dev/null +++ b/blazorbootstrap/Components/Form/SelectInput/SelectInput.razor @@ -0,0 +1,15 @@ +@* @namespace BlazorBootstrap +@inherits BlazorBootstrapComponentBase + + *@ \ No newline at end of file diff --git a/blazorbootstrap/Components/Form/SelectInput/SelectInput.razor.cs b/blazorbootstrap/Components/Form/SelectInput/SelectInput.razor.cs new file mode 100644 index 000000000..c22fc7617 --- /dev/null +++ b/blazorbootstrap/Components/Form/SelectInput/SelectInput.razor.cs @@ -0,0 +1,116 @@ +//namespace BlazorBootstrap; + +//public partial class SelectInput : BlazorBootstrapComponentBase +//{ +// #region Fields and Constants + +// private FieldIdentifier fieldIdentifier; + +// #endregion + +// #region Methods + +// protected override void OnInitialized() +// { +// AdditionalAttributes ??= new Dictionary(); + +// fieldIdentifier = FieldIdentifier.Create(ValueExpression); + +// base.OnInitialized(); +// } + +// /// +// /// Disables number input. +// /// +// public void Disable() => Disabled = true; + +// /// +// /// Enables number input. +// /// +// public void Enable() => Disabled = false; + +// private async Task OnChange(ChangeEventArgs e) +// { +// var oldValue = Value; +// var newValue = e.Value?.ToString() ?? string.Empty; // object + +// await ValueChanged.InvokeAsync(newValue); + +// EditContext?.NotifyFieldChanged(fieldIdentifier); +// } + +// #endregion + +// #region Properties, Indexers + +// protected override string? ClassNames => +// BuildClassNames( +// Class, +// (BootstrapClass.FormControl, true), +// (TextAlignment.ToTextAlignmentClass(), TextAlignment != Alignment.None) +// ); + +// private string autoComplete => AutoComplete ? "true" : "false"; + +// /// +// /// If , NumberInput can complete the values automatically by the browser. +// /// +// /// +// /// Default value is false. +// /// +// [Parameter] +// public bool AutoComplete { get; set; } + +// /// +// /// Gets or sets the disabled state. +// /// +// /// +// /// Default value is false. +// /// +// [Parameter] +// public bool Disabled { get; set; } + +// [CascadingParameter] private EditContext EditContext { get; set; } = default!; + +// private string fieldCssClasses => EditContext?.FieldCssClass(fieldIdentifier) ?? ""; + +// /// +// /// Gets or sets the maximum length of the input. +// /// +// [Parameter] +// public int? MaxLength { get; set; } + +// /// +// /// Gets or sets the placeholder. +// /// +// /// +// /// Default value is null. +// /// +// [Parameter] +// public string? Placeholder { get; set; } + +// /// +// /// Gets or sets the text alignment. +// /// +// /// +// /// Default value is . +// /// +// [Parameter] +// public Alignment TextAlignment { get; set; } = Alignment.None; + +// /// +// /// Gets or sets the value. +// /// +// [Parameter] +// public string Value { get; set; } = default!; + +// /// +// /// This event fired on every user keystroke that changes the NumberInput value. +// /// +// [Parameter] +// public EventCallback ValueChanged { get; set; } + +// [Parameter] public Expression> ValueExpression { get; set; } = default!; + +// #endregion +//} diff --git a/blazorbootstrap/Components/Form/Switch/Switch.razor.cs b/blazorbootstrap/Components/Form/Switch/Switch.razor.cs index 38483c0bf..4038bd230 100644 --- a/blazorbootstrap/Components/Form/Switch/Switch.razor.cs +++ b/blazorbootstrap/Components/Form/Switch/Switch.razor.cs @@ -1,5 +1,6 @@ namespace BlazorBootstrap; +[AddedVersion("1.3.0")] public partial class Switch : BlazorBootstrapComponentBase { #region Fields and Constants @@ -36,13 +37,17 @@ protected override async Task OnParametersSetAsync() } /// - /// Disables switch. + /// Disables the switch so users cannot change its value. /// + [AddedVersion("1.3.0")] + [Description("Disables the switch so users cannot change its value.")] public void Disable() => Disabled = true; /// - /// Enables switch. + /// Enables the switch so users can change its value. /// + [AddedVersion("1.3.0")] + [Description("Enables the switch so users can change its value.")] public void Enable() => Disabled = false; /// @@ -72,11 +77,14 @@ private async Task OnChange(ChangeEventArgs args) (BootstrapClass.FormCheckReverse, Reverse)); /// - /// Gets or sets the disabled state. + /// Gets or sets whether the switch is disabled. /// /// /// Default value is false. /// + [AddedVersion("1.3.0")] + [DefaultValue(false)] + [Description("Gets or sets whether the switch is disabled. When true, users cannot change its value.")] [Parameter] public bool Disabled { get; set; } @@ -90,6 +98,9 @@ private async Task OnChange(ChangeEventArgs args) /// /// Default value is null. /// + [AddedVersion("1.3.0")] + [DefaultValue(null)] + [Description("Gets or sets the label displayed next to the switch.")] [Parameter] public string Label { get; set; } = default!; @@ -101,6 +112,9 @@ private async Task OnChange(ChangeEventArgs args) /// /// Default value is false. /// + [AddedVersion("1.3.0")] + [DefaultValue(false)] + [Description("Gets or sets whether the switch is displayed on the opposite side of its label.")] [Parameter] public bool Reverse { get; set; } @@ -110,16 +124,31 @@ private async Task OnChange(ChangeEventArgs args) /// /// Default value is false. /// + [AddedVersion("1.3.0")] + [DefaultValue(false)] + [Description("Gets or sets the current checked value bound to the switch.")] [Parameter] public bool Value { get; set; } /// /// This event is fired when the switch selection changes. /// + [AddedVersion("1.3.0")] + [Description("Fires whenever user interaction changes the switch value.")] [Parameter] public EventCallback ValueChanged { get; set; } = default!; - [Parameter] public Expression> ValueExpression { get; set; } = default!; + /// + /// Gets or sets an expression that identifies the bound value. + /// + /// + /// Default value is . + /// + [AddedVersion("1.3.0")] + [DefaultValue(null)] + [Description("Gets or sets the expression that identifies the bound value for validation and EditContext notifications.")] + [Parameter] + public Expression> ValueExpression { get; set; } = default!; #endregion } diff --git a/blazorbootstrap/Components/Form/TextAreaInput/TextAreaInput.razor b/blazorbootstrap/Components/Form/TextAreaInput/TextAreaInput.razor new file mode 100644 index 000000000..3a3cff244 --- /dev/null +++ b/blazorbootstrap/Components/Form/TextAreaInput/TextAreaInput.razor @@ -0,0 +1,17 @@ +@namespace BlazorBootstrap +@inherits BlazorBootstrapComponentBase + + \ No newline at end of file diff --git a/blazorbootstrap/Components/Form/TextAreaInput/TextAreaInput.razor.cs b/blazorbootstrap/Components/Form/TextAreaInput/TextAreaInput.razor.cs new file mode 100644 index 000000000..a65a001f2 --- /dev/null +++ b/blazorbootstrap/Components/Form/TextAreaInput/TextAreaInput.razor.cs @@ -0,0 +1,181 @@ +namespace BlazorBootstrap; + +[AddedVersion("3.3.0")] +public partial class TextAreaInput : BlazorBootstrapComponentBase +{ + #region Fields and Constants + + private FieldIdentifier fieldIdentifier; + + #endregion + + #region Methods + + protected override void OnInitialized() + { + AdditionalAttributes ??= new Dictionary(); + + fieldIdentifier = FieldIdentifier.Create(ValueExpression); + + base.OnInitialized(); + } + + /// + /// Disables the text area so users cannot change its value. + /// + [AddedVersion("3.3.0")] + [Description("Disables the text area so users cannot change its value.")] + public void Disable() => Disabled = true; + + /// + /// Enables the text area so users can change its value. + /// + [AddedVersion("3.3.0")] + [Description("Enables the text area so users can change its value.")] + public void Enable() => Disabled = false; + + private async Task OnChange(ChangeEventArgs e) + { + var oldValue = Value; + var newValue = e.Value?.ToString() ?? string.Empty; // object + + await ValueChanged.InvokeAsync(newValue); + + EditContext?.NotifyFieldChanged(fieldIdentifier); + } + + #endregion + + #region Properties, Indexers + + protected override string? ClassNames => + BuildClassNames( + Class, + (BootstrapClass.FormControl, true), + (TextAlignment.ToTextAlignmentClass(), TextAlignment != Alignment.None) + ); + + private string autoComplete => AutoComplete ? "true" : "false"; + + /// + /// Gets or sets whether browser autocomplete is enabled for the text area. + /// + /// + /// Default value is false. + /// + [AddedVersion("3.3.0")] + [DefaultValue(false)] + [Description("Gets or sets whether browser autocomplete is enabled. When true, the browser may offer saved values for the text area.")] + [Parameter] + public bool AutoComplete { get; set; } + + /// + /// Gets or sets the visible width of the text area in columns. + /// + /// + /// Default value is . + /// + [AddedVersion("3.3.0")] + [DefaultValue(null)] + [Description("Gets or sets the visible width of the text area in columns.")] + [Parameter] + public int? Cols { get; set; } + + /// + /// Gets or sets whether the text area is disabled. + /// + /// + /// Default value is false. + /// + [AddedVersion("3.3.0")] + [DefaultValue(false)] + [Description("Gets or sets whether the text area is disabled. When true, users cannot change its value.")] + [Parameter] + public bool Disabled { get; set; } + + [CascadingParameter] private EditContext EditContext { get; set; } = default!; + + private string fieldCssClasses => EditContext?.FieldCssClass(fieldIdentifier) ?? ""; + + /// + /// Gets or sets the maximum number of characters users can enter. + /// + /// + /// Default value is . + /// + [AddedVersion("3.3.0")] + [DefaultValue(null)] + [Description("Gets or sets the maximum number of characters users can enter. Additional input is prevented when the limit is reached.")] + [Parameter] + public int? MaxLength { get; set; } + + /// + /// Gets or sets placeholder text displayed when the text area has no value. + /// + /// + /// Default value is null. + /// + [AddedVersion("3.3.0")] + [DefaultValue(null)] + [Description("Gets or sets placeholder text displayed when the text area has no value.")] + [Parameter] + public string? Placeholder { get; set; } + + /// + /// Gets or sets the visible height of the text area in rows. + /// + /// + /// Default value is . + /// + [AddedVersion("3.3.0")] + [DefaultValue(null)] + [Description("Gets or sets the visible height of the text area in rows.")] + [Parameter] + public int? Rows { get; set; } + + /// + /// Gets or sets the horizontal alignment of the text area value. + /// + /// + /// Default value is . + /// + [AddedVersion("3.3.0")] + [DefaultValue(Alignment.None)] + [Description("Gets or sets the horizontal alignment of the text area value.")] + [Parameter] + public Alignment TextAlignment { get; set; } = Alignment.None; + + /// + /// Gets or sets the current text value bound to the text area. + /// + /// + /// Default value is . + /// + [AddedVersion("3.3.0")] + [DefaultValue(null)] + [Description("Gets or sets the current text value bound to the text area.")] + [Parameter] + public string Value { get; set; } = default!; + + /// + /// This event fires when the value changes. + /// + [AddedVersion("3.3.0")] + [Description("Fires whenever user input changes the text area value.")] + [Parameter] + public EventCallback ValueChanged { get; set; } + + /// + /// Gets or sets the expression that identifies the bound value for validation and EditContext notifications. + /// + /// + /// Default value is . + /// + [AddedVersion("3.3.0")] + [DefaultValue(null)] + [Description("Gets or sets the expression that identifies the bound value for validation and EditContext notifications.")] + [Parameter] + public Expression> ValueExpression { get; set; } = default!; + + #endregion +} diff --git a/blazorbootstrap/Components/Form/TextInput/TextInput.razor b/blazorbootstrap/Components/Form/TextInput/TextInput.razor new file mode 100644 index 000000000..795fbbbc6 --- /dev/null +++ b/blazorbootstrap/Components/Form/TextInput/TextInput.razor @@ -0,0 +1,15 @@ +@namespace BlazorBootstrap +@inherits BlazorBootstrapComponentBase + + \ No newline at end of file diff --git a/blazorbootstrap/Components/Form/TextInput/TextInput.razor.cs b/blazorbootstrap/Components/Form/TextInput/TextInput.razor.cs new file mode 100644 index 000000000..450bc8d5c --- /dev/null +++ b/blazorbootstrap/Components/Form/TextInput/TextInput.razor.cs @@ -0,0 +1,157 @@ +namespace BlazorBootstrap; + +[AddedVersion("3.3.0")] +public partial class TextInput : BlazorBootstrapComponentBase +{ + #region Fields and Constants + + private FieldIdentifier fieldIdentifier = default!; + + #endregion + + #region Methods + + protected override void OnInitialized() + { + AdditionalAttributes ??= new Dictionary(); + + fieldIdentifier = FieldIdentifier.Create(ValueExpression); + + base.OnInitialized(); + } + + /// + /// Disables the text input so users cannot change its value. + /// + [AddedVersion("3.3.0")] + [Description("Disables the text input so users cannot change its value.")] + public void Disable() => Disabled = true; + + /// + /// Enables the text input so users can change its value. + /// + [AddedVersion("3.3.0")] + [Description("Enables the text input so users can change its value.")] + public void Enable() => Disabled = false; + + private async Task OnChange(ChangeEventArgs e) + { + var oldValue = Value; + var newValue = e.Value?.ToString() ?? string.Empty; // object + + await ValueChanged.InvokeAsync(newValue); + + EditContext?.NotifyFieldChanged(fieldIdentifier); + } + + #endregion + + #region Properties, Indexers + + protected override string? ClassNames => + BuildClassNames( + Class, + (BootstrapClass.FormControl, true), + (TextAlignment.ToTextAlignmentClass(), TextAlignment != Alignment.None) + ); + + private string autoComplete => AutoComplete ? "true" : "false"; + + /// + /// Gets or sets whether browser autocomplete is enabled for the text input. + /// + /// + /// Default value is false. + /// + [AddedVersion("3.3.0")] + [DefaultValue(false)] + [Description("Gets or sets whether browser autocomplete is enabled. When true, the browser may offer saved values for the input.")] + [Parameter] + public bool AutoComplete { get; set; } + + /// + /// Gets or sets whether the input is disabled. + /// + /// + /// Default value is false. + /// + [AddedVersion("3.3.0")] + [DefaultValue(false)] + [Description("Gets or sets whether the input is disabled. When true, users cannot change its value.")] + [Parameter] + public bool Disabled { get; set; } + + [CascadingParameter] private EditContext EditContext { get; set; } = default!; + + private string fieldCssClasses => EditContext?.FieldCssClass(fieldIdentifier) ?? ""; + + /// + /// Gets or sets the maximum number of characters users can enter. + /// + /// + /// Default value is . + /// + [AddedVersion("3.3.0")] + [DefaultValue(null)] + [Description("Gets or sets the maximum number of characters users can enter. Additional input is prevented when the limit is reached.")] + [Parameter] + public int? MaxLength { get; set; } + + /// + /// Gets or sets placeholder text displayed when the input has no value. + /// + /// + /// Default value is null. + /// + [AddedVersion("3.3.0")] + [DefaultValue(null)] + [Description("Gets or sets placeholder text displayed when the input has no value.")] + [Parameter] + public string? Placeholder { get; set; } + + /// + /// Gets or sets the horizontal alignment of the input value. + /// + /// + /// Default value is . + /// + [AddedVersion("3.3.0")] + [DefaultValue(Alignment.None)] + [Description("Gets or sets the horizontal alignment of the input value.")] + [Parameter] + public Alignment TextAlignment { get; set; } = Alignment.None; + + /// + /// Gets or sets the current text value bound to the input. + /// + /// + /// Default value is . + /// + [AddedVersion("3.3.0")] + [DefaultValue(null)] + [Description("Gets or sets the current text value bound to the input.")] + [Parameter] + public string Value { get; set; } = default!; + + /// + /// This event fires when the value changes. + /// + [AddedVersion("3.3.0")] + [Description("Fires whenever user input changes the text value.")] + [Parameter] + public EventCallback ValueChanged { get; set; } + + /// + /// Gets or sets the expression that identifies the bound value for validation and EditContext notifications. + /// + /// + /// Default value is . + /// + [AddedVersion("3.3.0")] + [DefaultValue(null)] + [Description("Gets or sets the expression that identifies the bound value for validation and EditContext notifications.")] + [Parameter] + public Expression> ValueExpression { get; set; } = default!; + + #endregion +} diff --git a/blazorbootstrap/Components/Form/TimeInput/TimeInput.razor.cs b/blazorbootstrap/Components/Form/TimeInput/TimeInput.razor.cs index ca48872d4..1070467a0 100644 --- a/blazorbootstrap/Components/Form/TimeInput/TimeInput.razor.cs +++ b/blazorbootstrap/Components/Form/TimeInput/TimeInput.razor.cs @@ -1,5 +1,6 @@ namespace BlazorBootstrap; +[AddedVersion("1.6.0")] public partial class TimeInput : BlazorBootstrapComponentBase { #region Fields and Constants @@ -112,13 +113,17 @@ protected override async Task OnParametersSetAsync() } /// - /// Disables currency input. + /// Disables the time input so users cannot change its value. /// + [AddedVersion("1.6.0")] + [Description("Disables the time input so users cannot change its value.")] public void Disable() => Disabled = true; /// - /// Enables currency input. + /// Enables the time input so users can change its value. /// + [AddedVersion("1.6.0")] + [Description("Enables the time input so users can change its value.")] public void Enable() => Disabled = false; private string GetFormattedValue(object value) @@ -202,7 +207,7 @@ private async Task SetValueAsync(TValue oldValue, object? newValue) formattedValue = GetFormattedValue(Value!); if (oldValue!.Equals(Value)) - await JSRuntime.InvokeVoidAsync("window.blazorBootstrap.timeInput.setValue", Id, formattedValue); + await SafeInvokeVoidAsync("window.blazorBootstrap.timeInput.setValue", Id, formattedValue); await ValueChanged.InvokeAsync(Value); @@ -251,75 +256,101 @@ private bool TryParseValue(object value, out TValue newValue) private string autoComplete => AutoComplete ? "true" : "false"; /// - /// If , DateInput can complete the values automatically by the browser. + /// Gets or sets whether browser autocomplete is enabled for the time input. /// /// /// Default value is false. /// + [AddedVersion("1.6.0")] + [DefaultValue(false)] + [Description("Gets or sets whether browser autocomplete is enabled. When true, the browser may offer saved times for the input.")] [Parameter] public bool AutoComplete { get; set; } /// - /// Gets or sets the disabled state. + /// Gets or sets whether the time input is disabled. /// /// /// Default value is false. /// + [AddedVersion("1.6.0")] + [DefaultValue(false)] + [Description("Gets or sets whether the time input is disabled. When true, users cannot change its value.")] [Parameter] public bool Disabled { get; set; } + [AddedVersion("1.6.0")] [CascadingParameter] private EditContext EditContext { get; set; } = default!; + [DefaultValue(false)] /// - /// Determines whether to restrict the user input to Min and Max range. - /// If , restricts the user input between the Min and Max range. Else accepts the user input. + /// Gets or sets whether input is restricted to the configured minimum and maximum times. + /// /// /// /// Default value is false. /// + [Description("Gets or sets whether input is restricted to the configured minimum and maximum times. When true, times outside the range are rejected.")] [Parameter] public bool EnableMinMax { get; set; } private string fieldCssClasses => EditContext?.FieldCssClass(fieldIdentifier) ?? ""; /// - /// Gets or sets the max. - /// Allowed format is hh:mm. + /// Gets or sets the maximum permitted time. + /// /// + [AddedVersion("1.6.0")] + [Description("Gets or sets the maximum permitted time. It is enforced only when EnableMinMax is true.")] [Parameter] public TValue Max { get; set; } = default!; /// - /// Gets or sets the min. - /// Allowed format is hh:mm. + /// Gets or sets the minimum permitted time. + /// /// + [AddedVersion("1.6.0")] + [Description("Gets or sets the minimum permitted time. It is enforced only when EnableMinMax is true.")] [Parameter] public TValue Min { get; set; } = default!; /// - /// Gets or sets the placeholder. + /// Gets or sets placeholder text displayed when the input has no value. /// /// /// Default value is null. /// + [AddedVersion("1.6.0")] + [DefaultValue(null)] + [Description("Gets or sets placeholder text displayed when the input has no value.")] [Parameter] public string? Placeholder { get; set; } /// - /// Gets or sets the value. + /// Gets or sets the current time value bound to the input. /// + [AddedVersion("1.6.0")] + [Description("Gets or sets the current time value bound to the input.")] [Parameter] public TValue Value { get; set; } = default!; /// - /// This event fired on every user keystroke that changes the TimeInput value. + /// Occurs whenever user input changes the time value, including changes produced by typing. /// + [AddedVersion("1.6.0")] + [Description("Fires whenever user input changes the time value, including changes produced by typing.")] [Parameter] public EventCallback ValueChanged { get; set; } /// - /// Gets or sets the expression. + /// Gets or sets the expression that identifies the bound value for validation and EditContext notifications. /// + /// + /// Default value is . + /// + [AddedVersion("1.6.0")] + [DefaultValue(null)] + [Description("Gets or sets the expression that identifies the bound value for validation and EditContext notifications.")] [Parameter] public Expression> ValueExpression { get; set; } = default!; diff --git a/blazorbootstrap/Components/Grid/Grid.razor b/blazorbootstrap/Components/Grid/Grid.razor index 88f0c3f50..e6f7a82d4 100644 --- a/blazorbootstrap/Components/Grid/Grid.razor +++ b/blazorbootstrap/Components/Grid/Grid.razor @@ -7,7 +7,11 @@ @if (columns.Any()) -{ +{ + var columnCount = columns.Where(c => c.IsVisible).Count(); + if (AllowSelection) columnCount += 1; + if (AllowDetailView) columnCount += 1; +
    @@ -22,6 +26,10 @@ } @foreach (var column in columns) { + @if (!column.IsVisible) + { + continue; + } @column.HeaderTemplate } @@ -38,6 +46,10 @@ } @foreach (var column in columns) { + @if (!column.IsVisible) + { + continue; + } var columnClassList = new HashSet(); var columnStyleList = new List(); @@ -56,32 +68,37 @@ } } } - @{ - var columnCount = columns.Count; - if (AllowSelection) columnCount += 1; - if (AllowDetailView) columnCount += 1; - } @if (requestInProgress) //|| totalCount is null { @if (loadingTemplate is null) @@ -140,7 +157,7 @@ { var rowClass = RowClass?.Invoke(item) ?? ""; var detailViewRowId = IdUtility.GetNextId(); - + @if (AllowDetailView) { @@ -179,12 +200,41 @@ } } + @if (AllowSummary) + { + + + @if (totalCount > 0) + { + @if (AllowSelection) + { + + } + foreach (var column in columns) + { + @if (!column.IsVisible) + { + continue; + } + else if (column.SummaryType == GridSummaryColumnType.None) + { + + } + else if (column.SummaryType != GridSummaryColumnType.None) + { + + } + } + } + + + }
    - @if (column.Filterable) + + @if (isColumnsLoading) { - + + + } + else + { + @if (column.Filterable) + { + + } + }
    @@ -158,6 +175,10 @@ @foreach (var column in columns) { + @if (!column.IsVisible) + { + continue; + } @column.CellTemplate(item) }
    @GetColumnSummaryValue(column.SummaryType, column.PropertyName, column.SummaryValueDisplayFormat, column.SummaryValuePrefix)
    @if (AllowPaging && totalCount.HasValue && totalCount.Value > 0 && (!AutoHidePaging || (AutoHidePaging && totalCount.Value > pageSize))) { -
    +
    : BlazorBootstrapComponentBase private List> columns = new(); + private GridDetailView? detailView; + + public GridEmptyDataTemplate? emptyDataTemplate; + /// /// Current grid state (filters, paging, sorting). /// @@ -21,11 +25,7 @@ public partial class Grid : BlazorBootstrapComponentBase private RenderFragment? headerSelectionTemplate; - private GridDetailView? detailView; - - public GridEmptyDataTemplate? emptyDataTemplate; - - public GridLoadingTemplate? loadingTemplate; + private bool isColumnVisibilityChanged = false; private bool isFirstRenderComplete = false; @@ -33,16 +33,20 @@ public partial class Grid : BlazorBootstrapComponentBase private object? lastAssignedDataOrDataProvider; + public GridLoadingTemplate? loadingTemplate; + private int pageSize; private bool requestInProgress = false; private HashSet selectedItems = new(); - public int SelectedItemsCount = 0; - private int? totalCount = null; + private bool pendingPageSizeChanging = false; + + private bool isColumnsLoading = false; + #endregion #region Methods @@ -55,6 +59,9 @@ protected override async Task OnAfterRenderAsync(bool firstRender) isFirstRenderComplete = true; } + // As Rendering now complete we can reset the column visibility change to false + isColumnVisibilityChanged = false; + await base.OnAfterRenderAsync(firstRender); } @@ -63,17 +70,27 @@ protected override void OnInitialized() headerCheckboxId = IdUtility.GetNextId(); pageSize = PageSize; + selectedItems = SelectedItems!; + + isColumnsLoading = true; base.OnInitialized(); } - protected override Task OnParametersSetAsync() + protected override async Task OnParametersSetAsync() { - if ((Data is null && DataProvider is null) || (Data is not null && DataProvider is not null)) throw new ArgumentException($"Grid requires either {nameof(Data)} or {nameof(DataProvider)}, but not both or neither."); + if ((Data is null && DataProvider is null) || (Data is not null && DataProvider is not null)) + throw new ArgumentException($"Grid requires either {nameof(Data)} or {nameof(DataProvider)}, but not both or neither."); if (AllowPaging && PageSize < 0) throw new ArgumentException($"{nameof(PageSize)} must be greater than zero."); + if (pendingPageSizeChanging) + { + PageSize = pageSize; + return; + } + if (isFirstRenderComplete) { // Perform a re-query only if the data source or something else has changed @@ -88,43 +105,119 @@ protected override Task OnParametersSetAsync() { mustRefreshData = true; pageSize = PageSize; - _ = ResetPageNumberAsync(); - SaveGridSettingsAsync(); + await ResetPageNumberAsync(); + await SaveGridSettingsAsync(); } + //if (!mustRefreshData && selectedItems != SelectedItems) + //{ + // mustRefreshData = true; + // SelectedItems = selectedItems; + //} + // We want to trigger the first data load when we've collected the initial set of columns // because they might perform some action, like setting the default sort order. // It would be wasteful to have to re-query immediately. - return columns.Count > 0 && mustRefreshData ? RefreshDataAsync(false) : Task.CompletedTask; + if (columns.Count > 0 && mustRefreshData) + await RefreshDataAsync(false); } - return base.OnParametersSetAsync(); + await base.OnParametersSetAsync(); } /// /// Get filters. /// /// IEnumerable + [AddedVersion("1.0.0")] + [Description("Get filters.")] public IEnumerable? GetFilters() => !AllowFiltering || columns == null || !columns.Any() ? null : columns .Where(column => column.Filterable && column.GetFilterOperator() != FilterOperator.None && !string.IsNullOrWhiteSpace(column.GetFilterValue())) - ?.Select(column => new FilterItem(column.PropertyName, column.GetFilterValue(), column.GetFilterOperator(), column.StringComparison)); + ?.Select(column => new FilterItem(column.PropertyName!, column.GetFilterValue(), column.GetFilterOperator(), column.StringComparison)); + + private string GetColumnSummaryValue(GridSummaryColumnType type, string propertyName, string format, string prefix) + { + double value = 0; + + if (type == GridSummaryColumnType.Average) + { + prefix ??= "Avg: "; + value = items?.Average(x => Convert.ToDouble(x?.GetType().GetProperty(propertyName)?.GetValue(x))) ?? 0; + } + else if (type == GridSummaryColumnType.Count) + { + prefix ??= "Count: "; + value = items?.Where(x => x?.GetType().GetProperty(propertyName)?.GetValue(x) is not null).Count() ?? 0; + } + else if (type == GridSummaryColumnType.Max) + { + prefix ??= "Max: "; + value = items?.Max(x => Convert.ToDouble(x?.GetType().GetProperty(propertyName)?.GetValue(x))) ?? 0; + } + else if (type == GridSummaryColumnType.Min) + { + prefix ??= "Min: "; + value = items?.Min(x => Convert.ToDouble(x?.GetType().GetProperty(propertyName)?.GetValue(x))) ?? 0; + } + else if (type == GridSummaryColumnType.Sum) + { + prefix ??= "Total: "; + value = items?.Sum(x => Convert.ToDouble(x?.GetType().GetProperty(propertyName)?.GetValue(x))) ?? 0; + } + + if (string.IsNullOrWhiteSpace(format)) + return $"{prefix}{value}"; + else + return $"{prefix}{value.ToString(format, GetCultureInfo())}"; + } /// /// Refresh the grid data. /// /// Task + [AddedVersion("1.0.0")] + [Description("Refresh the grid data.")] public async Task RefreshDataAsync(CancellationToken cancellationToken = default) => await RefreshDataAsync(false, cancellationToken); /// /// Reset the page number to 1 and refresh the grid. /// + [AddedVersion("1.4.3")] + [Description("Reset the page number to 1 and refresh the grid.")] public async ValueTask ResetPageNumber() => await ResetPageNumberAsync(true); + /// + /// Selects all items in the grid asynchronously. + /// + /// A task that represents the asynchronous operation. The task completes when all items have been selected. + [AddedVersion("1.8.0")] + [Description("Selects all items in the grid asynchronously.")] + public Task SelectAllItemsAsync() => SelectAllItemsInternalAsync(true); + + /// + /// Asynchronously clears the selection of all items in the grid. + /// + /// This method can be awaited to ensure that all items are unselected before proceeding with + /// further actions. If no items are currently selected, the operation completes without effect. + /// A task that represents the asynchronous operation of deselecting all items. + [AddedVersion("1.8.0")] + [Description("Asynchronously clears the selection of all items in the grid.")] + public Task UnSelectAllItemsAsync() => SelectAllItemsInternalAsync(false); + internal void AddColumn(GridColumn column) => columns.Add(column); + internal void ColumnVisibilityUpdated() + { + if (!isColumnVisibilityChanged) + { + isColumnVisibilityChanged = true; + StateHasChanged(); + } + } + internal async Task FilterChangedAsync() { if (cancellationTokenSource is not null @@ -177,6 +270,10 @@ internal async Task RefreshDataAsync(bool firstRender = false, CancellationToken { items = result.Data!.ToList(); totalCount = result.TotalCount ?? result.Data!.Count(); + if (result.PageNumber.HasValue) + { + gridCurrentState = new GridState(result.PageNumber.Value, gridCurrentState.Sorting); + } } else { @@ -187,11 +284,12 @@ internal async Task RefreshDataAsync(bool firstRender = false, CancellationToken if (AllowSelection) { PrepareCheckboxIds(); - - if (!firstRender) - await RefreshSelectionAsync(); + await RefreshSelectionAsync(); } + if (firstRender) + isColumnsLoading = false; + requestInProgress = false; await InvokeAsync(StateHasChanged); @@ -205,6 +303,12 @@ internal async ValueTask ResetPageNumberAsync(bool refreshGrid = false) await RefreshDataAsync(false); } + internal void SetGridDetailView(GridDetailView detailView) => this.detailView = detailView; + + internal void SetGridEmptyDataTemplate(GridEmptyDataTemplate emptyDataTemplate) => this.emptyDataTemplate = emptyDataTemplate; + + internal void SetGridLoadingTemplate(GridLoadingTemplate loadingTemplate) => this.loadingTemplate = loadingTemplate; + internal async Task SortingChangedAsync(GridColumn column) { if (columns == null || !columns.Any()) @@ -243,7 +347,7 @@ internal async Task SortingChangedAsync(GridColumn column) await RefreshDataAsync(false); } - private async Task CheckOrUnCheckAll() => await JSRuntime.InvokeVoidAsync("window.blazorBootstrap.grid.checkOrUnCheckAll", $".bb-grid-form-check-{headerCheckboxId} > input.form-check-input", allItemsSelected); + private async Task CheckOrUnCheckAll() => await SafeInvokeVoidAsync("window.blazorBootstrap.grid.checkOrUnCheckAll", $".bb-grid-form-check-{headerCheckboxId} > input.form-check-input", allItemsSelected); /// /// Child selection template. @@ -284,6 +388,21 @@ private RenderFragment ChildSelectionTemplate(int rowIndex, TItem rowData) => builder.CloseElement(); // close: th }; + private CultureInfo GetCultureInfo() + { + if (string.IsNullOrWhiteSpace(Locale)) + return CultureInfo.CurrentCulture; + + try + { + return CultureInfo.GetCultureInfo(Locale); + } + catch (CultureNotFoundException) + { + return CultureInfo.InvariantCulture; + } + } + private IEnumerable>? GetDefaultSorting() => !AllowSorting || columns == null || !columns.Any() ? null @@ -343,7 +462,7 @@ private int GetTotalPagesCount() /// /// /// bool - private bool IsItemSelected(TItem item) => selectedItems.Contains(item); + private bool IsItemSelected(TItem item) => selectedItems?.Contains(item) ?? false; private async Task LoadGridSettingsAsync() { @@ -358,18 +477,10 @@ private async Task LoadGridSettingsAsync() if (settings.Filters is not null && settings.Filters.Any()) SetFilters(settings.Filters); - if (settings.PageNumber > 0) - { - if (settings.PageSize > 0 && settings.PageNumber < settings.PageSize) - { - gridCurrentState = new GridState(settings.PageNumber, gridCurrentState.Sorting); - pageSize = settings.PageSize; - } - else - { - gridCurrentState = new GridState(1, null); - pageSize = 10; - } + if ((settings.PageNumber > 0) && (settings.PageSize > 0)) + { + gridCurrentState = new GridState(settings.PageNumber, gridCurrentState.Sorting); + pageSize = settings.PageSize; } else { @@ -380,28 +491,27 @@ private async Task LoadGridSettingsAsync() private async Task OnHeaderCheckboxChanged(ChangeEventArgs args) { - allItemsSelected = bool.TryParse(args?.Value?.ToString(), out var checkboxState) && checkboxState; - selectedItems = allItemsSelected ? new HashSet(items!) : new HashSet(); - SelectedItemsCount = selectedItems.Count; - await CheckOrUnCheckAll(); - - if (SelectedItemsChanged.HasDelegate) - await SelectedItemsChanged.InvokeAsync(selectedItems); + var headerCheckboxState = bool.TryParse(args?.Value?.ToString(), out var checkboxState) && checkboxState; + await SelectAllItemsInternalAsync(headerCheckboxState); } private async Task OnPageChangedAsync(int newPageNumber) { + pendingPageSizeChanging = true; gridCurrentState = new GridState(newPageNumber, gridCurrentState.Sorting); await SaveGridSettingsAsync(); await RefreshDataAsync(false); + pendingPageSizeChanging = false; } private async Task OnPageSizeChangedAsync(int newPageSize) { + pendingPageSizeChanging = true; pageSize = PageSize = newPageSize; await ResetPageNumberAsync(); await SaveGridSettingsAsync(); await RefreshDataAsync(false); + pendingPageSizeChanging = false; } private async Task OnRowCheckboxChanged(string id, TItem item, ChangeEventArgs args) @@ -411,12 +521,11 @@ private async Task OnRowCheckboxChanged(string id, TItem item, ChangeEventArgs a if (SelectionMode == GridSelectionMode.Multiple) { _ = isChecked ? selectedItems.Add(item) : selectedItems.Remove(item); - SelectedItemsCount = selectedItems.Count; - allItemsSelected = SelectedItemsCount == (items?.Count ?? 0); + allItemsSelected = (selectedItems.Count == (items?.Count ?? 0)); if (allItemsSelected) await SetCheckboxStateAsync(headerCheckboxId, CheckboxState.Checked); - else if (SelectedItemsCount == 0) + else if (selectedItems.Count == 0) await SetCheckboxStateAsync(headerCheckboxId, CheckboxState.Unchecked); else await SetCheckboxStateAsync(headerCheckboxId, CheckboxState.Indeterminate); @@ -424,7 +533,6 @@ private async Task OnRowCheckboxChanged(string id, TItem item, ChangeEventArgs a else { selectedItems = isChecked ? new HashSet { item } : new HashSet(); - SelectedItemsCount = selectedItems.Count; allItemsSelected = false; await CheckOrUnCheckAll(); await SetCheckboxStateAsync(id, isChecked ? CheckboxState.Checked : CheckboxState.Unchecked); @@ -432,11 +540,13 @@ private async Task OnRowCheckboxChanged(string id, TItem item, ChangeEventArgs a if (SelectedItemsChanged.HasDelegate) await SelectedItemsChanged.InvokeAsync(selectedItems); + else + SelectedItems = selectedItems; } private async Task OnScroll(EventArgs e) { - await JSRuntime.InvokeVoidAsync("window.blazorBootstrap.grid.scroll", Id); + await SafeInvokeVoidAsync("window.blazorBootstrap.grid.scroll", Id); } private void PrepareCheckboxIds() @@ -459,18 +569,19 @@ private async Task RefreshSelectionAsync() ? new HashSet() : selectedItems?.Intersect(items!).ToHashSet() ?? new HashSet(); - SelectedItemsCount = selectedItems.Count; - allItemsSelected = SelectedItemsCount > 0 && items!.Count == SelectedItemsCount; + allItemsSelected = selectedItems.Count > 0 && items!.Count == selectedItems.Count; if (allItemsSelected) await SetCheckboxStateAsync(headerCheckboxId, CheckboxState.Checked); - else if (SelectedItemsCount > 0) + else if (selectedItems.Count > 0) await SetCheckboxStateAsync(headerCheckboxId, CheckboxState.Indeterminate); else await SetCheckboxStateAsync(headerCheckboxId, CheckboxState.Unchecked); if (SelectedItemsChanged.HasDelegate) await SelectedItemsChanged.InvokeAsync(selectedItems); + else + SelectedItems = selectedItems; } private async Task RowClick(TItem item, EventArgs args) @@ -485,23 +596,41 @@ private async Task RowDoubleClick(TItem item, EventArgs args) await OnRowDoubleClick.InvokeAsync(new GridRowEventArgs(item)); } - private Task SaveGridSettingsAsync() + private async Task SaveGridSettingsAsync() { if (!GridSettingsChanged.HasDelegate) - return Task.CompletedTask; + return; var settings = new GridSettings { PageNumber = AllowPaging ? gridCurrentState.PageIndex : 0, PageSize = AllowPaging ? pageSize : 0, Filters = AllowFiltering ? GetFilters() : null }; - return GridSettingsChanged.InvokeAsync(settings); + await GridSettingsChanged.InvokeAsync(settings); } - private async Task SetCheckboxStateAsync(string id, CheckboxState checkboxState) => await JSRuntime.InvokeVoidAsync("window.blazorBootstrap.grid.setSelectAllCheckboxState", id, (int)checkboxState); + private async Task SelectAllItemsInternalAsync(bool selectAll) + { + if (SelectionMode != GridSelectionMode.Multiple) + return; - internal void SetGridDetailView(GridDetailView detailView) => this.detailView = detailView; + allItemsSelected = selectAll; + selectedItems = allItemsSelected ? new HashSet(items!) : new HashSet(); - internal void SetGridEmptyDataTemplate(GridEmptyDataTemplate emptyDataTemplate) => this.emptyDataTemplate = emptyDataTemplate; + if (allItemsSelected) + await SetCheckboxStateAsync(headerCheckboxId, CheckboxState.Checked); + else + await SetCheckboxStateAsync(headerCheckboxId, CheckboxState.Unchecked); - internal void SetGridLoadingTemplate(GridLoadingTemplate loadingTemplate) => this.loadingTemplate = loadingTemplate; + await CheckOrUnCheckAll(); + + if (SelectedItemsChanged.HasDelegate) + await SelectedItemsChanged.InvokeAsync(selectedItems); + else + SelectedItems = selectedItems; + } + + private async Task SetCheckboxStateAsync(string id, CheckboxState checkboxState) + { + queuedTasks.Enqueue(async () => await SafeInvokeVoidAsync("window.blazorBootstrap.grid.setSelectAllCheckboxState", id, (int)checkboxState)); + } /// /// Set filters. @@ -534,9 +663,11 @@ private void SetFilters(IEnumerable filterItems) #region Properties, Indexers protected override string? ClassNames => - BuildClassNames(Class, + BuildClassNames( + Class, ("bb-table", true), - (BootstrapClass.TableSticky, FixedHeader)); + (BootstrapClass.TableSticky, FixedHeader) + ); /// /// Gets or sets the grid delete. @@ -550,188 +681,280 @@ private void SetFilters(IEnumerable filterItems) /// /// Gets or sets a value indicating whether the grid detail view is enabled. + /// + /// Default value is . + /// /// - /// - /// Default value is false. - /// + [AddedVersion("3.0.0")] + [DefaultValue(false)] + [Description("Gets or sets a value indicating whether the grid detail view is enabled.")] [Parameter] public bool AllowDetailView { get; set; } /// /// Gets or sets the grid filtering. + /// + /// Default value is . + /// /// - /// - /// Default value is false. - /// + [AddedVersion("1.0.0")] + [DefaultValue(false)] + [Description("Gets or sets the grid filtering.")] [Parameter] public bool AllowFiltering { get; set; } /// /// Gets or sets the grid paging. + /// + /// Default value is . + /// /// - /// - /// Default value is false. - /// + [AddedVersion("1.0.0")] + [DefaultValue(false)] + [Description("Gets or sets the grid paging.")] [Parameter] public bool AllowPaging { get; set; } /// /// Gets or sets the allow row click. + /// + /// Default value is . + /// /// - /// - /// Default value is false. - /// + [AddedVersion("1.9.5")] + [DefaultValue(false)] + [Description("Gets or sets the allow row click.")] [Parameter] public bool AllowRowClick { get; set; } /// /// Gets or sets the grid selection. + /// + /// Default value is . + /// /// - /// - /// Default value is false. - /// + [AddedVersion("1.8.0")] + [DefaultValue(false)] + [Description("Gets or sets the grid selection.")] [Parameter] public bool AllowSelection { get; set; } /// /// Gets or sets the grid sorting. + /// + /// Default value is . + /// /// - /// - /// Default value is false. - /// + [AddedVersion("1.0.0")] + [DefaultValue(false)] + [Description("Gets or sets the grid sorting.")] [Parameter] public bool AllowSorting { get; set; } + /// + /// Gets or sets the grid summary. + /// + /// Default value is . + /// + /// + [AddedVersion("1.0.0")] + [DefaultValue(false)] + [Description("Gets or sets the grid summary.")] + [Parameter] + public bool AllowSummary { get; set; } + /// /// Automatically hides the paging controls when the grid item count is less than or equal to the /// and this property is set to `true`. + /// + /// Default value is . + /// /// - /// - /// Default value is false. - /// + [AddedVersion("1.10.5")] + [DefaultValue(false)] + [Description("Automatically hides the paging controls when the grid item count is less than or equal to the PageSize and this property is set to true.")] [Parameter] public bool AutoHidePaging { get; set; } /// /// Gets or sets the content to be rendered within the component. + /// + /// Default value is . + /// /// - /// - /// Default value is null. - /// + [AddedVersion("1.0.0")] + [DefaultValue(null)] + [Description("Gets or sets the content to be rendered within the component.")] + [EditorRequired] [Parameter] - public RenderFragment ChildContent { get; set; } = default!; + public RenderFragment? ChildContent { get; set; } /// /// Gets or sets the grid data. + /// + /// Default value is . + /// /// - /// - /// Default value is null. - /// + [AddedVersion("1.4.3")] + [DefaultValue(null)] + [Description("Gets or sets the grid data.")] [Parameter] - public IEnumerable Data { get; set; } = default!; + public IEnumerable? Data { get; set; } /// /// DataProvider is for items to render. - /// The provider should always return an instance of 'GridDataProviderResult', and 'null' is not allowed. + /// The provider should always return an instance of , and is not allowed. + /// + /// Default value is . + /// /// - /// - /// Default value is null. - /// + [AddedVersion("1.0.0")] + [DefaultValue(null)] + [Description("DataProvider is for items to render. The provider should always return an instance of GridDataProviderResult, and null is not allowed.")] [Parameter] - public GridDataProviderDelegate DataProvider { get; set; } = default!; + public GridDataProviderDelegate? DataProvider { get; set; } /// /// Enable or disable the header checkbox selection. + /// + /// Default value is . + /// /// + [AddedVersion("1.8.0")] + [DefaultValue(null)] + [Description("Enable or disable the header checkbox selection.")] [Parameter] public Func, bool>? DisableAllRowsSelection { get; set; } /// /// Enable or disable the row level checkbox selection. + /// + /// Default value is . + /// /// + [AddedVersion("1.8.0")] + [DefaultValue(null)] + [Description("Enable or disable the row level checkbox selection.")] [Parameter] public Func? DisableRowSelection { get; set; } /// /// Gets or sets the empty text. /// Shows text on no records. - /// - /// + /// /// Default value is 'No records to display'. - /// + /// + /// + [AddedVersion("1.0.0")] + [DefaultValue("No records to display")] + [Description("Gets or sets the empty text. Shows text on no records.")] [Parameter] public string EmptyText { get; set; } = "No records to display"; /// /// Gets or sets the enum filter select text. - /// - /// + /// /// Default value is 'Select'. - /// + /// + /// + [AddedVersion("3.1.0")] + [DefaultValue("Select")] + [Description("Gets or sets the enum filter select text.")] [Parameter] - public string? EnumFilterSelectText { get; set; } = "Select"; + public string EnumFilterSelectText { get; set; } = "Select"; /// /// Gets or sets the filters row css class. + /// + /// Default value is . + /// /// - /// - /// Default value is null. - /// + [AddedVersion("1.9.2")] + [DefaultValue(null)] + [Description("Gets or sets the filters row css class.")] [Parameter] - public string FiltersRowCssClass { get; set; } = default!; + public string? FiltersRowCssClass { get; set; } /// /// Gets or sets the filters translation provider. + /// + /// Default value is . + /// /// - /// - /// Default value is null. - /// + [AddedVersion("1.10.0")] + [DefaultValue(null)] + [Description("Gets or sets the filters translation provider.")] [Parameter] - public GridFiltersTranslationDelegate FiltersTranslationProvider { get; set; } = default!; + public GridFiltersTranslationDelegate? FiltersTranslationProvider { get; set; } /// /// Gets or sets the grid fixed header. + /// + /// Default value is . + /// /// - /// - /// Default value is false. - /// + [AddedVersion("1.10.3")] + [DefaultValue(false)] + [Description("Gets or sets the grid fixed header.")] [Parameter] public bool FixedHeader { get; set; } /// /// Gets or sets the grid container css class. + /// + /// Default value is . + /// /// + [AddedVersion("3.0.0")] + [DefaultValue(null)] + [Description("Gets or sets the grid container css class.")] [Parameter] public string? GridContainerClass { get; set; } private string? GridContainerClassNames => - BuildClassNames(GridContainerClass, - (BootstrapClass.TableResponsive, Responsive)); + BuildClassNames( + GridContainerClass, + (BootstrapClass.TableResponsive, Responsive) + ); /// /// Gets or sets the grid container css style. + /// + /// Default value is . + /// /// + [AddedVersion("3.0.0")] + [DefaultValue(null)] + [Description("Gets or sets the grid container css style.")] [Parameter] public string? GridContainerStyle { get; set; } private string? GridContainerStyleNames => - BuildStyleNames(GridContainerStyle, - ($"height:{Height.ToString(CultureInfo.InvariantCulture)}{Unit.ToCssString()}", FixedHeader)); + BuildStyleNames( + GridContainerStyle, + ($"height:{Height.ToString(CultureInfo.InvariantCulture)}{Unit.ToCssString()}", FixedHeader), + ($"overflow-x:auto;", Responsive) + ); /// /// This event is fired when the grid state is changed. /// + [AddedVersion("1.0.0")] + [Description("This event is fired when the grid state is changed.")] [Parameter] public EventCallback GridSettingsChanged { get; set; } /// /// Gets or sets the header row css class but not the thead tag class. + /// + /// Default value is . + /// /// - /// - /// Default value is null. - /// + [AddedVersion("1.9.2")] + [DefaultValue(null)] + [Description("Gets or sets the header row css class but not the thead tag class.")] [Parameter] - public string HeaderRowCssClass { get; set; } = default!; + public string? HeaderRowCssClass { get; set; } /// /// Header selection template. @@ -776,27 +999,46 @@ private void SetFilters(IEnumerable filterItems) /// /// Gets or sets the grid height. - /// - /// + /// /// Default value is 320 . - /// + /// + /// + [AddedVersion("1.10.3")] + [DefaultValue(320)] + [Description("Gets or sets the grid height.")] [Parameter] public float Height { get; set; } = 320; /// /// Gets or sets the items per page text. - /// - /// + /// /// Default value is 'Items per page'. - /// + /// + ///
    + [AddedVersion("1.9.5")] + [DefaultValue("Items per page")] + [Description("Gets or sets the items per page text.")] [Parameter] - //[EditorRequired] public string ItemsPerPageText { get; set; } = "Items per page"!; + /// + /// Gets or sets the locale. + /// + /// Default value is . + /// + /// + [AddedVersion("3.4.0")] + [DefaultValue(null)] + [Description("Gets or sets the locale.")] + [Parameter] + public string? Locale { get; set; } + /// /// This event is triggered when the user clicks on the row. /// Set AllowRowClick to true to enable row clicking. /// + [AddedVersion("1.9.5")] + [Description("This event is triggered when the user clicks on the row. Set AllowRowClick to true to enable row clicking.")] [Parameter] public EventCallback> OnRowClick { get; set; } @@ -804,105 +1046,154 @@ private void SetFilters(IEnumerable filterItems) /// This event is triggered when the user double clicks on the row. /// Set AllowRowClick to true to enable row double clicking. /// + [AddedVersion("1.9.5")] + [Description("This event is triggered when the user double clicks on the row. Set AllowRowClick to true to enable row double clicking.")] [Parameter] public EventCallback> OnRowDoubleClick { get; set; } /// /// Gets or sets the page size. - /// - /// + /// /// Default value is 10. - /// + /// + /// + [AddedVersion("1.0.0")] + [DefaultValue(10)] + [Description("Gets or sets the page size.")] [Parameter] public int PageSize { get; set; } = 10; /// /// Gets or sets the page size selector items. - /// - /// + /// /// Default value is '{ 10, 20, 50 }'. - /// + /// + /// + [AddedVersion("1.8.0")] + [DefaultValue(new int[] { 10, 20, 50 })] + [Description("Gets or sets the page size selector items.")] [Parameter] - //[EditorRequired] public int[] PageSizeSelectorItems { get; set; } = { 10, 20, 50 }; /// /// Gets or sets the page size selector visible. + /// + /// Default value is . + /// /// - /// - /// Default value is false. - /// + [AddedVersion("1.8.0")] + [DefaultValue(false)] + [Description("Gets or sets the page size selector visible.")] [Parameter] public bool PageSizeSelectorVisible { get; set; } - [Obsolete("PaginationAlignment parameter is not supported from 1.8.0 version onwards")] - /// - /// Gets or sets the pagination alignment. - /// - /// - /// Default value is . - /// - [Parameter] - public Alignment PaginationAlignment { get; set; } = Alignment.Start; - private string paginationItemsText => GetPaginationItemsText(); /// /// Gets or sets the pagination items text format. - /// - /// + /// /// Default value is '{0} - {1} of {2} items'. - /// + /// + /// + [AddedVersion("1.8.0")] + [DefaultValue("{0} - {1} of {2} items")] + [Description("Gets or sets the pagination items text format.")] [Parameter] - //[EditorRequired] public string PaginationItemsTextFormat { get; set; } = "{0} - {1} of {2} items"!; /// /// Gets or sets a value indicating whether the grid is responsive. + /// + /// Default value is . + /// /// - /// - /// Default value is false. - /// + [AddedVersion("1.0.0")] + [DefaultValue(false)] + [Description("Gets or sets a value indicating whether the grid is responsive.")] [Parameter] public bool Responsive { get; set; } /// /// Gets or sets the row class. + /// + /// Default value is . + /// /// + [AddedVersion("1.6.0")] + [DefaultValue(null)] + [Description("Gets or sets the row class.")] [Parameter] public Func? RowClass { get; set; } + /// + /// Gets or sets the function used to extract a unique key from a row item. + /// + /// The key returned by the function is used to uniquely identify each row in the data set. This + /// is typically required for operations such as tracking changes or rendering rows efficiently. + /// If not set, the item hash code will be used as the key. + /// Example usage: `RowKeySelector="(employee) => employee.Id"`. + /// + /// + [AddedVersion("1.0.0")] + [DefaultValue(null)] + [Description("Gets or sets the function used to extract a unique key from a row item.")] + [Parameter] + public Func? RowKeySelector { get; set; } + + /// + /// Gets or sets the selected items. + /// + /// Default value is . + /// + /// + [AddedVersion("1.8.0")] + [DefaultValue(null)] + [Description("Gets or sets the selected items.")] + [Parameter] + public HashSet? SelectedItems { get; set; } + /// /// This event is fired when the item selection changes. /// + [AddedVersion("1.8.0")] + [Description("This event is fired when the item selection changes.")] [Parameter] public EventCallback> SelectedItemsChanged { get; set; } /// /// Gets or sets the grid selection mode. - /// - /// + /// /// Default value is . - /// + /// + /// + [AddedVersion("1.8.0")] + [DefaultValue(GridSelectionMode.Single)] + [Description("Gets or sets the grid selection mode.")] [Parameter] public GridSelectionMode SelectionMode { get; set; } = GridSelectionMode.Single; /// /// Settings is for grid to render. - /// The provider should always return an instance of 'GridSettings', and 'null' is not allowed. + /// The provider should always return an instance of , and is not allowed. + /// + /// Default value is . + /// /// - /// - /// Default value is null. - /// + [AddedVersion("1.0.0")] + [DefaultValue(null)] + [Description("Settings is for grid to render. The provider should always return an instance of GridSettings, and null is not allowed.")] [Parameter] - public GridSettingsProviderDelegate SettingsProvider { get; set; } = default!; + public GridSettingsProviderDelegate? SettingsProvider { get; set; } /// /// Gets or sets the thead css class. + /// + /// Default value is . + /// /// - /// - /// Default value is null. - /// + [AddedVersion("1.10.3")] + [DefaultValue(null)] + [Description("Gets or sets the thead css class.")] [Parameter] public string? THeadCssClass { get; set; } @@ -910,10 +1201,13 @@ private void SetFilters(IEnumerable filterItems) /// /// Gets or sets the units. - /// - /// + /// /// Default value is . - /// + /// + /// + [AddedVersion("1.10.3")] + [DefaultValue(null)] + [Description("Gets or sets the units.")] [Parameter] public Unit Unit { get; set; } = Unit.Px; diff --git a/blazorbootstrap/Components/Grid/GridColumn.razor.cs b/blazorbootstrap/Components/Grid/GridColumn.razor.cs index 236de2651..3c15c53ec 100644 --- a/blazorbootstrap/Components/Grid/GridColumn.razor.cs +++ b/blazorbootstrap/Components/Grid/GridColumn.razor.cs @@ -14,6 +14,8 @@ public partial class GridColumn : BlazorBootstrapComponentBase private string filterValue = default!; + private bool isVisible = true; + private RenderFragment? headerTemplate; #endregion @@ -25,7 +27,7 @@ protected override async Task OnInitializedAsync() Id = IdUtility.GetNextId(); // Required filterOperator = FilterOperator; - filterValue = FilterValue; + filterValue = FilterValue!; currentSortDirection = SortDirection; defaultSortDirection = SortDirection; @@ -46,16 +48,16 @@ protected override async Task OnInitializedAsync() internal string GetFilterValue() => filterValue; - internal Type GetPropertyType() => typeof(TItem).GetPropertyType(PropertyName)!; + internal Type GetPropertyType() => typeof(TItem).GetPropertyType(PropertyName!)!; - internal string GetPropertyTypeName() => typeof(TItem).GetPropertyTypeName(PropertyName); + internal string GetPropertyTypeName() => typeof(TItem).GetPropertyTypeName(PropertyName!); internal IEnumerable> GetSorting() { if (SortKeySelector == null && string.IsNullOrWhiteSpace(SortString)) yield break; - yield return new SortingItem(SortString, SortKeySelector!, currentSortDirection); + yield return new SortingItem(SortString!, SortKeySelector!, currentSortDirection); } internal async Task OnFilterChangedAsync(FilterEventArgs args, GridColumn column) @@ -109,6 +111,11 @@ or StringConstants.PropertyTypeNameDecimal if (filterOperator == FilterOperator.None) FilterOperator = filterOperator = FilterOperator.Equals; } + if (isVisible != IsVisible) + { + isVisible = IsVisible; + Parent?.ColumnVisibilityUpdated(); + } } internal void SetFilterOperator(FilterOperator filterOperator) => FilterOperator = this.filterOperator = filterOperator; @@ -189,125 +196,180 @@ private async Task OnSortClickAsync() /// /// Specifies the content to be rendered inside the grid column. + /// + /// Default value is . + /// /// - /// - /// Default value is null. - /// + [AddedVersion("1.0.0")] + [DefaultValue(null)] + [Description("Specifies the content to be rendered inside the grid column.")] + [EditorRequired] [Parameter] - public RenderFragment ChildContent { get; set; } = default!; + public RenderFragment? ChildContent { get; set; } /// /// Gets or sets the column class. + /// + /// Default value is . + /// /// + [AddedVersion("1.6.0")] + [DefaultValue(null)] + [Description("Gets or sets the column class.")] [Parameter] public Func? ColumnClass { get; set; } /// /// If , filter is enabled. /// The filter is enabled or disabled based on the grid `AllowFiltering` parameter. + /// + /// Default value is . + /// /// - /// - /// Default value is true. - /// + [AddedVersion("1.0.0")] + [DefaultValue(true)] + [Description("If true, filter is enabled. The filter is enabled or disabled based on the grid AllowFiltering parameter.")] [Parameter] public bool Filterable { get; set; } = true; /// /// Gets or sets the filter button color. - /// - /// + /// /// Default value is . - /// + /// + /// + [AddedVersion("3.0.0")] + [DefaultValue(ButtonColor.Light)] + [Description("Gets or sets the filter button color.")] [Parameter] public ButtonColor FilterButtonColor { get; set; } = ButtonColor.Light; /// /// Gets or sets the filter button CSS class. + /// + /// Default value is . + /// /// - /// - /// Default value is null. - /// + [AddedVersion("3.0.0")] + [DefaultValue(null)] + [Description("Gets or sets the filter button CSS class.")] [Parameter] public string? FilterButtonCSSClass { get; set; } /// /// Gets or sets the filter operator. - /// - /// + /// /// Default value is . - /// + /// + /// + [AddedVersion("1.0.0")] + [DefaultValue(FilterOperator.None)] + [Description("Gets or sets the filter operator.")] [Parameter] public FilterOperator FilterOperator { get; set; } = FilterOperator.None; /// /// Gets or sets the filter textbox width in pixels. - /// - /// + /// /// Default value is 0. - /// + /// + /// + [AddedVersion("1.0.0")] + [DefaultValue(0)] + [Description("Gets or sets the filter textbox width in pixels.")] [Parameter] public int FilterTextboxWidth { get; set; } + /// + /// Gets or sets the filter textbox width units. + /// + /// Default value is . + /// + /// + [AddedVersion("1.0.0")] + [DefaultValue(Unit.Px)] + [Description("Gets or sets the filter textbox width units.")] + [Parameter] + public Unit FilterTextboxWidthUnit { get; set; } = Unit.Px; + /// /// Gets or sets the filter value. + /// + /// Default value is . + /// /// - /// - /// Default value is null. - /// + [AddedVersion("1.0.0")] + [DefaultValue(null)] + [Description("Gets or sets the filter value.")] [Parameter] - public string FilterValue { get; set; } = default!; + public string? FilterValue { get; set; } /// /// Indicates whether the column is frozen. + /// + /// Default value is . + /// /// - /// - /// Default value is false. - /// + [AddedVersion("1.10.4")] + [DefaultValue(false)] + [Description("Indicates whether the column is frozen.")] [Parameter] public bool Freeze { get; set; } /// /// Gets or sets the freeze direction of the column. - /// - /// + /// /// Default value is . - /// + /// + /// + [AddedVersion("1.10.4")] + [DefaultValue(FreezeDirection.Left)] + [Description("Gets or sets the freeze direction of the column.")] [Parameter] public FreezeDirection FreezeDirection { get; set; } = FreezeDirection.Left; /// /// Gets or sets the horizontal position of the column from left. It has no effect on non-positioned columns. - /// - /// + /// /// Default value is 0. - /// + /// + /// + [AddedVersion("1.10.4")] + [DefaultValue(0)] + [Description("Gets or sets the horizontal position of the column from left. It has no effect on non-positioned columns.")] [Parameter] public double FreezeLeftPosition { get; set; } /// /// Gets or sets the horizontal position of the column from right. It has no effect on non-positioned columns. - /// - /// + /// /// Default value is 0. - /// + /// + /// + [AddedVersion("1.10.4")] + [DefaultValue(0)] + [Description("Gets or sets the horizontal position of the column from right. It has no effect on non-positioned columns.")] [Parameter] public double FreezeRightPosition { get; set; } /// /// Gets or sets the header content. /// - /// - /// Default value is null. - /// + /// + /// Default value is . + /// + [AddedVersion("1.7.3")] + [DefaultValue(null)] + [Description("Gets or sets the header content.")] [Parameter] - public RenderFragment HeaderContent { get; set; } = default!; + public RenderFragment? HeaderContent { get; set; } /// /// Gets or sets the header template. /// - /// + /// /// Default value is null. - /// + /// internal RenderFragment HeaderTemplate => headerTemplate ??= builder => { @@ -386,30 +448,51 @@ private async Task OnSortClickAsync() /// /// Gets or sets the table column header text. + /// + /// Default value is . + /// /// - /// - /// Default value is null. - /// + [AddedVersion("1.0.0")] + [DefaultValue(null)] + [Description("Gets or sets the table column header text.")] [Parameter] - public string HeaderText { get; set; } = default!; + public string? HeaderText { get; set; } /// /// Gets or sets the header text alignment. - /// - /// + /// /// Default value is . - /// + /// + /// + [AddedVersion("1.0.0")] + [DefaultValue(Alignment.Start)] + [Description("Gets or sets the header text alignment.")] [Parameter] public Alignment HeaderTextAlignment { get; set; } = Alignment.Start; /// /// Gets or sets the default sort column. + /// + /// Default value is . + /// /// - /// - /// Default value is false. - /// + [AddedVersion("1.0.0")] + [DefaultValue(false)] + [Description("Gets or sets the default sort column.")] [Parameter] - public bool IsDefaultSortColumn { get; set; } = false; + public bool IsDefaultSortColumn { get; set; } + + /// + /// Gets or sets visibility of the Grid column. + /// + /// Default value is . + /// + /// + [AddedVersion("3.4.0")] + [DefaultValue(true)] + [Description("Gets or sets visibility of the Grid column.")] + [Parameter] + public bool IsVisible { get; set; } = true; [CascadingParameter(Name = "Parent")] public Grid Parent { get; set; } = default!; @@ -417,73 +500,138 @@ private async Task OnSortClickAsync() /// /// Gets or sets the property name. /// This is required when `AllowFiltering` is true. + /// + /// Default value is . + /// /// - /// - /// Default value is null. - /// + [AddedVersion("1.0.0")] + [DefaultValue(null)] + [Description("Gets or sets the property name. This is required when AllowFiltering is true.")] [Parameter] - public string PropertyName { get; set; } = default!; + public string? PropertyName { get; set; } /// /// Enable or disable the sorting on a specific column. /// The sorting is enabled or disabled based on the `AllowSorting` parameter on the grid. + /// + /// Default value is . + /// /// - /// - /// Default value is true. - /// + [AddedVersion("1.0.0")] + [DefaultValue(true)] + [Description("Enable or disable the sorting on a specific column. The sorting is enabled or disabled based on the AllowSorting parameter on the grid.")] [Parameter] public bool Sortable { get; set; } = true; /// /// Gets or sets the default sort direction of a column. - /// - /// + /// /// Default value is . - /// + /// + /// + [AddedVersion("1.0.0")] + [DefaultValue(SortDirection.None)] + [Description("Gets or sets the default sort direction of a column.")] [Parameter] public SortDirection SortDirection { get; set; } = SortDirection.None; /// /// Expression used for sorting. + /// + /// Default value is . + /// /// + [AddedVersion("1.0.0")] + [DefaultValue(null)] + [Description("Expression used for sorting.")] [Parameter] - public Expression> SortKeySelector { get; set; } = default!; + public Expression>? SortKeySelector { get; set; } /// /// Gets or sets the column sort string. /// This value will be passed to the backend/API for sorting. /// And this property is ignored for the client-side sorting. + /// + /// Default value is . + /// /// - /// - /// Default value is null. - /// + [AddedVersion("1.0.0")] + [DefaultValue(null)] + [Description("Gets or sets the column sort string. This value will be passed to the backend/API for sorting. And this property is ignored for the client-side sorting.")] [Parameter] - public string SortString { get; set; } = default!; + public string? SortString { get; set; } /// /// Gets or sets the StringComparison. - /// - /// + /// /// Default value is . - /// + /// + /// + [AddedVersion("1.0.0")] + [DefaultValue(StringComparison.OrdinalIgnoreCase)] + [Description("Gets or sets the StringComparison.")] [Parameter] public StringComparison StringComparison { get; set; } = StringComparison.OrdinalIgnoreCase; /// - /// Gets or sets the text alignment. + /// Gets or sets the summary column type. + /// + /// Default value is . + /// /// - /// + [AddedVersion("3.4.0")] + [DefaultValue(GridSummaryColumnType.None)] + [Description("Gets or sets the summary column type.")] + [Parameter] + public GridSummaryColumnType SummaryType { get; set; } = GridSummaryColumnType.None; + + /// + /// Gets or sets the summary value display format. + /// + /// Default value is . + /// + /// + [AddedVersion("3.4.0")] + [DefaultValue(null)] + [Description("Gets or sets the summary value display format.")] + [Parameter] + public string? SummaryValueDisplayFormat { get; set; } + + /// + /// Gets or sets the summary value prefix. If set, it will be displayed before the summary value. + /// Otherwise, based on the , default prefix will be displayed. + /// To remove the default prefix, set this property to an empty string. + /// + /// Example: "Total: ", "Average: ", etc. + /// + /// + [AddedVersion("3.4.0")] + [DefaultValue(null)] + [Description("Gets or sets the summary value prefix. If set, it will be displayed before the summary value. Otherwise, based on the SummaryType, default prefix will be displayed. To remove the default prefix, set this property to an empty string.")] + [Parameter] + public string? SummaryValuePrefix { get; set; } + + /// + /// Gets or sets the text alignment. + /// /// Default value is . - /// + /// + /// + [AddedVersion("1.0.0")] + [DefaultValue(Alignment.Start)] + [Description("Gets or sets the text alignment.")] [Parameter] public Alignment TextAlignment { get; set; } = Alignment.Start; /// /// Gets or sets text nowrap. + /// + /// Default value is . + /// /// - /// - /// Default value is false. - /// + [AddedVersion("1.0.0")] + [DefaultValue(false)] + [Description("Gets or sets text nowrap.")] [Parameter] public bool TextNoWrap { get; set; } diff --git a/blazorbootstrap/Components/Grid/GridColumnFilter.razor b/blazorbootstrap/Components/Grid/GridColumnFilter.razor index 4321a1811..22bc06a88 100644 --- a/blazorbootstrap/Components/Grid/GridColumnFilter.razor +++ b/blazorbootstrap/Components/Grid/GridColumnFilter.razor @@ -31,28 +31,7 @@ } - @if (PropertyTypeName == StringConstants.PropertyTypeNameInt16 - || PropertyTypeName == StringConstants.PropertyTypeNameInt32 - || PropertyTypeName == StringConstants.PropertyTypeNameInt64 - || PropertyTypeName == StringConstants.PropertyTypeNameSingle // float - || PropertyTypeName == StringConstants.PropertyTypeNameDecimal - || PropertyTypeName == StringConstants.PropertyTypeNameDouble) - { - - } - else if (PropertyTypeName == StringConstants.PropertyTypeNameDateOnly) - { - - } - else if (PropertyTypeName == StringConstants.PropertyTypeNameDateTime) - { - - } - else if (PropertyTypeName == StringConstants.PropertyTypeNameBoolean) - { - - } - else if (PropertyTypeName == StringConstants.PropertyTypeNameEnum) + @if (PropertyTypeName == StringConstants.PropertyTypeNameEnum) { @@ -62,7 +41,7 @@ } else { - @filterValue + @(PropertyType!.GetDisplayName(filterValue)) } @@ -70,14 +49,15 @@ { @foreach (var item in Enum.GetValues(PropertyType!)) { - @item + var name = PropertyType!.GetDisplayName(Enum.GetName(PropertyType!, item)); + @name } } } - else // guid or string + else { - + @InputFilterTemplate } diff --git a/blazorbootstrap/Components/Grid/GridColumnFilter.razor.cs b/blazorbootstrap/Components/Grid/GridColumnFilter.razor.cs index d43af52b2..a15036adc 100644 --- a/blazorbootstrap/Components/Grid/GridColumnFilter.razor.cs +++ b/blazorbootstrap/Components/Grid/GridColumnFilter.razor.cs @@ -72,6 +72,62 @@ or StringConstants.PropertyTypeNameDecimal } } + private RenderFragment InputFilterTemplate => builder => + { + string inputType; + string inputClass; + + switch (PropertyTypeName) + { + case StringConstants.PropertyTypeNameInt16: + case StringConstants.PropertyTypeNameInt32: + case StringConstants.PropertyTypeNameInt64: + case StringConstants.PropertyTypeNameSingle: + case StringConstants.PropertyTypeNameDecimal: + case StringConstants.PropertyTypeNameDouble: + inputType = "number"; + inputClass = "form-control"; + break; + case StringConstants.PropertyTypeNameDateOnly: + inputType = "date"; + inputClass = "form-control"; + break; + case StringConstants.PropertyTypeNameDateTime: + inputType = "datetime-local"; + inputClass = "form-control"; + break; + case StringConstants.PropertyTypeNameBoolean: + inputType = "checkbox"; + inputClass = "form-check-input"; + break; + default: + inputType = "text"; + inputClass = "form-control"; + break; + } + + builder.OpenElement(100, "input"); + builder.AddAttribute(101, "class", inputClass); + + builder.AddAttribute(102, "type", inputType); + builder.AddAttribute(103, "value", filterValue); + + if (PropertyTypeName == StringConstants.PropertyTypeNameBoolean) + { + if ((bool.TryParse(filterValue, out bool isChecked)) && isChecked) + builder.AddAttribute(104, "checked", "checked"); + + builder.AddAttribute(106, "onchange", async (ChangeEventArgs args) => await OnFilterValueChangedAsync(args)); + } + else + { + builder.AddAttribute(105, "style", filterStyle); + builder.AddAttribute(106, "oninput", async (ChangeEventArgs args) => await OnFilterValueChangedAsync(args)); + } + + builder.CloseElement(); + }; + private async Task> GetFilterOperatorsAsync(string propertyTypeName) { if (FiltersTranslationProvider is null) @@ -153,18 +209,18 @@ or StringConstants.PropertyTypeNameDecimal /// /// Gets or sets the filter button color. /// - /// + /// /// Default value is . - /// + /// [Parameter] public ButtonColor FilterButtonColor { get; set; } = ButtonColor.Light; /// /// Gets or sets the filter button CSS class. /// - /// + /// /// Default value is null. - /// + /// [Parameter] public string? FilterButtonCSSClass { get; set; } @@ -183,14 +239,14 @@ or StringConstants.PropertyTypeNameDecimal [Parameter] public GridFiltersTranslationDelegate FiltersTranslationProvider { get; set; } = default!; - private string filterStyle => FilterWidth > 0 ? $"width:{FilterWidth.ToString(CultureInfo.InvariantCulture)}{Unit.ToString().ToLower()};" : ""; + private string filterStyle => FilterWidth > 0 ? $"width:{FilterWidth.ToString(CultureInfo.InvariantCulture)}{Unit.ToCssString()};" : ""; /// /// Gets or sets filter value. /// - /// + /// /// Default value is null. - /// + /// [Parameter] public string? FilterValue { get; set; } @@ -217,9 +273,9 @@ or StringConstants.PropertyTypeNameDecimal /// /// Gets or sets the filter property name. /// - /// + /// /// Default value is null. - /// + /// [Parameter] public string? PropertyTypeName { get; set; } diff --git a/blazorbootstrap/Components/Grid/GridColumns.razor.cs b/blazorbootstrap/Components/Grid/GridColumns.razor.cs index 09a263a7f..339b6b3ad 100644 --- a/blazorbootstrap/Components/Grid/GridColumns.razor.cs +++ b/blazorbootstrap/Components/Grid/GridColumns.razor.cs @@ -4,10 +4,12 @@ public partial class GridColumns : BlazorBootstrapComponentBase { /// /// Specifies the content to be rendered inside the grid columns component. + /// + /// Default value is . + /// /// - /// - /// Default value is null. - /// + [AddedVersion("1.0.0")] + [Description("Specifies the content to be rendered inside the grid columns component.")] [Parameter] - public RenderFragment? ChildContent { get; set; } = default!; + public RenderFragment? ChildContent { get; set; } } diff --git a/blazorbootstrap/Components/Grid/GridDetailView.razor.cs b/blazorbootstrap/Components/Grid/GridDetailView.razor.cs index 88a761bbd..ada06434b 100644 --- a/blazorbootstrap/Components/Grid/GridDetailView.razor.cs +++ b/blazorbootstrap/Components/Grid/GridDetailView.razor.cs @@ -16,12 +16,15 @@ protected override async Task OnInitializedAsync() /// /// Specifies the content to be rendered inside the component. + /// + /// Default value is . + /// /// - /// - /// Default value is null. - /// + [AddedVersion("1.0.0")] + [DefaultValue(null)] + [Description("Specifies the content to be rendered inside the component.")] [Parameter] - public RenderFragment ChildContent { get; set; } = default!; + public RenderFragment? ChildContent { get; set; } internal RenderFragment GetTemplate => gridDetailViewTemplate ??= rowData => builder => diff --git a/blazorbootstrap/Components/Grid/GridEmptyDataTemplate.razor.cs b/blazorbootstrap/Components/Grid/GridEmptyDataTemplate.razor.cs index 81ea04f3c..73af4910a 100644 --- a/blazorbootstrap/Components/Grid/GridEmptyDataTemplate.razor.cs +++ b/blazorbootstrap/Components/Grid/GridEmptyDataTemplate.razor.cs @@ -16,12 +16,15 @@ protected override async Task OnInitializedAsync() /// /// Specifies the content to be rendered inside the component. + /// + /// Default value is . + /// /// - /// - /// Default value is null. - /// + [AddedVersion("1.0.0")] + [DefaultValue(null)] + [Description("Specifies the content to be rendered inside the component.")] [Parameter] - public RenderFragment ChildContent { get; set; } = default!; + public RenderFragment? ChildContent { get; set; } internal RenderFragment Template => template ??= builder => diff --git a/blazorbootstrap/Components/Grid/GridLoadingTemplate.razor.cs b/blazorbootstrap/Components/Grid/GridLoadingTemplate.razor.cs index 51ac498cd..71adc4a78 100644 --- a/blazorbootstrap/Components/Grid/GridLoadingTemplate.razor.cs +++ b/blazorbootstrap/Components/Grid/GridLoadingTemplate.razor.cs @@ -16,12 +16,15 @@ protected override async Task OnInitializedAsync() /// /// Specifies the content to be rendered inside the component. + /// + /// Default value is . + /// /// - /// - /// Default value is null. - /// + [AddedVersion("1.0.0")] + [DefaultValue(null)] + [Description("Specifies the content to be rendered inside the component.")] [Parameter] - public RenderFragment ChildContent { get; set; } = default!; + public RenderFragment? ChildContent { get; set; } internal RenderFragment Template => template ??= builder => diff --git a/blazorbootstrap/Components/Grid/GridTemplates.razor.cs b/blazorbootstrap/Components/Grid/GridTemplates.razor.cs index 9b1b112ea..3f4e2242f 100644 --- a/blazorbootstrap/Components/Grid/GridTemplates.razor.cs +++ b/blazorbootstrap/Components/Grid/GridTemplates.razor.cs @@ -4,10 +4,14 @@ public partial class GridTemplates : BlazorBootstrapComponentBase { /// /// Specifies the content to be rendered inside the grid templates component. + /// + /// Default value is . + /// /// - /// - /// Default value is null. - /// + [AddedVersion("1.0.0")] + [DefaultValue(null)] + [Description("Specifies the content to be rendered inside the grid templates component.")] + [EditorRequired] [Parameter] - public RenderFragment? ChildContent { get; set; } = default!; + public RenderFragment? ChildContent { get; set; } } diff --git a/blazorbootstrap/Components/Icon/Icon.razor.cs b/blazorbootstrap/Components/Icon/Icon.razor.cs index 98e095140..47a59230a 100644 --- a/blazorbootstrap/Components/Icon/Icon.razor.cs +++ b/blazorbootstrap/Components/Icon/Icon.razor.cs @@ -14,38 +14,50 @@ public partial class Icon : BlazorBootstrapComponentBase /// /// Gets or sets the icon color. - /// - /// + /// /// Default value is . - /// + /// + /// + [AddedVersion("1.9.0")] + [DefaultValue(IconColor.None)] + [Description("Gets or sets the icon color.")] [Parameter] public IconColor Color { get; set; } = IconColor.None; /// /// Gets or sets the custom icon name. /// Specify custom icons of your own, like `fontawesome`. Example: `fas fa-alarm-clock`. + /// + /// Default value is . + /// /// - /// - /// Default value is null. - /// + [AddedVersion("1.0.0")] + [DefaultValue(null)] + [Description("Gets or sets the custom icon name. Specify custom icons of your own, like `fontawesome`. Example: `fas fa-alarm-clock`.")] [Parameter] public string? CustomIconName { get; set; } /// /// Gets or sets the icon name. - /// - /// + /// /// Default value is . - /// + /// + /// + [AddedVersion("1.0.0")] + [DefaultValue(IconName.None)] + [Description("Gets or sets the icon name.")] [Parameter] public IconName Name { get; set; } = IconName.None; /// /// Gets or sets the icon size. - /// - /// + /// /// Default value is . - /// + /// + /// + [AddedVersion("1.0.0")] + [DefaultValue(IconSize.None)] + [Description("Gets or sets the icon size.")] [Parameter] public IconSize Size { get; set; } = IconSize.None; diff --git a/blazorbootstrap/Components/Image/Image.razor.cs b/blazorbootstrap/Components/Image/Image.razor.cs index c02d7d87e..c8490dbf6 100644 --- a/blazorbootstrap/Components/Image/Image.razor.cs +++ b/blazorbootstrap/Components/Image/Image.razor.cs @@ -11,37 +11,49 @@ public partial class Image: BlazorBootstrapComponentBase /// /// Gets or sets the alternate text for the image. + /// + /// Default value is . + /// /// - /// - /// Default value is null. - /// + [AddedVersion("3.0.0")] + [DefaultValue(null)] + [Description("Gets or sets the alternate text for the image.")] [Parameter] public string? Alt { get; set; } /// /// Gets or sets the source of the image. + /// + /// Default value is . + /// /// - /// - /// Default value is null. - /// + [AddedVersion("3.0.0")] + [DefaultValue(null)] + [Description("Gets or sets the source of the image.")] [Parameter] public string? Src { get; set; } /// /// Gets or sets a value indicating whether the image is responsive. - /// - /// + /// /// Default value is . - /// + /// + /// + [AddedVersion("3.0.0")] + [DefaultValue(true)] + [Description("Gets or sets a value indicating whether the image is responsive.")] [Parameter] public bool IsResponsive { get; set; } = true; /// /// Makes the image have a rounded 1px border appearance if set to . - /// - /// + /// /// Default value is . - /// + /// + /// + [AddedVersion("3.0.0")] + [DefaultValue(false)] + [Description("Makes the image have a rounded 1px border appearance if set to true.")] [Parameter] public bool IsThumbnail { get; set; } diff --git a/blazorbootstrap/Components/Layout/BlazorBootstrapLayout.razor.cs b/blazorbootstrap/Components/Layout/BlazorBootstrapLayout.razor.cs index 7d2abbc16..c5783eea7 100644 --- a/blazorbootstrap/Components/Layout/BlazorBootstrapLayout.razor.cs +++ b/blazorbootstrap/Components/Layout/BlazorBootstrapLayout.razor.cs @@ -6,16 +6,81 @@ public partial class BlazorBootstrapLayout : BlazorBootstrapLayoutComponentBase protected override string? ClassNames => BuildClassNames(Class, ("bb-page", true)); - [Parameter] public RenderFragment? ContentSection { get; set; } - [Parameter] public string? ContentSectionCssClass { get; set; } + /// + /// Gets or sets the content section. + /// + /// Default value is . + /// + /// + [AddedVersion("3.2.0")] + [DefaultValue(null)] + [Description("Gets or sets the content section.")] + [Parameter] + public RenderFragment? ContentSection { get; set; } + + /// + /// Gets or sets the CSS class for content section. + /// + /// Default value is . + /// + /// + [AddedVersion("3.2.0")] + [DefaultValue(null)] + [Description("Gets or sets the CSS class for content section.")] + [Parameter] + public string? ContentSectionCssClass { get; set; } + protected string? ContentSectionCssClassNames => BuildClassNames(ContentSectionCssClass, ("p-4", true)); - [Parameter] public RenderFragment? FooterSection { get; set; } - [Parameter] public string? FooterSectionCssClass { get; set; } = "bg-body-tertiary"; + /// + /// Gets or sets the footer section. + /// + /// Default value is . + /// + /// + [AddedVersion("3.2.0")] + [DefaultValue(null)] + [Description("Gets or sets the footer section.")] + [Parameter] + public RenderFragment? FooterSection { get; set; } + + /// + /// Gets or sets the CSS class applied to the footer section of the component. + /// + /// Default value is . + /// + /// + [AddedVersion("3.2.0")] + [DefaultValue("bg-body-tertiary")] + [Description("Gets or sets the CSS class applied to the footer section of the component.")] + [Parameter] + public string FooterSectionCssClass { get; set; } = "bg-body-tertiary"; + protected string? FooterSectionCssClassNames => BuildClassNames(FooterSectionCssClass, ("bb-footer p-4", true)); - [Parameter] public RenderFragment? HeaderSection { get; set; } - [Parameter] public string? HeaderSectionCssClass { get; set; } = "d-flex justify-content-end"; + /// + /// Gets or sets the header section. + /// + /// Default value is . + /// + /// + [AddedVersion("3.2.0")] + [DefaultValue(null)] + [Description("Gets or sets the header section.")] + [Parameter] + public RenderFragment? HeaderSection { get; set; } + + /// + /// Gets or sets the CSS class applied to the header section of the component. + /// + /// Default value is . + /// + /// + [AddedVersion("3.2.0")] + [DefaultValue("d-flex justify-content-end")] + [Description("Gets or sets the CSS class applied to the header section of the component.")] + [Parameter] + public string HeaderSectionCssClass { get; set; } = "d-flex justify-content-end"; protected string? HeaderSectionCssClassNames => BuildClassNames( @@ -25,9 +90,29 @@ public partial class BlazorBootstrapLayout : BlazorBootstrapLayoutComponentBase ("px-4", true) ); - [Parameter] public bool StickyHeader { get; set; } + /// + /// Gets or sets a value indicating whether the header section is sticky. + /// + /// Default value is . + /// + /// + [AddedVersion("3.2.0")] + [DefaultValue(false)] + [Description("Gets or sets a value indicating whether the header section is sticky.")] + [Parameter] + public bool StickyHeader { get; set; } - [Parameter] public RenderFragment? SidebarSection { get; set; } + /// + /// Gets or sets the sidebar section. + /// + /// Default value is . + /// + /// + [AddedVersion("3.2.0")] + [DefaultValue(null)] + [Description("Gets or sets the sidebar section.")] + [Parameter] + public RenderFragment? SidebarSection { get; set; } #endregion } diff --git a/blazorbootstrap/Components/Maps/GoogleMap.razor b/blazorbootstrap/Components/Maps/GoogleMap.razor index f61c6d7e3..cc8b42c9b 100644 --- a/blazorbootstrap/Components/Maps/GoogleMap.razor +++ b/blazorbootstrap/Components/Maps/GoogleMap.razor @@ -4,9 +4,8 @@ + ScriptId="blazor-bootstrap-google-maps-script" + Source="@GoogleMapsJsFileUrl" />
    diff --git a/blazorbootstrap/Components/Maps/GoogleMap.razor.cs b/blazorbootstrap/Components/Maps/GoogleMap.razor.cs index 90613c4b5..91382bf3e 100644 --- a/blazorbootstrap/Components/Maps/GoogleMap.razor.cs +++ b/blazorbootstrap/Components/Maps/GoogleMap.razor.cs @@ -10,6 +10,14 @@ public partial class GoogleMap : BlazorBootstrapComponentBase #region Methods + protected override async Task OnAfterRenderAsync(bool firstRender) + { + if (firstRender) + await SafeInvokeVoidAsync("window.blazorBootstrap.googlemaps.initialize", Id, Zoom, Center, Markers, Clickable, objRef); + + await base.OnAfterRenderAsync(firstRender); + } + protected override async Task OnInitializedAsync() { objRef ??= DotNetObjectReference.Create(this); @@ -22,9 +30,11 @@ protected override async Task OnInitializedAsync() /// /// The marker to add to the map. /// A completed task. + [AddedVersion("3.0.0")] + [Description("Adds a marker to the GoogleMap.")] public ValueTask AddMarkerAsync(GoogleMapMarker marker) { - JSRuntime.InvokeVoidAsync("window.blazorBootstrap.googlemaps.addMarker", Id, marker, objRef); + _ = SafeInvokeVoidAsync("window.blazorBootstrap.googlemaps.addMarker", Id, marker, objRef); return ValueTask.CompletedTask; } @@ -40,9 +50,11 @@ public async Task OnMarkerClickJS(GoogleMapMarker marker) /// Refreshes the Google Map component. /// /// A completed task. + [AddedVersion("3.0.0")] + [Description("Refreshes the Google Map component.")] public ValueTask RefreshAsync() { - JSRuntime.InvokeVoidAsync("window.blazorBootstrap.googlemaps.initialize", Id, Zoom, Center, Markers, Clickable, objRef); + _ = SafeInvokeVoidAsync("window.blazorBootstrap.googlemaps.initialize", Id, Zoom, Center, Markers, Clickable, objRef); return ValueTask.CompletedTask; } @@ -51,18 +63,15 @@ public ValueTask RefreshAsync() /// Updates the markers on the Google Map. /// /// A completed task. + [AddedVersion("3.0.0")] + [Description("Updates the markers on the Google Map.")] public ValueTask UpdateMarkersAsync(IEnumerable markers) { - JSRuntime.InvokeVoidAsync("window.blazorBootstrap.googlemaps.updateMarkers", Id, markers, objRef); + _ = SafeInvokeVoidAsync("window.blazorBootstrap.googlemaps.updateMarkers", Id, markers, objRef); return ValueTask.CompletedTask; } - private void OnScriptLoad() - { - Task.Run(async () => await JSRuntime.InvokeVoidAsync("window.blazorBootstrap.googlemaps.initialize", Id, Zoom, Center, Markers, Clickable, objRef)); - } - #endregion #region Properties, Indexers @@ -76,45 +85,75 @@ private void OnScriptLoad() /// /// Gets or sets the Google Map API key. + /// + /// Default value is . + /// /// + [AddedVersion("3.0.0")] + [DefaultValue(null)] + [Description("Gets or sets the Google Map API key.")] [Parameter] public string? ApiKey { get; set; } /// /// Gets or sets the center parameter. + /// + /// Default value is . + /// /// + [AddedVersion("3.0.0")] + [DefaultValue(null)] + [Description("Gets or sets the center parameter.")] [Parameter] - public GoogleMapCenter Center { get; set; } = default!; + public GoogleMapCenter? Center { get; set; } /// /// Makes the marker clickable if set to . + /// + /// Default value is . + /// /// + [AddedVersion("3.0.0")] + [DefaultValue(false)] + [Description("Makes the marker clickable if set to true.")] [Parameter] public bool Clickable { get; set; } - private string? GoogleMapsJsFileUrl => $"https://maps.googleapis.com/maps/api/js?key={ApiKey}&libraries=maps,marker"; + private string? GoogleMapsJsFileUrl => $"https://maps.googleapis.com/maps/api/js?key={ApiKey}&libraries=maps,marker&loading=async&callback=blazorBootstrap.googlemaps.onApiLoaded"; /// /// Gets or sets the height of the . - /// - /// + /// /// Default value is . - /// + /// + /// + [AddedVersion("3.0.0")] + [DefaultValue(null)] + [Description("Gets or sets the height of the GoogleMap.")] [Parameter] public double? Height { get; set; } /// /// Gets or sets the units for the . - /// - /// + /// /// Default value is . - /// + /// + /// + [AddedVersion("3.0.0")] + [DefaultValue(Unit.Px)] + [Description("Gets or sets the units for the Height.")] [Parameter] public Unit HeightUnit { get; set; } = Unit.Px; /// /// Gets or sets the markers. + /// + /// Default value is . + /// /// + [AddedVersion("3.0.0")] + [DefaultValue(null)] + [Description("Gets or sets the markers.")] [Parameter] public IEnumerable? Markers { get; set; } @@ -122,33 +161,44 @@ private void OnScriptLoad() /// Event fired when a user clicks on a marker. /// This event fires only when is set to . /// + [AddedVersion("3.0.0")] + [Description("Event fired when a user clicks on a marker. This event fires only when Clickable is set to true.")] [Parameter] public EventCallback OnMarkerClick { get; set; } /// /// Gets or sets the width of the . - /// - /// + /// /// Default value is . - /// + /// + /// + [AddedVersion("3.0.0")] + [DefaultValue(null)] + [Description("Gets or sets the width of the GoogleMap.")] [Parameter] public double? Width { get; set; } /// /// Gets or sets the units for the . - /// - /// + /// /// Default value is . - /// + /// + /// + [AddedVersion("3.0.0")] + [DefaultValue(Unit.Percentage)] + [Description("Gets or sets the units for the Width.")] [Parameter] public Unit WidthUnit { get; set; } = Unit.Percentage; /// /// Gets or sets the zoom level of the . - /// - /// + /// /// Default value is 14. - /// + /// + /// + [AddedVersion("3.0.0")] + [DefaultValue(14)] + [Description("Gets or sets the zoom level of the GoogleMap.")] [Parameter] public int Zoom { get; set; } = 14; diff --git a/blazorbootstrap/Components/Markdown/Markdown.razor.cs b/blazorbootstrap/Components/Markdown/Markdown.razor.cs index df8a60c45..4f598f20a 100644 --- a/blazorbootstrap/Components/Markdown/Markdown.razor.cs +++ b/blazorbootstrap/Components/Markdown/Markdown.razor.cs @@ -608,7 +608,7 @@ private List GetLines() inputs.RemoveAt(0); // remove last blank line - if (string.IsNullOrWhiteSpace(inputs[^1])) + if (inputs.Count > 0 && string.IsNullOrWhiteSpace(inputs[^1])) inputs.RemoveAt(inputs.Count - 1); } @@ -678,24 +678,39 @@ private static void RemoveLastLineBreak(List htmlLines) /// /// Gets or sets the CSS class for blockquotes. + /// + /// Default value is "blockquote". + /// /// + [AddedVersion("3.1.0")] + [DefaultValue("blockquote")] + [Description("Gets or sets the CSS class for blockquotes.")] [Parameter] - public string? BlockquotesCssClass { get; set; } = "blockquote"; + public string BlockquotesCssClass { get; set; } = "blockquote"; /// /// Gets or sets the content to be rendered within the component. - /// - /// + /// /// Default value is . - /// + /// + /// + [AddedVersion("3.1.0")] + [DefaultValue(null)] + [Description("Gets or sets the content to be rendered within the component.")] [Parameter] public RenderFragment? ChildContent { get; set; } /// /// Gets or sets the CSS class for table. + /// + /// Default value is "table". + /// /// + [AddedVersion("3.1.0")] + [DefaultValue("table")] + [Description("Gets or sets the CSS class for table.")] [Parameter] - public string? TableCssClass { get; set; } = "table"; + public string TableCssClass { get; set; } = "table"; #endregion } diff --git a/blazorbootstrap/Components/Modals/Modal.razor.cs b/blazorbootstrap/Components/Modals/Modal.razor.cs index d840f81fe..02a81ed37 100644 --- a/blazorbootstrap/Components/Modals/Modal.razor.cs +++ b/blazorbootstrap/Components/Modals/Modal.razor.cs @@ -32,7 +32,7 @@ protected override async ValueTask DisposeAsyncCore(bool disposing) try { if (IsRenderComplete) - await JSRuntime.InvokeVoidAsync("window.blazorBootstrap.modal.dispose", Id); + await SafeInvokeVoidAsync("window.blazorBootstrap.modal.dispose", Id); } catch (JSDisconnectedException) { @@ -51,7 +51,7 @@ protected override async ValueTask DisposeAsyncCore(bool disposing) protected override async Task OnAfterRenderAsync(bool firstRender) { if (firstRender) - await JSRuntime.InvokeVoidAsync("window.blazorBootstrap.modal.initialize", Id, UseStaticBackdrop, CloseOnEscape, objRef); + await SafeInvokeVoidAsync("window.blazorBootstrap.modal.initialize", Id, UseStaticBackdrop, CloseOnEscape, objRef); await base.OnAfterRenderAsync(firstRender); } @@ -90,24 +90,30 @@ public async Task bsHiddenModal() /// /// Hides a modal. /// + [AddedVersion("1.0.0")] + [Description("Hides a modal.")] public async Task HideAsync() { isVisible = false; - await JSRuntime.InvokeVoidAsync("window.blazorBootstrap.modal.hide", Id); + await SafeInvokeVoidAsync("window.blazorBootstrap.modal.hide", Id); } /// /// Opens a modal. /// + [AddedVersion("1.4.1")] + [Description("Opens a modal.")] public async Task ShowAsync() => await ShowAsync(null, null, null, null); /// - /// Opens a modal. + /// Opens a modal. T is component. /// /// /// /// /// + [AddedVersion("1.0.0")] + [Description("Opens a modal. T is component.")] public async Task ShowAsync(string title, string? message = null, Dictionary? parameters = null) => await ShowAsync(title, message, typeof(T), parameters); private Task OnShowAsync(ModalOption modalOption) @@ -150,7 +156,7 @@ private async Task ShowAsync(string? title, string? message, Type? type, Diction await InvokeAsync(StateHasChanged); - await JSRuntime.InvokeVoidAsync("window.blazorBootstrap.modal.show", Id); + await SafeInvokeVoidAsync("window.blazorBootstrap.modal.show", Id); } #endregion @@ -164,84 +170,111 @@ private async Task ShowAsync(string? title, string? message, Type? type, Diction /// /// Gets or sets the body CSS class. + /// + /// Default value is . + /// /// - /// - /// Default value is null. - /// + [AddedVersion("1.0.0")] + [DefaultValue(null)] + [Description("Gets or sets the body CSS class.")] [Parameter] - public string BodyCssClass { get; set; } = default!; + public string? BodyCssClass { get; set; } /// /// Gets or sets the body template. + /// + /// Default value is . + /// /// - /// - /// Default value is null. - /// + [AddedVersion("1.0.0")] + [DefaultValue(null)] + [Description("Gets or sets the body template.")] [Parameter] - public RenderFragment BodyTemplate { get; set; } = default!; + public RenderFragment? BodyTemplate { get; set; } /// /// Gets or sets the close icon color. - /// - /// + /// /// Default value is . - /// + /// + /// + [AddedVersion("1.0.0")] + [DefaultValue(IconColor.None)] + [Description("Gets or sets the close icon color.")] [Parameter] public IconColor CloseIconColor { get; set; } = IconColor.None; /// /// Indicates whether the modal closes when escape key is pressed. + /// + /// Default value is . + /// /// - /// - /// Default value is true. - /// + [AddedVersion("1.0.0")] + [DefaultValue(true)] + [Description("Indicates whether the modal closes when escape key is pressed.")] [Parameter] public bool CloseOnEscape { get; set; } = true; /// /// Gets or sets the modal dialog (div.modal-dialog) CSS class. + /// + /// Default value is . + /// /// - /// - /// Default value is null. - /// + [AddedVersion("1.0.0")] + [DefaultValue(null)] + [Description("Gets or sets the modal dialog (div.modal-dialog) CSS class.")] [Parameter] - public string DialogCssClass { get; set; } = default!; + public string? DialogCssClass { get; set; } /// /// Gets or sets the footer CSS class. + /// + /// Default value is . + /// /// - /// - /// Default value is null. - /// + [AddedVersion("1.0.0")] + [DefaultValue(null)] + [Description("Gets or sets the footer CSS class.")] [Parameter] - public string FooterCssClass { get; set; } = default!; + public string? FooterCssClass { get; set; } /// /// Gets or sets the footer template. + /// + /// Default value is . + /// /// - /// - /// Default value is null. - /// + [AddedVersion("1.0.0")] + [DefaultValue(null)] + [Description("Gets or sets the footer template.")] [Parameter] - public RenderFragment FooterTemplate { get; set; } = default!; + public RenderFragment? FooterTemplate { get; set; } /// /// Gets or sets the fullscreen behavior of the modal. - /// - /// + /// /// Default value is . - /// + /// + /// + [AddedVersion("1.0.0")] + [DefaultValue(ModalFullscreen.Disabled)] + [Description("Gets or sets the fullscreen behavior of the modal.")] [Parameter] public ModalFullscreen Fullscreen { get; set; } = ModalFullscreen.Disabled; /// /// Gets or sets the header CSS class. + /// + /// Default value is . + /// /// - /// - /// Default value is null. - /// + [AddedVersion("1.0.0")] + [DefaultValue(null)] + [Description("Gets or sets the header CSS class.")] [Parameter] - public string HeaderCssClass { get; set; } = default!; + public string? HeaderCssClass { get; set; } // Modal close "X" button with bootstrap 5.3.3 - https://github.com/vikramlearning/blazorbootstrap/issues/714 // Review this fix after bootstrap 5.3.4 or 5.4 release. Ref: https://github.com/twbs/bootstrap/issues/39798 @@ -249,94 +282,121 @@ private async Task ShowAsync(string? title, string? message, Type? type, Diction /// /// Gets or sets the header template. + /// + /// Default value is . + /// /// - /// - /// Default value is null. - /// + [AddedVersion("1.0.0")] + [DefaultValue(null)] + [Description("Gets or sets the header template.")] [Parameter] - public RenderFragment HeaderTemplate { get; set; } = default!; + public RenderFragment? HeaderTemplate { get; set; } /// /// If , scroll will be enabled on the modal body. + /// + /// Default value is . + /// /// - /// - /// Default value is false. - /// + [AddedVersion("1.0.0")] + [DefaultValue(false)] + [Description("If true, scroll will be enabled on the modal body.")] [Parameter] public bool IsScrollable { get; set; } /// /// Indicates whether the modal is related to a modal service or not. + /// + /// Default value is . + /// /// - /// - /// Default value is false. - /// + [AddedVersion("1.9.4")] + [DefaultValue(false)] + [Description("Indicates whether the modal is related to a modal service or not.")] [Parameter] public bool IsServiceModal { get; set; } /// /// If , shows the modal vertically in the center. + /// + /// Default value is . + /// /// - /// - /// Default value is false. - /// + [AddedVersion("1.0.0")] + [DefaultValue(false)] + [Description("If true, shows the modal vertically in the center.")] [Parameter] public bool IsVerticallyCentered { get; set; } /// /// Gets or sets the message. + /// + /// Default value is . + /// /// - /// - /// Default value is null. - /// + [AddedVersion("1.0.0")] + [DefaultValue(null)] + [Description("Gets or sets the message.")] [Parameter] - public string Message { get; set; } = default!; + public string? Message { get; set; } private string modalFullscreen => Fullscreen.ToModalFullscreenClass(); - [Inject] private ModalService ModalService { get; set; } = default!; + [Inject] + private ModalService ModalService { get; set; } = default!; private string modalSize => Size.ToModalSizeClass(); /// /// Gets or sets the modal type. - /// - /// + /// /// Default value is . - /// + /// + /// + [AddedVersion("1.9.5")] + [DefaultValue(ModalType.None)] + [Description("Gets or sets the modal type.")] [Parameter] public ModalType ModalType { get; set; } = ModalType.None; /// - /// This event is fired when an offcanvas element has been hidden from the user (will wait for CSS transitions to - /// complete). + /// This event is fired when an offcanvas element has been hidden from the user (will wait for CSS transitions to complete). /// + [AddedVersion("1.0.0")] + [Description("This event is fired when an offcanvas element has been hidden from the user (will wait for CSS transitions to complete).")] [Parameter] public EventCallback OnHidden { get; set; } /// /// This event is fired when the modal is shown, its backdrop is static and a click outside the modal or an escape key - /// press is performed with the keyboard option or data-bs-keyboard set to false. + /// press is performed with the keyboard option or data-bs-keyboard set to . /// + [AddedVersion("1.0.0")] + [Description("This event is fired when the modal is shown, its backdrop is static and a click outside the modal or an escape key press is performed with the keyboard option or data-bs-keyboard set to false.")] [Parameter] public EventCallback OnHidePrevented { get; set; } /// /// This event is fired immediately when the hide method has been called. /// + [AddedVersion("1.0.0")] + [Description("This event is fired immediately when the hide method has been called.")] [Parameter] public EventCallback OnHiding { get; set; } /// /// This event fires immediately when the show instance method is called. /// + [AddedVersion("1.0.0")] + [Description("This event fires immediately when the show instance method is called.")] [Parameter] public EventCallback OnShowing { get; set; } /// - /// This event is fired when an offcanvas element has been made visible to the user (will wait for CSS transitions to - /// complete). + /// This event is fired when an offcanvas element has been made visible to the user (will wait for CSS transitions to complete). /// + [AddedVersion("1.0.0")] + [Description("This event is fired when an offcanvas element has been made visible to the user (will wait for CSS transitions to complete).")] [Parameter] public EventCallback OnShown { get; set; } @@ -344,43 +404,61 @@ private async Task ShowAsync(string? title, string? message, Type? type, Diction /// /// If , close button will be visible in the modal header. + /// + /// Default value is . + /// /// - /// - /// Default value is true. - /// + [AddedVersion("1.0.0")] + [DefaultValue(true)] + [Description("If true, close button will be visible in the modal header.")] [Parameter] public bool ShowCloseButton { get; set; } = true; /// /// Gets or sets the modal size. - /// - /// + /// /// Default value is . - /// + /// + /// + [AddedVersion("1.0.0")] + [DefaultValue(ModalSize.Regular)] + [Description("Gets or sets the modal size.")] [Parameter] public ModalSize Size { get; set; } = ModalSize.Regular; /// /// Gets or sets the modal tab index. - /// - /// + /// /// Default value is -1. - /// + /// + /// + [AddedVersion("1.6.0")] + [DefaultValue(-1)] + [Description("Gets or sets the modal tab index.")] [Parameter] public int TabIndex { get; set; } = -1; /// /// Gets or sets the modal header title. + /// + /// Default value is . + /// /// + [AddedVersion("1.0.0")] + [DefaultValue(null)] + [Description("Gets or sets the modal header title.")] [Parameter] - public string Title { get; set; } = default!; + public string? Title { get; set; } /// /// Indicates whether the modal uses a static backdrop. + /// + /// Default value is . + /// /// - /// - /// Default value is false. - /// + [AddedVersion("1.0.0")] + [DefaultValue(false)] + [Description("Indicates whether the modal uses a static backdrop.")] [Parameter] public bool UseStaticBackdrop { get; set; } diff --git a/blazorbootstrap/Components/Offcanvas/Offcanvas.razor.cs b/blazorbootstrap/Components/Offcanvas/Offcanvas.razor.cs index 7c3d705c6..f84ebc3c8 100644 --- a/blazorbootstrap/Components/Offcanvas/Offcanvas.razor.cs +++ b/blazorbootstrap/Components/Offcanvas/Offcanvas.razor.cs @@ -6,11 +6,11 @@ public partial class Offcanvas : BlazorBootstrapComponentBase private Type? childComponent; - private DotNetObjectReference objRef = default!; + private DotNetObjectReference? objRef; - private Dictionary parameters = default!; + private Dictionary? parameters; - private string title = default!; + private string? title; #endregion @@ -24,7 +24,7 @@ protected override async ValueTask DisposeAsyncCore(bool disposing) try { if (IsRenderComplete) - await JSRuntime.InvokeVoidAsync("window.blazorBootstrap.offcanvas.dispose", Id); + await SafeInvokeVoidAsync("window.blazorBootstrap.offcanvas.dispose", Id); } catch (JSDisconnectedException) { @@ -40,7 +40,7 @@ protected override async ValueTask DisposeAsyncCore(bool disposing) protected override async Task OnAfterRenderAsync(bool firstRender) { if (firstRender) - await JSRuntime.InvokeVoidAsync("window.blazorBootstrap.offcanvas.initialize", Id, UseStaticBackdrop, CloseOnEscape, IsScrollable, objRef); + await SafeInvokeVoidAsync("window.blazorBootstrap.offcanvas.initialize", Id, UseStaticBackdrop, CloseOnEscape, IsScrollable, objRef); await base.OnAfterRenderAsync(firstRender); } @@ -69,11 +69,15 @@ protected override async Task OnInitializedAsync() /// /// Hides an offcanvas. /// - public async Task HideAsync() => await JSRuntime.InvokeVoidAsync("window.blazorBootstrap.offcanvas.hide", Id); + [AddedVersion("1.0.0")] + [Description("Hides an offcanvas.")] + public async Task HideAsync() => await SafeInvokeVoidAsync("window.blazorBootstrap.offcanvas.hide", Id); /// /// Shows an offcanvas. /// + [AddedVersion("1.0.0")] + [Description("Shows an offcanvas.")] public async Task ShowAsync() => await ShowAsync(null, null, null); /// @@ -82,6 +86,8 @@ protected override async Task OnInitializedAsync() /// /// /// + [AddedVersion("1.0.0")] + [Description("Opens a offcanvas. T is component.")] public async Task ShowAsync(string title, Dictionary? parameters = null) => await ShowAsync(title, typeof(T), parameters); private async Task ShowAsync(string? title, Type? type, Dictionary? parameters) @@ -91,7 +97,7 @@ private async Task ShowAsync(string? title, Type? type, Dictionary /// Gets or sets the body CSS class. + /// + /// Default value is . + /// /// - /// - /// Default value is null. - /// + [AddedVersion("1.0.0")] + [DefaultValue(null)] + [Description("Gets or sets the body CSS class.")] [Parameter] - public string BodyCssClass { get; set; } = default!; + public string? BodyCssClass { get; set; } /// /// Gets or sets the body template. + /// + /// Default value is . + /// /// - /// - /// Default value is null. - /// + [AddedVersion("1.0.0")] + [DefaultValue(null)] + [Description("Gets or sets the body template.")] [Parameter] - public RenderFragment BodyTemplate { get; set; } = default!; + public RenderFragment? BodyTemplate { get; set; } /// /// If , offcanvas closes when escape key is pressed. + /// + /// Default value is . + /// /// - /// - /// Default value is true. - /// + [AddedVersion("1.0.0")] + [DefaultValue(true)] + [Description("If true, offcanvas closes when escape key is pressed.")] [Parameter] public bool CloseOnEscape { get; set; } = true; /// /// Gets or sets the footer CSS class. + /// + /// Default value is . + /// /// - /// - /// Default value is null. - /// + [AddedVersion("1.0.0")] + [DefaultValue(null)] + [Description("Gets or sets the footer CSS class.")] [Parameter] - public string FooterCssClass { get; set; } = default!; + public string? FooterCssClass { get; set; } /// /// Gets or sets the footer template. + /// + /// Default value is . + /// /// - /// - /// Default value is null. - /// + [AddedVersion("1.0.0")] + [DefaultValue(null)] + [Description("Gets or sets the footer template.")] [Parameter] - public RenderFragment FooterTemplate { get; set; } = default!; + public RenderFragment? FooterTemplate { get; set; } /// /// Gets or sets the header CSS class. + /// + /// Default value is . + /// /// - /// - /// Default value is null. - /// + [AddedVersion("1.0.0")] + [DefaultValue(null)] + [Description("Gets or sets the header CSS class.")] [Parameter] - public string HeaderCssClass { get; set; } = default!; + public string? HeaderCssClass { get; set; } /// /// Gets or sets the header template. + /// + /// Default value is . + /// /// - /// - /// Default value is null. - /// + [AddedVersion("1.0.0")] + [DefaultValue(null)] + [Description("Gets or sets the header template.")] [Parameter] - public RenderFragment HeaderTemplate { get; set; } = default!; + public RenderFragment? HeaderTemplate { get; set; } /// /// Indicates whether body scrolling is allowed while offcanvas is open. + /// + /// Default value is . + /// /// - /// - /// Default value is false. - /// + [AddedVersion("1.0.0")] + [DefaultValue(false)] + [Description("Indicates whether body scrolling is allowed while offcanvas is open.")] [Parameter] public bool IsScrollable { get; set; } /// - /// This event is fired when an offcanvas element has been hidden from the user (will wait for CSS transitions to - /// complete). + /// This event is fired when an offcanvas element has been hidden from the user (will wait for CSS transitions to complete). /// + [AddedVersion("1.0.0")] + [Description("This event is fired when an offcanvas element has been hidden from the user (will wait for CSS transitions to complete).")] [Parameter] public EventCallback OnHidden { get; set; } /// /// This event is fired immediately when the hide method has been called. /// + [AddedVersion("1.0.0")] + [Description("This event is fired immediately when the hide method has been called.")] [Parameter] public EventCallback OnHiding { get; set; } /// /// This event fires immediately when the show instance method is called. /// + [AddedVersion("1.0.0")] + [Description("This event fires immediately when the show instance method is called.")] [Parameter] public EventCallback OnShowing { get; set; } /// - /// This event is fired when an offcanvas element has been made visible to the user (will wait for CSS transitions to - /// complete). + /// This event is fired when an offcanvas element has been made visible to the user (will wait for CSS transitions to complete). /// + [AddedVersion("1.0.0")] + [Description("This event is fired when an offcanvas element has been made visible to the user (will wait for CSS transitions to complete).")] [Parameter] public EventCallback OnShown { get; set; } /// /// Gets or sets the offcanvas placement. - /// - /// + /// /// Default value is . - /// + /// + /// + [AddedVersion("1.0.0")] + [DefaultValue(Placement.End)] + [Description("Gets or sets the offcanvas placement.")] [Parameter] public Placement Placement { get; set; } = Placement.End; /// /// If , modal shows close button in the header. + /// + /// Default value is . + /// /// - /// - /// Default value is true. - /// + [AddedVersion("1.0.0")] + [DefaultValue(true)] + [Description("If true, modal shows close button in the header.")] [Parameter] public bool ShowCloseButton { get; set; } = true; /// /// Gets or sets the offcanvas size. - /// - /// + /// /// Default value is . - /// + /// + /// + [AddedVersion("1.0.0")] + [DefaultValue(OffcanvasSize.Regular)] + [Description("Gets or sets the offcanvas size.")] [Parameter] public OffcanvasSize Size { get; set; } = OffcanvasSize.Regular; /// /// Gets or sets the tab index. - /// - /// + /// /// Default value is -1. - /// + /// + /// + [AddedVersion("1.0.0")] + [DefaultValue(-1)] + [Description("Gets or sets the tab index.")] [Parameter] public int TabIndex { get; set; } = -1; /// /// Gets or sets the offcanvas title. + /// + /// Default value is . + /// /// - /// - /// Default value is null. - /// - [Parameter] - public string Title { get; set; } = default!; - - [Obsolete("Use `UseStaticBackdrop` parameter.")] - /// - /// Indicates whether to apply a backdrop on body while offcanvas is open. - /// - /// - /// Default value is true. - /// + [AddedVersion("1.0.0")] + [DefaultValue(null)] + [Description("Gets or sets the offcanvas title.")] [Parameter] - public bool UseBackdrop { get; set; } = true; + public string? Title { get; set; } /// - /// When `UseStaticBackdrop` is set to true, the offcanvas will not close when clicking outside of it. + /// When `UseStaticBackdrop` is set to , the offcanvas will not close when clicking outside of it. + /// + /// Default value is . + /// /// - /// - /// Default value is false. - /// + [AddedVersion("1.0.0")] + [DefaultValue(false)] + [Description("When `UseStaticBackdrop` is set to true, the offcanvas will not close when clicking outside of it.")] [Parameter] public bool UseStaticBackdrop { get; set; } diff --git a/blazorbootstrap/Components/Pagination/Pagination.razor.cs b/blazorbootstrap/Components/Pagination/Pagination.razor.cs index 23a5b733c..7a9c7a774 100644 --- a/blazorbootstrap/Components/Pagination/Pagination.razor.cs +++ b/blazorbootstrap/Components/Pagination/Pagination.razor.cs @@ -75,36 +75,48 @@ private async Task SetPageNumberTo(int newPageNumber) /// /// Gets or sets the active page number. /// - /// + /// /// Default value is 1. - /// + /// + [AddedVersion("1.0.0")] + [DefaultValue(1)] + [Description("Gets or sets the active page number.")] [Parameter] public int ActivePageNumber { get; set; } = 1; /// /// Gets or sets the pagination alignment. /// - /// + /// /// Default value is . - /// + /// + [AddedVersion("1.0.0")] + [DefaultValue(Alignment.None)] + [Description("Gets or sets the pagination alignment.")] [Parameter] public Alignment Alignment { get; set; } = Alignment.None; /// /// Gets or sets the maximum page links to be displayed. /// - /// + /// /// Default value is 5. - /// + /// + [AddedVersion("1.0.0")] + [DefaultValue(5)] + [Description("Gets or sets the maximum page links to be displayed.")] [Parameter] public int DisplayPages { get; set; } = 5; /// /// Gets or sets the first link icon. /// - /// + /// /// Default value is . - /// + /// + [AddedVersion("1.0.0")] + [DefaultValue(IconName.None)] + [Description("Gets or sets the first link icon.")] [Parameter] public IconName FirstLinkIcon { get; set; } = IconName.None; @@ -113,9 +125,12 @@ private async Task SetPageNumberTo(int newPageNumber) /// /// Gets or sets the first link text. 'FirstLinkText' is ignored if 'FirstLinkIcon' is specified. /// - /// - /// Default value is null. - /// + /// + /// Default value is . + /// + [AddedVersion("1.0.0")] + [DefaultValue(null)] + [Description("Gets or sets the first link text. FirstLinkText is ignored if FirstLinkIcon is specified.")] [Parameter] public string? FirstLinkText { get; set; } @@ -124,9 +139,12 @@ private async Task SetPageNumberTo(int newPageNumber) /// /// Gets or sets the last link icon. /// - /// + /// /// Default value is . - /// + /// + [AddedVersion("1.0.0")] + [DefaultValue(IconName.None)] + [Description("Gets or sets the last link icon.")] [Parameter] public IconName LastLinkIcon { get; set; } = IconName.None; @@ -135,9 +153,12 @@ private async Task SetPageNumberTo(int newPageNumber) /// /// Gets or sets the last link text. 'LastLinkText' is ignored if 'LastLinkIcon' is specified. /// - /// - /// Default value is null. - /// + /// + /// Default value is . + /// + [AddedVersion("1.0.0")] + [DefaultValue(null)] + [Description("Gets or sets the last link text. LastLinkText is ignored if LastLinkIcon is specified.")] [Parameter] public string? LastLinkText { get; set; } @@ -146,9 +167,12 @@ private async Task SetPageNumberTo(int newPageNumber) /// /// Gets or sets the next link icon. /// - /// + /// /// Default value is . - /// + /// + [AddedVersion("1.0.0")] + [DefaultValue(IconName.None)] + [Description("Gets or sets the next link icon.")] [Parameter] public IconName NextLinkIcon { get; set; } = IconName.None; @@ -157,9 +181,12 @@ private async Task SetPageNumberTo(int newPageNumber) /// /// Gets or sets the next link text. 'NextLinkText' is ignored if 'NextLinkIcon' is specified. /// - /// - /// Default value is null. - /// + /// + /// Default value is . + /// + [AddedVersion("1.0.0")] + [DefaultValue(null)] + [Description("Gets or sets the next link text. NextLinkText is ignored if NextLinkIcon is specified.")] [Parameter] public string? NextLinkText { get; set; } @@ -168,6 +195,8 @@ private async Task SetPageNumberTo(int newPageNumber) /// /// This event fires immediately when the page number is changed. /// + [AddedVersion("1.0.0")] + [Description("This event fires immediately when the page number is changed.")] [Parameter] public EventCallback PageChanged { get; set; } @@ -178,9 +207,12 @@ private async Task SetPageNumberTo(int newPageNumber) /// /// Gets or sets the previous link icon. /// - /// + /// /// Default value is . - /// + /// + [AddedVersion("1.0.0")] + [DefaultValue(IconName.None)] + [Description("Gets or sets the previous link icon.")] [Parameter] public IconName PreviousLinkIcon { get; set; } = IconName.None; @@ -189,9 +221,12 @@ private async Task SetPageNumberTo(int newPageNumber) /// /// Gets or sets the previous link text. 'PreviousLinkText' is ignored if 'PreviousLinkIcon' is specified. /// - /// + /// /// Default value is null. - /// + /// + [AddedVersion("1.0.0")] + [DefaultValue(null)] + [Description("Gets or sets the previous link text. PreviousLinkText is ignored if PreviousLinkIcon is specified.")] [Parameter] public string? PreviousLinkText { get; set; } @@ -199,19 +234,25 @@ private async Task SetPageNumberTo(int newPageNumber) /// /// Gets or sets the pagination size. - /// - /// + /// /// Default value is . - /// + /// + /// + [AddedVersion("1.0.0")] + [DefaultValue(PaginationSize.None)] + [Description("Gets or sets the pagination size.")] [Parameter] public PaginationSize Size { get; set; } = PaginationSize.None; /// /// Gets or sets the total pages. - /// - /// + /// /// Default value is 0. - /// + /// + /// + [AddedVersion("1.0.0")] + [DefaultValue(0)] + [Description("Gets or sets the total pages.")] [Parameter] public int TotalPages { get; set; } diff --git a/blazorbootstrap/Components/PdfViewer/PdfViewer.razor b/blazorbootstrap/Components/PdfViewer/PdfViewer.razor index 6829314c7..543b9806c 100644 --- a/blazorbootstrap/Components/PdfViewer/PdfViewer.razor +++ b/blazorbootstrap/Components/PdfViewer/PdfViewer.razor @@ -36,6 +36,7 @@
  • Go to First Page
  • Go to Last Page
  • Reset Zoom
  • +
  • Download
  • diff --git a/blazorbootstrap/Components/PdfViewer/PdfViewer.razor.cs b/blazorbootstrap/Components/PdfViewer/PdfViewer.razor.cs index 5a0056530..c1d1b82cb 100644 --- a/blazorbootstrap/Components/PdfViewer/PdfViewer.razor.cs +++ b/blazorbootstrap/Components/PdfViewer/PdfViewer.razor.cs @@ -32,7 +32,7 @@ public partial class PdfViewer : BlazorBootstrapComponentBase protected override async Task OnAfterRenderAsync(bool firstRender) { if (firstRender) - await PdfViewerJsInterop.InitializeAsync(objRef!, Id!, scale, rotation, Url!); + await PdfViewerJsInterop!.InitializeAsync(objRef!, Id!, scale, rotation, Url!, Password!); await base.OnAfterRenderAsync(firstRender); } @@ -53,12 +53,31 @@ protected override async Task OnParametersSetAsync() { oldOrientation = Orientation; rotation = Orientation == Orientation.Portrait ? 0 : -90; - await PdfViewerJsInterop.RotateAsync(objRef!, Id!, rotation); + await PdfViewerJsInterop!.RotateAsync(objRef!, Id!, rotation); } await base.OnParametersSetAsync(); } + /// + /// Asynchronously sets the zoom level of the PDF viewer to the specified percentage. + /// + /// The zoom percentage is converted to a scale factor for rendering the PDF document. Ensure + /// that the provided zoom percentage is within valid bounds to avoid unexpected display behavior. + /// The desired zoom percentage to apply to the PDF viewer. Must be a valid value defined by the + /// PdfViewerZoomPercentage enumeration. + /// A task that represents the asynchronous operation of updating the zoom level. + [AddedVersion("4.0.0")] + [Description("Asynchronously sets the zoom level of the PDF viewer to the specified percentage.")] + public async Task SetZoomPercentageAsync(PdfViewerZoomPercentage zoomPercentage) + { + zoomLevel = (int)zoomPercentage; + var zp = GetZoomPercentage(zoomLevel); + this.zoomPercentage = $"{zp}%"; + scale = 0.01 * zp; + await PdfViewerJsInterop!.ZoomInOutAsync(objRef!, Id!, scale); + } + [JSInvokable] public void DocumentLoaded(PdfViewerModel pdfViewerModel) { @@ -73,6 +92,15 @@ public void DocumentLoaded(PdfViewerModel pdfViewerModel) OnDocumentLoaded.InvokeAsync(new PdfViewerEventArgs(pageNumber, pagesCount)); } + [JSInvokable] + public void DocumentLoadError(string errorMessage) + { + if(string.IsNullOrEmpty(errorMessage)) return; + + if (OnDocumentLoadError.HasDelegate) + OnDocumentLoadError.InvokeAsync(errorMessage); + } + [JSInvokable] public void SetPdfViewerMetaData(PdfViewerModel pdfViewerModel) { @@ -85,7 +113,12 @@ public void SetPdfViewerMetaData(PdfViewerModel pdfViewerModel) OnPageChanged.InvokeAsync(new PdfViewerEventArgs(pageNumber, pagesCount)); } - private async Task FirstPageAsync() => await PdfViewerJsInterop.FirstPageAsync(objRef!, Id!); + private async Task DownloadPdf() + { + await PdfViewerJsInterop!.DownloadPdfAsync(objRef!, Id!, Url!); + } + + private async Task FirstPageAsync() => await PdfViewerJsInterop!.FirstPageAsync(objRef!, Id!); private int GetZoomPercentage(int zoomLevel) => zoomLevel switch @@ -110,9 +143,9 @@ private int GetZoomPercentage(int zoomLevel) => _ => 100 }; - private async Task LastPageAsync() => await PdfViewerJsInterop.LastPageAsync(objRef!, Id!); + private async Task LastPageAsync() => await PdfViewerJsInterop!.LastPageAsync(objRef!, Id!); - private async Task NextPageAsync() => await PdfViewerJsInterop.NextPageAsync(objRef!, Id!); + private async Task NextPageAsync() => await PdfViewerJsInterop!.NextPageAsync(objRef!, Id!); private async Task PageNumberChangedAsync(int value) { @@ -121,12 +154,12 @@ private async Task PageNumberChangedAsync(int value) else pageNumber = value; - await PdfViewerJsInterop.GotoPageAsync(objRef!, Id!, pageNumber); + await PdfViewerJsInterop!.GotoPageAsync(objRef!, Id!, pageNumber); } - private async Task PreviousPageAsync() => await PdfViewerJsInterop.PreviousPageAsync(objRef!, Id!); + private async Task PreviousPageAsync() => await PdfViewerJsInterop!.PreviousPageAsync(objRef!, Id!); - private async Task PrintAsync() => await PdfViewerJsInterop.PrintAsync(objRef!, Id!, Url!); + private async Task PrintAsync() => await PdfViewerJsInterop!.PrintAsync(objRef!, Id!, Url!); private async Task ResetZoomAsync() { @@ -134,14 +167,14 @@ private async Task ResetZoomAsync() var zp = GetZoomPercentage(defaultZoomLevel); zoomPercentage = $"{zp}%"; scale = 0.01 * zp; - await PdfViewerJsInterop.ZoomInOutAsync(objRef!, Id!, scale); + await PdfViewerJsInterop!.ZoomInOutAsync(objRef!, Id!, scale); } private async Task RotateClockwiseAsync() { rotation += 90; rotation = rotation.Equals(360) ? 0 : rotation; - await PdfViewerJsInterop.RotateAsync(objRef!, Id!, rotation); + await PdfViewerJsInterop!.RotateAsync(objRef!, Id!, rotation); // Orientation SetOrientation(); @@ -151,7 +184,7 @@ private async Task RotateCounterclockwiseAsync() { rotation -= 90; rotation = rotation.Equals(-360) ? 0 : rotation; - await PdfViewerJsInterop.RotateAsync(objRef!, Id!, rotation); + await PdfViewerJsInterop!.RotateAsync(objRef!, Id!, rotation); // Orientation SetOrientation(); @@ -170,7 +203,7 @@ private async Task SwitchOrientationAsync() oldOrientation = Orientation; Orientation = Orientation == Orientation.Portrait ? Orientation.Landscape : Orientation.Portrait; rotation = Orientation == Orientation.Portrait ? 0 : -90; - await PdfViewerJsInterop.RotateAsync(objRef!, Id!, rotation); + await PdfViewerJsInterop!.RotateAsync(objRef!, Id!, rotation); } private async Task ZoomInAsync() @@ -182,7 +215,7 @@ private async Task ZoomInAsync() var zp = GetZoomPercentage(zoomLevel); zoomPercentage = $"{zp}%"; scale = 0.01 * zp; - await PdfViewerJsInterop.ZoomInOutAsync(objRef!, Id!, scale); + await PdfViewerJsInterop!.ZoomInOutAsync(objRef!, Id!, scale); } private async Task ZoomOutAsync() @@ -194,7 +227,7 @@ private async Task ZoomOutAsync() var zp = GetZoomPercentage(zoomLevel); zoomPercentage = $"{zp}%"; scale = 0.01 * zp; - await PdfViewerJsInterop.ZoomInOutAsync(objRef!, Id!, scale); + await PdfViewerJsInterop!.ZoomInOutAsync(objRef!, Id!, scale); } #endregion @@ -204,37 +237,67 @@ private async Task ZoomOutAsync() /// /// This event fires immediately after the PDF document is loaded. /// + [AddedVersion("1.0.0")] + [Description("This event fires immediately after the PDF document is loaded.")] [Parameter] public EventCallback OnDocumentLoaded { get; set; } + /// + /// This event fires if there is an error loading the PDF document. + /// + [AddedVersion("1.11.0")] + [Description("This event fires if there is an error loading the PDF document.")] + [Parameter] + public EventCallback OnDocumentLoadError { get; set; } + /// /// This event fires immediately after the page is changed. /// + [AddedVersion("1.11.0")] + [Description("This event fires immediately after the page is changed.")] [Parameter] public EventCallback OnPageChanged { get; set; } /// /// Gets or sets the preferred orientation for the PDF viewer. - /// - /// + /// /// Default value is . - /// + /// + /// + [AddedVersion("2.1.0")] + [DefaultValue(Orientation.Portrait)] + [Description("Gets or sets the preferred orientation for the PDF viewer.")] [Parameter] public Orientation Orientation { get; set; } = Orientation.Portrait; + /// + /// Gets or sets the password used for the PDF document if it is password-protected. + /// + /// Default value is . + /// + /// + [AddedVersion("3.5.0")] + [DefaultValue(null)] + [Description("Gets or sets the password used for the PDF document if it is password-protected.")] + [Parameter] + public string? Password { get; set; } + /// /// Provides JavaScript interop functionality for the PDF viewer. /// [Inject] - private PdfViewerJsInterop PdfViewerJsInterop { get; set; } = default!; + private PdfViewerJsInterop? PdfViewerJsInterop { get; set; } /// /// Gets or sets the URL of the PDF document to be displayed. /// PDF Viewer component supports base64 string as a URL. + /// + /// Default value is . + /// /// - /// - /// Default value is null. - /// + [AddedVersion("1.11.0")] + [DefaultValue(null)] + [Description("Gets or sets the URL of the PDF document to be displayed. PDF Viewer component supports base64 string as a URL.")] [Parameter] public string? Url { get; set; } diff --git a/blazorbootstrap/Components/PdfViewer/PdfViewerJsInterop.cs b/blazorbootstrap/Components/PdfViewer/PdfViewerJsInterop.cs index 93bfc7f48..6add82a0f 100644 --- a/blazorbootstrap/Components/PdfViewer/PdfViewerJsInterop.cs +++ b/blazorbootstrap/Components/PdfViewer/PdfViewerJsInterop.cs @@ -1,86 +1,69 @@ namespace BlazorBootstrap; -public class PdfViewerJsInterop : IAsyncDisposable +public class PdfViewerJsInterop : JsInteropBase { - #region Fields and Constants - - private readonly Lazy> moduleTask; - - #endregion - #region Constructors public PdfViewerJsInterop(IJSRuntime jsRuntime) + : base(jsRuntime, "./_content/Blazor.Bootstrap/blazor.bootstrap.pdf.js") { - moduleTask = new Lazy>(() => jsRuntime.InvokeAsync("import", "./_content/Blazor.Bootstrap/blazor.bootstrap.pdf.js").AsTask()); } #endregion #region Methods - public async ValueTask DisposeAsync() + public async Task DownloadPdfAsync(object objRef, string elementId, string url) { - if (moduleTask.IsValueCreated) - { - var module = await moduleTask.Value; - await module.DisposeAsync(); - } + if (string.IsNullOrWhiteSpace(url)) + throw new ArgumentException("URL cannot be null or empty.", nameof(url)); + + await SafeInvokeVoidAsync("downloadPdf", objRef, elementId, url); } public async Task FirstPageAsync(object objRef, string elementId) { - var module = await moduleTask.Value; - await module.InvokeVoidAsync("firstPage", objRef, elementId); + await SafeInvokeVoidAsync("firstPage", objRef, elementId); } public async Task GotoPageAsync(object objRef, string elementId, int gotoPageNum) { - var module = await moduleTask.Value; - await module.InvokeVoidAsync("gotoPage", objRef, elementId, gotoPageNum); + await SafeInvokeVoidAsync("gotoPage", objRef, elementId, gotoPageNum); } - public async Task InitializeAsync(object objRef, string elementId, double scale, double rotation, string url) + public async Task InitializeAsync(object objRef, string elementId, double scale, double rotation, string url, string password) { - var module = await moduleTask.Value; - await module.InvokeVoidAsync("initialize", objRef, elementId, scale, rotation, url); + await SafeInvokeVoidAsync("initialize", objRef, elementId, scale, rotation, url, password); } public async Task LastPageAsync(object objRef, string elementId) { - var module = await moduleTask.Value; - await module.InvokeVoidAsync("lastPage", objRef, elementId); + await SafeInvokeVoidAsync("lastPage", objRef, elementId); } public async Task NextPageAsync(object objRef, string elementId) { - var module = await moduleTask.Value; - await module.InvokeVoidAsync("nextPage", objRef, elementId); + await SafeInvokeVoidAsync("nextPage", objRef, elementId); } public async Task PreviousPageAsync(object objRef, string elementId) { - var module = await moduleTask.Value; - await module.InvokeVoidAsync("previousPage", objRef, elementId); + await SafeInvokeVoidAsync("previousPage", objRef, elementId); } public async Task PrintAsync(object objRef, string elementId, string url) { - var module = await moduleTask.Value; - await module.InvokeVoidAsync("print", objRef, elementId, url); + await SafeInvokeVoidAsync("print", objRef, elementId, url); } public async Task RotateAsync(object objRef, string elementId, double rotation) { - var module = await moduleTask.Value; - await module.InvokeVoidAsync("rotate", objRef, elementId, rotation); + await SafeInvokeVoidAsync("rotate", objRef, elementId, rotation); } public async Task ZoomInOutAsync(object objRef, string elementId, double scale) { - var module = await moduleTask.Value; - await module.InvokeVoidAsync("zoomInOut", objRef, elementId, scale); + await SafeInvokeVoidAsync("zoomInOut", objRef, elementId, scale); } - #endregion } diff --git a/blazorbootstrap/Components/Placeholders/Placeholder.razor.cs b/blazorbootstrap/Components/Placeholders/Placeholder.razor.cs index 7166e560f..c0d34ede3 100644 --- a/blazorbootstrap/Components/Placeholders/Placeholder.razor.cs +++ b/blazorbootstrap/Components/Placeholders/Placeholder.razor.cs @@ -13,28 +13,37 @@ public partial class Placeholder : BlazorBootstrapComponentBase /// /// Gets or sets the placeholder color. - /// - /// + /// /// Default value is . - /// + /// + /// + [AddedVersion("1.0.0")] + [DefaultValue(PlaceholderColor.None)] + [Description("Gets or sets the placeholder color.")] [Parameter] public PlaceholderColor Color { get; set; } = PlaceholderColor.None; /// /// Gets or sets the placeholder size. - /// - /// + /// /// Default value is . - /// + /// + /// + [AddedVersion("1.0.0")] + [DefaultValue(PlaceholderSize.None)] + [Description("Gets or sets the placeholder size.")] [Parameter] public PlaceholderSize Size { get; set; } = PlaceholderSize.None; /// /// Gets or sets the placeholder width. - /// - /// + /// /// Default value is . - /// + /// + /// + [AddedVersion("1.0.0")] + [DefaultValue(PlaceholderWidth.Col1)] + [Description("Gets or sets the placeholder width.")] [Parameter] public PlaceholderWidth Width { get; set; } = PlaceholderWidth.Col1; diff --git a/blazorbootstrap/Components/Placeholders/PlaceholderContainer.razor.cs b/blazorbootstrap/Components/Placeholders/PlaceholderContainer.razor.cs index 55e28a2d4..acb378284 100644 --- a/blazorbootstrap/Components/Placeholders/PlaceholderContainer.razor.cs +++ b/blazorbootstrap/Components/Placeholders/PlaceholderContainer.razor.cs @@ -9,19 +9,26 @@ public partial class PlaceholderContainer : BlazorBootstrapComponentBase /// /// Gets or sets the placeholder animation. - /// - /// + /// /// Default value is . - /// + /// + /// + [AddedVersion("1.0.0")] + [DefaultValue(PlaceholderAnimation.Glow)] + [Description("Gets or sets the placeholder animation.")] [Parameter] public PlaceholderAnimation Animation { get; set; } = PlaceholderAnimation.Glow; /// /// Gets or sets the content to be rendered within the component. + /// + /// Default value is . + /// /// - /// - /// Default value is null. - /// + [AddedVersion("1.0.0")] + [DefaultValue(null)] + [Description("Gets or sets the content to be rendered within the component.")] + [EditorRequired] [Parameter] public RenderFragment? ChildContent { get; set; } diff --git a/blazorbootstrap/Components/Preload/Preload.razor.cs b/blazorbootstrap/Components/Preload/Preload.razor.cs index 6bf2add4e..5617e143b 100644 --- a/blazorbootstrap/Components/Preload/Preload.razor.cs +++ b/blazorbootstrap/Components/Preload/Preload.razor.cs @@ -68,13 +68,25 @@ private void OnShow(SpinnerColor spinnerColor, string? loadingText) /// /// Gets or sets the content to be rendered within the component. + /// + /// Default value is . + /// /// + [AddedVersion("1.1.0")] + [DefaultValue(null)] + [Description("Gets or sets the content to be rendered within the component.")] [Parameter] public RenderFragment? ChildContent { get; set; } /// /// Gets or sets the loading text. + /// + /// Default value is . + /// /// + [AddedVersion("1.10.4")] + [DefaultValue(null)] + [Description("Gets or sets the loading text.")] [Parameter] public string? LoadingText { get; set; } diff --git a/blazorbootstrap/Components/Progress/Progress.razor.cs b/blazorbootstrap/Components/Progress/Progress.razor.cs index 650abe762..1c9c2cad2 100644 --- a/blazorbootstrap/Components/Progress/Progress.razor.cs +++ b/blazorbootstrap/Components/Progress/Progress.razor.cs @@ -29,19 +29,25 @@ protected override void OnInitialized() /// /// Gets or sets the content to be rendered within the component. + /// + /// Default value is . + /// /// - /// - /// Default value is null. - /// + [AddedVersion("1.0.0")] + [DefaultValue(null)] + [Description("Gets or sets the content to be rendered within the component.")] [Parameter] public RenderFragment? ChildContent { get; set; } /// /// Gets or sets the height of the Progress. Height is measured in pixels. - /// - /// + /// /// Default value is 16. - /// + /// + /// + [AddedVersion("1.0.0")] + [DefaultValue(16)] + [Description("Gets or sets the height of the Progress. Height is measured in pixels.")] [Parameter] public double Height { get; set; } = 16; diff --git a/blazorbootstrap/Components/Progress/ProgressBar.razor.cs b/blazorbootstrap/Components/Progress/ProgressBar.razor.cs index d563583ab..8c7791f14 100644 --- a/blazorbootstrap/Components/Progress/ProgressBar.razor.cs +++ b/blazorbootstrap/Components/Progress/ProgressBar.razor.cs @@ -17,6 +17,8 @@ public partial class ProgressBar /// Decrease the progress bar width. /// /// + [AddedVersion("1.0.0")] + [Description("Decrease the progress bar width.")] public void DecreaseWidth(double width) { if (width is < 0 or > 100) @@ -31,13 +33,17 @@ public void DecreaseWidth(double width) /// /// Get the progress bar width. /// - /// + /// double + [AddedVersion("1.0.0")] + [Description("Get the progress bar width.")] public double GetWidth() => width; /// /// Increase the progress bar width. /// /// + [AddedVersion("1.0.0")] + [Description("Increase the progress bar width.")] public void IncreaseWidth(double width) { if (width is < 0 or > 100) @@ -53,18 +59,24 @@ public void IncreaseWidth(double width) /// Set the progress bar color. /// /// + [AddedVersion("1.0.0")] + [Description("Set the progress bar color.")] public void SetColor(ProgressColor color) => Color = color; /// /// Set the progress bar label. /// /// + [AddedVersion("1.0.0")] + [Description("Set the progress bar label.")] public void SetLabel(string text) => Label = text; /// /// Set the progress bar width. /// /// + [AddedVersion("1.0.0")] + [Description("Set the progress bar width.")] public void SetWidth(double width) { if (width is < 0 or > 100) @@ -91,10 +103,13 @@ public void SetWidth(double width) /// /// Gets or sets the progress color. - /// - /// + /// /// Default value is . - /// + /// + /// + [AddedVersion("1.0.0")] + [DefaultValue(ProgressColor.None)] + [Description("Gets or sets the progress color.")] [Parameter] public ProgressColor Color { @@ -108,19 +123,25 @@ public ProgressColor Color /// /// Gets or sets the progress bar label. + /// + /// Default value is . + /// /// - /// - /// Default value is null. - /// + [AddedVersion("1.0.0")] + [DefaultValue(null)] + [Description("Gets or sets the progress bar label.")] [Parameter] - public string Label { get; set; } = default!; + public string? Label { get; set; } /// /// Gets or sets the progress bar type. - /// - /// + /// /// Default value is . - /// + /// + /// + [AddedVersion("1.0.0")] + [DefaultValue(ProgressType.Default)] + [Description("Gets or sets the progress bar type.")] [Parameter] public ProgressType Type { @@ -134,10 +155,13 @@ public ProgressType Type /// /// Get or sets the progress bar width. - /// - /// + /// /// Default value is 0. - /// + /// + /// + [AddedVersion("1.0.0")] + [DefaultValue(0)] + [Description("Get or sets the progress bar width.")] [Parameter] public double Width { diff --git a/blazorbootstrap/Components/Ribbon/Ribbon.razor.cs b/blazorbootstrap/Components/Ribbon/Ribbon.razor.cs index 5d5f51af2..fbedcacb3 100644 --- a/blazorbootstrap/Components/Ribbon/Ribbon.razor.cs +++ b/blazorbootstrap/Components/Ribbon/Ribbon.razor.cs @@ -111,6 +111,8 @@ public async Task bsShowTab(string activeTabId, string previousActiveTabId) /// /// /// + [AddedVersion("2.2.0")] + [Description("Removes the tab by index.")] public void RemoveTabByIndex(int tabIndex) { if (!tabs?.Any() ?? true) return; @@ -130,6 +132,8 @@ public void RemoveTabByIndex(int tabIndex) /// Removes the tab by name. /// /// + [AddedVersion("2.2.0")] + [Description("Removes the tab by name.")] public void RemoveTabByName(string tabName) { if (!tabs?.Any() ?? true) return; @@ -148,6 +152,8 @@ public void RemoveTabByName(string tabName) /// /// Selects the first tab and show its associated pane. /// + [AddedVersion("2.2.0")] + [Description("Selects the first tab and show its associated pane.")] public async Task ShowFirstTabAsync() { if (!tabs?.Any() ?? true) return; @@ -161,6 +167,8 @@ public async Task ShowFirstTabAsync() /// /// Selects the last tab and show its associated pane. /// + [AddedVersion("2.2.0")] + [Description("Selects the last tab and show its associated pane.")] public async Task ShowLastTabAsync() { if (!tabs?.Any() ?? true) return; @@ -174,12 +182,16 @@ public async Task ShowLastTabAsync() /// /// Shows the recently added tab. /// + [AddedVersion("2.2.0")] + [Description("Shows the recently added tab.")] public void ShowRecentTab() => showLastTab = true; /// /// Selects the tab by index and show its associated pane. /// /// The zero-based index of the element to get or set. + [AddedVersion("2.2.0")] + [Description("Selects the tab by index and show its associated pane.")] public async Task ShowTabByIndexAsync(int tabIndex) { if (!tabs?.Any() ?? true) return; @@ -196,6 +208,8 @@ public async Task ShowTabByIndexAsync(int tabIndex) /// Selects the tab by name and show its associated pane. /// /// The name of the tab to select. + [AddedVersion("2.2.0")] + [Description("Selects the tab by name and show its associated pane.")] public async Task ShowTabByNameAsync(string tabName) { if (!tabs?.Any() ?? true) return; @@ -281,16 +295,26 @@ private async Task ShowTabAsync(RibbonTab tab) /// /// Gets or sets the content to be rendered within the component. + /// + /// Default value is . + /// /// + [AddedVersion("2.2.0")] + [DefaultValue(null)] + [Description("Gets or sets the content to be rendered within the component.")] + [EditorRequired] [Parameter] - public RenderFragment ChildContent { get; set; } = default!; + public RenderFragment? ChildContent { get; set; } /// /// Gets or sets the tabs fade effect. /// - /// - /// Default value is false. - /// + /// + /// Default value is . + /// + [AddedVersion("2.2.0")] + [DefaultValue(false)] + [Description("Gets or sets the tabs fade effect.")] [Parameter] public bool EnableFadeEffect { get; set; } @@ -310,39 +334,49 @@ private async Task ShowTabAsync(RibbonTab tab) /// /// Get or sets the nav style. /// - /// + /// /// Default value is . - /// + /// //[Parameter] private NavStyle NavStyle { get; set; } = NavStyle.Underline; /// /// This event fires when the user clicks the corresponding . /// + [AddedVersion("2.2.0")] + [Description("This event fires when the user clicks the corresponding RibbonItem.")] [Parameter] public EventCallback OnClick { get; set; } /// /// This event fires after a new tab is shown (and thus the previous active tab is hidden). /// + [AddedVersion("2.2.0")] + [Description("This event fires after a new tab is shown (and thus the previous active tab is hidden).")] [Parameter] public EventCallback OnHidden { get; set; } /// /// This event fires when a new tab is to be shown (and thus the previous active tab is to be hidden). /// + [AddedVersion("2.2.0")] + [Description("This event fires when a new tab is to be shown (and thus the previous active tab is to be hidden).")] [Parameter] public EventCallback OnHiding { get; set; } /// /// This event fires on tab show, but before the new tab has been shown. /// + [AddedVersion("2.2.0")] + [Description("This event fires on tab show, but before the new tab has been shown.")] [Parameter] public EventCallback OnShowing { get; set; } /// /// This event fires on tab show after a tab has been shown. /// + [AddedVersion("2.2.0")] + [Description("This event fires on tab show after a tab has been shown.")] [Parameter] public EventCallback OnShown { get; set; } diff --git a/blazorbootstrap/Components/Ribbon/RibbonGroup.razor.cs b/blazorbootstrap/Components/Ribbon/RibbonGroup.razor.cs index db3af8db9..48c923e13 100644 --- a/blazorbootstrap/Components/Ribbon/RibbonGroup.razor.cs +++ b/blazorbootstrap/Components/Ribbon/RibbonGroup.razor.cs @@ -12,8 +12,14 @@ public partial class RibbonGroup : BlazorBootstrapComponentBase (BootstrapClass.Border, true)); /// - /// Gets or sets the content to be rendered inside this component. + /// Gets or sets the content to be rendered within the component. + /// + /// Default value is . + /// /// + [AddedVersion("2.2.0")] + [DefaultValue(null)] + [Description("Gets or sets the content to be rendered within the component.")] [Parameter] public RenderFragment? ChildContent { get; set; } diff --git a/blazorbootstrap/Components/Ribbon/RibbonItem.razor.cs b/blazorbootstrap/Components/Ribbon/RibbonItem.razor.cs index 3dbc0d744..9593c6aee 100644 --- a/blazorbootstrap/Components/Ribbon/RibbonItem.razor.cs +++ b/blazorbootstrap/Components/Ribbon/RibbonItem.razor.cs @@ -30,103 +30,145 @@ private async Task OnRibbonItemClickAsync() /// /// Gets or sets the content to be rendered within the component. + /// + /// Default value is . + /// /// + [AddedVersion("2.2.0")] + [DefaultValue(null)] + [Description("Gets or sets the content to be rendered within the component.")] [Parameter] public RenderFragment? ChildContent { get; set; } /// /// Gets or sets the custom icon name. + /// + /// Default value is . + /// /// - /// - /// Default value is null. - /// + [AddedVersion("2.2.0")] + [DefaultValue(null)] + [Description("Gets or sets the custom icon name.")] [Parameter] public string? CustomIconName { get; set; } /// /// Gets or sets the icon color. - /// - /// + /// /// Default value is . - /// + /// + /// + [AddedVersion("2.2.0")] + [DefaultValue(IconColor.None)] + [Description("Gets or sets the icon color.")] [Parameter] public IconColor IconColor { get; set; } = IconColor.None; /// /// Gets or sets the icon CSS class. + /// + /// Default value is . + /// /// - /// - /// Default value is null. - /// + [AddedVersion("2.2.0")] + [DefaultValue(null)] + [Description("Gets or sets the icon CSS class.")] [Parameter] public string? IconCssClass { get; set; } /// /// Gets or sets the icon name. - /// - /// + /// /// Default value is . - /// + /// + /// + [AddedVersion("2.2.0")] + [DefaultValue(IconName.None)] + [Description("Gets or sets the icon name.")] [Parameter] public IconName IconName { get; set; } = IconName.None; /// /// Gets or sets the icon size. - /// - /// + /// /// Default value is . - /// + /// + /// + [AddedVersion("2.2.0")] + [DefaultValue(IconSize.x3)] + [Description("Gets or sets the icon size.")] [Parameter] public IconSize IconSize { get; set; } = IconSize.x3; /// /// Gets or sets the image hieght. The height of the image in pixels. - /// - /// + /// /// Default value is 28. - /// + /// + /// + [AddedVersion("2.2.0")] + [DefaultValue(28)] + [Description("Gets or sets the image hieght. The height of the image in pixels.")] [Parameter] public double ImgHeight { get; set; } = 28; /// /// Gets or sets the image source. + /// + /// Default value is . + /// /// - /// - /// Default value is null. - /// + [AddedVersion("2.2.0")] + [DefaultValue(null)] + [Description("Gets or sets the image source.")] [Parameter] public string? ImgSrc { get; set; } /// /// Gets or sets the image width. The width of the image in pixels. - /// - /// + /// /// Default value is 28. - /// + /// + /// + [AddedVersion("2.2.0")] + [DefaultValue(28)] + [Description("Gets or sets the image width. The width of the image in pixels.")] [Parameter] public double ImgWidth { get; set; } = 28; /// - /// Gets or sets the first item in the RibbonItemGroup. + /// Gets or sets the first item in the . + /// + /// Default value is . + /// /// - /// - /// Default value is false. - /// + [AddedVersion("2.2.0")] + [DefaultValue(false)] + [Description("Gets or sets the first item in the RibbonItemGroup.")] [Parameter] - public bool IsFirstItem { get; set; } = false; + public bool IsFirstItem { get; set; } /// - /// Gets or sets the last item in the RibbonItemGroup. + /// Gets or sets the last item in the . + /// + /// Default value is . + /// /// - /// - /// Default value is false. - /// + [AddedVersion("2.2.0")] + [DefaultValue(false)] + [Description("Gets or sets the last item in the RibbonItemGroup.")] [Parameter] - public bool IsLastItem { get; set; } = false; + public bool IsLastItem { get; set; } /// - /// Gets or sets the RibbonItem name. + /// Gets or sets the name. + /// + /// Default value is . + /// /// + [AddedVersion("2.2.0")] + [DefaultValue(null)] + [Description("Gets or sets the RibbonItem name.")] [Parameter] public string? Name { get; set; } @@ -139,6 +181,9 @@ private async Task OnRibbonItemClickAsync() /// /// Gets or sets the text to be displayed inside the RibbonItem. /// + [AddedVersion("2.2.0")] + [DefaultValue(null)] + [Description("Gets or sets the text to be displayed inside the RibbonItem.")] [Parameter] public string? Text { get; set; } diff --git a/blazorbootstrap/Components/Ribbon/RibbonItemGroup.razor.cs b/blazorbootstrap/Components/Ribbon/RibbonItemGroup.razor.cs index c19659f4d..5896546e6 100644 --- a/blazorbootstrap/Components/Ribbon/RibbonItemGroup.razor.cs +++ b/blazorbootstrap/Components/Ribbon/RibbonItemGroup.razor.cs @@ -15,16 +15,26 @@ public partial class RibbonItemGroup : BlazorBootstrapComponentBase /// /// Gets or sets the content to be rendered within the component. + /// + /// Default value is . + /// /// + [AddedVersion("2.2.0")] + [DefaultValue(null)] + [Description("Gets or sets the content to be rendered within the component.")] + [EditorRequired] [Parameter] public RenderFragment? ChildContent { get; set; } /// /// Gets or sets the text. + /// + /// Default value is . + /// /// - /// - /// Default value is null. - /// + [AddedVersion("2.2.0")] + [DefaultValue(null)] + [Description("Gets or sets the text.")] [Parameter] public string? Text { get; set; } diff --git a/blazorbootstrap/Components/Ribbon/RibbonTab.razor.cs b/blazorbootstrap/Components/Ribbon/RibbonTab.razor.cs index 006e857bc..425d4a330 100644 --- a/blazorbootstrap/Components/Ribbon/RibbonTab.razor.cs +++ b/blazorbootstrap/Components/Ribbon/RibbonTab.razor.cs @@ -34,44 +34,58 @@ protected override void OnInitialized() /// /// Gets or sets the active state. + /// + /// Default value is . + /// /// - /// - /// Default value is false. - /// + [AddedVersion("2.2.0")] + [DefaultValue(false)] + [Description("Gets or sets the active state.")] [Parameter] public bool Active { get; set; } /// /// Gets or sets the content to be rendered within the component. + /// + /// Default value is . + /// /// - /// - /// Default value is null. - /// - [Parameter] + [AddedVersion("2.2.0")] + [DefaultValue(null)] + [Description("Gets or sets the content to be rendered within the component.")] [EditorRequired] - public RenderFragment Content { get; set; } = default!; + [Parameter] + public RenderFragment? Content { get; set; } /// /// Gets or sets the disabled state. + /// + /// Default value is . + /// /// - /// - /// Default value is false. - /// + [AddedVersion("2.2.0")] + [DefaultValue(false)] + [Description("Gets or sets the disabled state.")] [Parameter] public bool Disabled { get; set; } /// /// Gets or sets the tab name. + /// + /// Default value is . + /// /// - /// - /// Default value is null. - /// + [AddedVersion("2.2.0")] + [DefaultValue(null)] + [Description("Gets or sets the tab name.")] [Parameter] - public string Name { get; set; } = default!; + public string? Name { get; set; } /// /// This event fires when the user clicks the corresponding tab button and the tab is displayed. /// + [AddedVersion("2.2.0")] + [Description("This event fires when the user clicks the corresponding tab button and the tab is displayed.")] [Parameter] public EventCallback OnClick { get; set; } @@ -79,22 +93,31 @@ protected override void OnInitialized() /// Gets or sets the parent ribbon. /// [CascadingParameter(Name = "Ribbon1")] - internal Ribbon Parent { get; set; } = default!; + internal Ribbon? Parent { get; set; } /// /// Gets or sets the tab title. + /// + /// Default value is . + /// /// - /// - /// Default value is null. - /// + [AddedVersion("2.2.0")] + [DefaultValue(null)] + [Description("Gets or sets the tab title.")] [Parameter] - public string Title { get; set; } = default!; + public string? Title { get; set; } /// /// Gets or sets the tab title template. + /// + /// Default value is . + /// /// + [AddedVersion("2.2.0")] + [DefaultValue(null)] + [Description("Gets or sets the tab title template.")] [Parameter] - public RenderFragment TitleTemplate { get; set; } = default!; + public RenderFragment? TitleTemplate { get; set; } #endregion } diff --git a/blazorbootstrap/Components/ScriptLoader/ScriptLoader.razor.cs b/blazorbootstrap/Components/ScriptLoader/ScriptLoader.razor.cs index d09d3b859..9c15eb4b8 100644 --- a/blazorbootstrap/Components/ScriptLoader/ScriptLoader.razor.cs +++ b/blazorbootstrap/Components/ScriptLoader/ScriptLoader.razor.cs @@ -24,7 +24,7 @@ public partial class ScriptLoader : BlazorBootstrapComponentBase protected override async Task OnAfterRenderAsync(bool firstRender) { if (firstRender) - await JSRuntime.InvokeVoidAsync("window.blazorBootstrap.scriptLoader.initialize", Id, Async, Defer, ScriptId, Source, ScriptType, objRef); + await SafeInvokeVoidAsync("window.blazorBootstrap.scriptLoader.initialize", Id, Async, Defer, ScriptId, Source, ScriptType, objRef); await base.OnAfterRenderAsync(firstRender); } @@ -71,53 +71,74 @@ public void OnLoadJS() /// /// Gets or sets a value indicating whether the script should be loaded asynchronously. - /// - /// + /// /// Default value is . - /// + /// + /// + [AddedVersion("1.11.0")] + [DefaultValue(false)] + [Description("Gets or sets a value indicating whether the script should be loaded asynchronously.")] [Parameter] public bool Async { get; set; } /// /// Gets or sets a value indicating whether the script is meant to be executed - /// after the document has been parsed, but before firing DOMContentLoaded event.. - /// - /// + /// after the document has been parsed, but before firing DOMContentLoaded event. + /// /// Default value is . - /// + /// + /// + [AddedVersion("1.11.0")] + [DefaultValue(false)] + [Description("Gets or sets a value indicating whether the script is meant to be executed after the document has been parsed, but before firing DOMContentLoaded event.")] [Parameter] public bool Defer { get; set; } /// /// An event that is fired when a script loading error occurs. /// + [AddedVersion("1.11.0")] + [Description("An event that is fired when a script loading error occurs.")] [Parameter] public EventCallback OnError { get; set; } /// /// An event that is fired when a script has been successfully loaded. /// + [AddedVersion("1.11.0")] + [Description("An event that is fired when a script has been successfully loaded.")] [Parameter] public EventCallback OnLoad { get; set; } /// /// Gets or sets the ID of the script element. - /// - /// + /// /// Default value is . - /// + /// + /// + [AddedVersion("1.11.0")] + [DefaultValue(null)] + [Description("Gets or sets the ID of the script element.")] [Parameter] public string? ScriptId { get; set; } /// /// Gets or sets the URI of the external script to load. - /// - /// + /// /// Default value is . - /// - [Parameter] + /// + /// + [AddedVersion("1.11.0")] + [DefaultValue(null)] + [Description("Gets or sets the URI of the external script to load.")] [EditorRequired] - public string? Source { get; set; } = default!; + [Parameter] + public string? Source { get; set; } + + // NOTE: Hiding base Class and Style properties to prevent their usage in this component. + private new string? Class { get; set; } + + private new string? Style { get; set; } #endregion } diff --git a/blazorbootstrap/Components/Sidebar/Sidebar.razor b/blazorbootstrap/Components/Sidebar/Sidebar.razor index 093b4ff06..7038e04ca 100644 --- a/blazorbootstrap/Components/Sidebar/Sidebar.razor +++ b/blazorbootstrap/Components/Sidebar/Sidebar.razor @@ -7,11 +7,11 @@