diff --git a/Material.Blazor.MD3/package-lock.json b/Material.Blazor.MD3/package-lock.json index 709bf1ead..6573630c4 100644 --- a/Material.Blazor.MD3/package-lock.json +++ b/Material.Blazor.MD3/package-lock.json @@ -16,27 +16,27 @@ "@babel/plugin-transform-runtime": "^7.24.0", "@babel/preset-env": "^7.24.0", "@babel/preset-typescript": "^7.23.3", - "@material/web": "^1.3.1-nightly.c3d303e.0", + "@material/web": "^1.3.1-nightly.34c0a67.0", "babel-loader": "^9.1.3", "fork-ts-checker-webpack-plugin": "^9.0.2", "material-components-web": "14.0.0", "regexp": "^1.0.0", "sass": "1.39.2", - "terser": "^5.28.1", + "terser": "^5.29.1", "ts-loader": "^9.5.1", - "typescript": "^5.3.3", + "typescript": "^5.4.2", "webpack": "^5.90.3", "webpack-cli": "^5.1.4" } }, "node_modules/@ampproject/remapping": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", - "integrity": "sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", + "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", "dev": true, "dependencies": { - "@jridgewell/gen-mapping": "^0.3.0", - "@jridgewell/trace-mapping": "^0.3.9" + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" }, "engines": { "node": ">=6.0.0" @@ -1822,14 +1822,14 @@ } }, "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.4.tgz", - "integrity": "sha512-Oud2QPM5dHviZNn4y/WhhYKSXksv+1xLEIsNrAbGcFzUN3ubqWRFT5gwPchNc5NuzILOU4tPBDTZ4VwhL8Y7cw==", + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", "dev": true, "dependencies": { - "@jridgewell/set-array": "^1.0.1", + "@jridgewell/set-array": "^1.2.1", "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" + "@jridgewell/trace-mapping": "^0.3.24" }, "engines": { "node": ">=6.0.0" @@ -1870,9 +1870,9 @@ "dev": true }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.23", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.23.tgz", - "integrity": "sha512-9/4foRoUKp8s96tSkh8DlAAc5A0Ty8vLXld+l9gjKKY6ckwI8G15f0hskGmuLZu78ZlGa1vtsfOa+lnB4vG6Jg==", + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", "dev": true, "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", @@ -2679,9 +2679,9 @@ } }, "node_modules/@material/web": { - "version": "1.3.1-nightly.c3d303e.0", - "resolved": "https://registry.npmjs.org/@material/web/-/web-1.3.1-nightly.c3d303e.0.tgz", - "integrity": "sha512-f9bP2ajpebxznK6usyCgXNRBxb3oGiGRZIpsQT6FbGb0U1PF6B+CRpVCwcxmPPwucnbnkHRIDqfALeDw8EeLAg==", + "version": "1.3.1-nightly.ec0a8eb.0", + "resolved": "https://registry.npmjs.org/@material/web/-/web-1.3.1-nightly.ec0a8eb.0.tgz", + "integrity": "sha512-DMTuCTrsB9qIXEnIEoPNIYeYv3FwAvQlmWgkUtz0/ZS0YQX/UF8q+OS6aCjGPgQtbw31x5n/r3MFcAHCU+2ACA==", "dev": true, "dependencies": { "lit": "^2.7.4 || ^3.0.0", @@ -2728,9 +2728,9 @@ "dev": true }, "node_modules/@types/node": { - "version": "20.11.24", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.24.tgz", - "integrity": "sha512-Kza43ewS3xoLgCEpQrsT+xRo/EJej1y0kVYGiLFE1NEODXGzTfwiC6tXTLMQskn1X4/Rjlh0MQUvx9W+L9long==", + "version": "20.11.25", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.25.tgz", + "integrity": "sha512-TBHyJxk2b7HceLVGFcpAUjsa5zIdsPWlR6XHfyGzd0SFu+/NFgQgMAl96MSDZgQDvJAvV6BKsFOrt6zIL09JDw==", "dev": true, "dependencies": { "undici-types": "~5.26.4" @@ -3182,9 +3182,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001591", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001591.tgz", - "integrity": "sha512-PCzRMei/vXjJyL5mJtzNiUCKP59dm8Apqc3PH8gJkMnMXZGox93RbE76jHsmLwmIo6/3nsYIpJtx0O7u5PqFuQ==", + "version": "1.0.30001596", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001596.tgz", + "integrity": "sha512-zpkZ+kEr6We7w63ORkoJ2pOfBwBkY/bJrG/UZ90qNb45Isblu8wzDgevEOrRL1r9dWayHjYiiyCMEXPn4DweGQ==", "dev": true, "funding": [ { @@ -3390,9 +3390,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.4.687", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.687.tgz", - "integrity": "sha512-Ic85cOuXSP6h7KM0AIJ2hpJ98Bo4hyTUjc4yjMbkvD+8yTxEhfK9+8exT2KKYsSjnCn2tGsKVSZwE7ZgTORQCw==", + "version": "1.4.695", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.695.tgz", + "integrity": "sha512-eMijZmeqPtm774pCZIOrfUHMs/7ls++W1sLhxwqgu8KQ8E2WmMtzwyqOMt0XXUJ3HTIPfuwlfwF+I5cwnfItBA==", "dev": true }, "node_modules/enhanced-resolve": { @@ -4995,9 +4995,9 @@ } }, "node_modules/terser": { - "version": "5.28.1", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.28.1.tgz", - "integrity": "sha512-wM+bZp54v/E9eRRGXb5ZFDvinrJIOaTapx3WUokyVGZu5ucVCK55zEgGd5Dl2fSr3jUo5sDiERErUWLY6QPFyA==", + "version": "5.29.1", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.29.1.tgz", + "integrity": "sha512-lZQ/fyaIGxsbGxApKmoPTODIzELy3++mXhS5hOqaAWZjQtpq/hFHAc+rm29NND1rYRxRWKcjuARNwULNXa5RtQ==", "dev": true, "dependencies": { "@jridgewell/source-map": "^0.3.3", @@ -5261,9 +5261,9 @@ "dev": true }, "node_modules/typescript": { - "version": "5.3.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz", - "integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==", + "version": "5.4.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.2.tgz", + "integrity": "sha512-+2/g0Fds1ERlP6JsakQQDXjZdZMM+rqpamFZJEKh4kwTIn3iDkgKtby0CeNd5ATNZ4Ry1ax15TMx0W2V+miizQ==", "dev": true, "bin": { "tsc": "bin/tsc", diff --git a/Material.Blazor.MD3/package.json b/Material.Blazor.MD3/package.json index 2533c9d6b..a90092424 100644 --- a/Material.Blazor.MD3/package.json +++ b/Material.Blazor.MD3/package.json @@ -26,15 +26,15 @@ "@babel/plugin-transform-runtime": "^7.24.0", "@babel/preset-env": "^7.24.0", "@babel/preset-typescript": "^7.23.3", - "@material/web": "^1.3.1-nightly.c3d303e.0", + "@material/web": "^1.3.1-nightly.34c0a67.0", "babel-loader": "^9.1.3", "fork-ts-checker-webpack-plugin": "^9.0.2", "material-components-web": "14.0.0", "regexp": "^1.0.0", "sass": "1.39.2", - "terser": "^5.28.1", + "terser": "^5.29.1", "ts-loader": "^9.5.1", - "typescript": "^5.3.3", + "typescript": "^5.4.2", "webpack": "^5.90.3", "webpack-cli": "^5.1.4" } diff --git a/Material.Blazor.Test/Material.Blazor.Test.csproj b/Material.Blazor.Test/Material.Blazor.Test.csproj index 1aebf2951..406f1fc4f 100644 --- a/Material.Blazor.Test/Material.Blazor.Test.csproj +++ b/Material.Blazor.Test/Material.Blazor.Test.csproj @@ -4,9 +4,9 @@ - - - + + + diff --git a/Material.Blazor.Test/Mocking.cs b/Material.Blazor.Test/Mocking.cs index c797de268..d29f8096b 100644 --- a/Material.Blazor.Test/Mocking.cs +++ b/Material.Blazor.Test/Mocking.cs @@ -1,8 +1,9 @@ using Bunit; -using Material.Blazor; using Material.Blazor.Internal; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; +using Microsoft.JSInterop; + using NSubstitute; using System.Globalization; using Xunit; @@ -14,6 +15,11 @@ public class Mocking private TestContext ctx; private void InjectMockedServices() { + _ = new BunitJSInterop + { + Mode = JSRuntimeMode.Loose + }; + var cultureInfo = new CultureInfo("en-US"); CultureInfo.DefaultThreadCurrentCulture = cultureInfo; @@ -27,8 +33,11 @@ private void InjectMockedServices() .AddSingleton(Substitute.For()) .AddSingleton(Substitute.For>()) .AddSingleton(Substitute.For()) - .AddSingleton(Substitute.For()); + .AddSingleton(Substitute.For()) + .AddSingleton(Substitute.For()); } + + [Fact] public void TryRenderMBAnchor() { @@ -286,6 +295,7 @@ public void TryRenderMBDatePicker() { InjectMockedServices(); var cut = ctx.RenderComponent(); + cut.MarkupMatches(@"
@@ -303,18 +313,17 @@ public void TryRenderMBDatePicker()
-
+
  • - Monday, January 1, 0001 + Monday, January 1, 0001
-
-
+
"); } @@ -561,7 +570,7 @@ public void TryRenderMBSlider()
-
+
diff --git a/Material.Blazor.Website.MD3/Pages/Roadmap.razor.cs b/Material.Blazor.Website.MD3/Pages/Roadmap.razor.cs index 091f7cec8..2057c9603 100644 --- a/Material.Blazor.Website.MD3/Pages/Roadmap.razor.cs +++ b/Material.Blazor.Website.MD3/Pages/Roadmap.razor.cs @@ -9,7 +9,7 @@ public partial class Roadmap public Roadmap() { var rawMarkDown = @" -# Version 2024-02-10 +# Version 2024-03-06 # About Material 3 @@ -110,13 +110,11 @@ Time picker | 🟡 | Future | 💤 | 💤 | DragAndDropList | 🟢 | n/a | n/a | 💤 | Drawer | 🟢 | n/a | n/a | 💤 | FileUpload | 🟢 | n/a | n/a | 💤 | -Grid | 🟢 | n/a | n/a | 🟢 | IconButtonToggle | 🟢 | n/a | n/a | 💤 | IntField | 🟢 | n/a | n/a | 🟡 | Density and supporting text persistence | PagedDataList | 🟢 | n/a | n/a | 💤 | Paginator | 🟢 | n/a | n/a | 💤 | RadioButtonGroup | 🟢 | n/a | n/a | 🟡 | Density | -Scheduler | 🟢 | n/a | n/a | 💤 | SegmentedButtonMulti | 🟢 | n/a | n/a | 💤 | Shield | 🟢 | n/a | n/a | 💤 | Slider | 🟢 | n/a | n/a | 💤 | diff --git a/Material.Blazor.Website.MD3/package-lock.json b/Material.Blazor.Website.MD3/package-lock.json index f8cca95bc..04eb0ddc3 100644 --- a/Material.Blazor.Website.MD3/package-lock.json +++ b/Material.Blazor.Website.MD3/package-lock.json @@ -21,21 +21,21 @@ "material-components-web": "14.0.0", "regexp": "^1.0.0", "sass": "1.39.2", - "terser": "^5.28.1", + "terser": "^5.29.1", "ts-loader": "^9.5.1", - "typescript": "^5.3.3", + "typescript": "^5.4.2", "webpack": "^5.90.3", "webpack-cli": "^5.1.4" } }, "node_modules/@ampproject/remapping": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", - "integrity": "sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", + "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", "dev": true, "dependencies": { - "@jridgewell/gen-mapping": "^0.3.0", - "@jridgewell/trace-mapping": "^0.3.9" + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" }, "engines": { "node": ">=6.0.0" @@ -1821,14 +1821,14 @@ } }, "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.4.tgz", - "integrity": "sha512-Oud2QPM5dHviZNn4y/WhhYKSXksv+1xLEIsNrAbGcFzUN3ubqWRFT5gwPchNc5NuzILOU4tPBDTZ4VwhL8Y7cw==", + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", "dev": true, "dependencies": { - "@jridgewell/set-array": "^1.0.1", + "@jridgewell/set-array": "^1.2.1", "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" + "@jridgewell/trace-mapping": "^0.3.24" }, "engines": { "node": ">=6.0.0" @@ -1869,9 +1869,9 @@ "dev": true }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.23", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.23.tgz", - "integrity": "sha512-9/4foRoUKp8s96tSkh8DlAAc5A0Ty8vLXld+l9gjKKY6ckwI8G15f0hskGmuLZu78ZlGa1vtsfOa+lnB4vG6Jg==", + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", "dev": true, "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", @@ -2702,9 +2702,9 @@ "dev": true }, "node_modules/@types/node": { - "version": "20.11.24", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.24.tgz", - "integrity": "sha512-Kza43ewS3xoLgCEpQrsT+xRo/EJej1y0kVYGiLFE1NEODXGzTfwiC6tXTLMQskn1X4/Rjlh0MQUvx9W+L9long==", + "version": "20.11.25", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.25.tgz", + "integrity": "sha512-TBHyJxk2b7HceLVGFcpAUjsa5zIdsPWlR6XHfyGzd0SFu+/NFgQgMAl96MSDZgQDvJAvV6BKsFOrt6zIL09JDw==", "dev": true, "dependencies": { "undici-types": "~5.26.4" @@ -3150,9 +3150,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001591", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001591.tgz", - "integrity": "sha512-PCzRMei/vXjJyL5mJtzNiUCKP59dm8Apqc3PH8gJkMnMXZGox93RbE76jHsmLwmIo6/3nsYIpJtx0O7u5PqFuQ==", + "version": "1.0.30001596", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001596.tgz", + "integrity": "sha512-zpkZ+kEr6We7w63ORkoJ2pOfBwBkY/bJrG/UZ90qNb45Isblu8wzDgevEOrRL1r9dWayHjYiiyCMEXPn4DweGQ==", "dev": true, "funding": [ { @@ -3358,9 +3358,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.4.687", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.687.tgz", - "integrity": "sha512-Ic85cOuXSP6h7KM0AIJ2hpJ98Bo4hyTUjc4yjMbkvD+8yTxEhfK9+8exT2KKYsSjnCn2tGsKVSZwE7ZgTORQCw==", + "version": "1.4.695", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.695.tgz", + "integrity": "sha512-eMijZmeqPtm774pCZIOrfUHMs/7ls++W1sLhxwqgu8KQ8E2WmMtzwyqOMt0XXUJ3HTIPfuwlfwF+I5cwnfItBA==", "dev": true }, "node_modules/enhanced-resolve": { @@ -4932,9 +4932,9 @@ } }, "node_modules/terser": { - "version": "5.28.1", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.28.1.tgz", - "integrity": "sha512-wM+bZp54v/E9eRRGXb5ZFDvinrJIOaTapx3WUokyVGZu5ucVCK55zEgGd5Dl2fSr3jUo5sDiERErUWLY6QPFyA==", + "version": "5.29.1", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.29.1.tgz", + "integrity": "sha512-lZQ/fyaIGxsbGxApKmoPTODIzELy3++mXhS5hOqaAWZjQtpq/hFHAc+rm29NND1rYRxRWKcjuARNwULNXa5RtQ==", "dev": true, "dependencies": { "@jridgewell/source-map": "^0.3.3", @@ -5198,9 +5198,9 @@ "dev": true }, "node_modules/typescript": { - "version": "5.3.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz", - "integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==", + "version": "5.4.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.2.tgz", + "integrity": "sha512-+2/g0Fds1ERlP6JsakQQDXjZdZMM+rqpamFZJEKh4kwTIn3iDkgKtby0CeNd5ATNZ4Ry1ax15TMx0W2V+miizQ==", "dev": true, "bin": { "tsc": "bin/tsc", diff --git a/Material.Blazor.Website.MD3/package.json b/Material.Blazor.Website.MD3/package.json index 26fc51558..c20550564 100644 --- a/Material.Blazor.Website.MD3/package.json +++ b/Material.Blazor.Website.MD3/package.json @@ -26,9 +26,9 @@ "material-components-web": "14.0.0", "regexp": "^1.0.0", "sass": "1.39.2", - "terser": "^5.28.1", + "terser": "^5.29.1", "ts-loader": "^9.5.1", - "typescript": "^5.3.3", + "typescript": "^5.4.2", "webpack": "^5.90.3", "webpack-cli": "^5.1.4" } diff --git a/Material.Blazor.Website.Server/Pages/Host.cshtml b/Material.Blazor.Website.Server/Pages/Host.cshtml index 9462089a2..01cc46fbe 100644 --- a/Material.Blazor.Website.Server/Pages/Host.cshtml +++ b/Material.Blazor.Website.Server/Pages/Host.cshtml @@ -13,7 +13,7 @@ } - + diff --git a/Material.Blazor.Website.WebAssembly.MD3/wwwroot/index.html b/Material.Blazor.Website.WebAssembly.MD3/wwwroot/index.html index 6ccc05ce8..05619abf6 100644 --- a/Material.Blazor.Website.WebAssembly.MD3/wwwroot/index.html +++ b/Material.Blazor.Website.WebAssembly.MD3/wwwroot/index.html @@ -1,5 +1,5 @@  - + diff --git a/Material.Blazor.Website/Pages/AutocompletePagedField.razor b/Material.Blazor.Website/Pages/AutocompletePagedField.razor index 5f170bf50..588047285 100644 --- a/Material.Blazor.Website/Pages/AutocompletePagedField.razor +++ b/Material.Blazor.Website/Pages/AutocompletePagedField.razor @@ -182,7 +182,9 @@ // A delay to mimic waiting for a database to respond await Task.Delay(200); - var fullMatchRegex = new Regex($"^{searchString}$", RegexOptions); + var escapedSearchString = Regex.Escape(searchString); + + var fullMatchRegex = new Regex($"^{escapedSearchString}$", RegexOptions); var fullMatchCity = AutocompleteSelectField.CitiesDict.Where(x => fullMatchRegex.Matches(x.Value.SearchTarget).Any()).FirstOrDefault().Value; if (fullMatchCity != default) @@ -200,7 +202,7 @@ }); } - var partialMatchRegex = new Regex(searchString, RegexOptions); + var partialMatchRegex = new Regex(escapedSearchString, RegexOptions); var partialMatchCities = AutocompleteSelectField.CitiesDict.Where(x => partialMatchRegex.Matches(x.Value.SearchTarget).Any()).Select(x => x.Value).OrderBy(x => x.FullName).ToList(); AllMatchingCityNames = partialMatchCities.Select(x => x.FullName).ToList(); _ = InvokeAsync(StateHasChanged); diff --git a/Material.Blazor.Website/Pages/AutocompleteSelectField.razor b/Material.Blazor.Website/Pages/AutocompleteSelectField.razor index 2099a8924..e1a0ab521 100644 --- a/Material.Blazor.Website/Pages/AutocompleteSelectField.razor +++ b/Material.Blazor.Website/Pages/AutocompleteSelectField.razor @@ -191,7 +191,9 @@ // A delay to mimic waiting for a database to respond await Task.Delay(200); - var fullMatchRegex = new Regex($"^{searchString}$", RegexOptions); + var escapedSearchString = Regex.Escape(searchString); + + var fullMatchRegex = new Regex($"^{escapedSearchString}$", RegexOptions); var fullMatchCity = CitiesDict.Where(x => fullMatchRegex.Matches(x.Value.SearchTarget).Any()).FirstOrDefault().Value; if (fullMatchCity != default) @@ -208,7 +210,7 @@ }; } - var partialMatchRegex = new Regex(searchString, RegexOptions); + var partialMatchRegex = new Regex(escapedSearchString, RegexOptions); var partialMatchCities = CitiesDict.Where(x => partialMatchRegex.Matches(x.Value.SearchTarget).Any()).Select(x => x.Value).OrderBy(x => x.FullName).ToList(); AllMatchingCityNames = partialMatchCities.Select(x => x.FullName).ToList(); _ = InvokeAsync(StateHasChanged); diff --git a/Material.Blazor.Website/Pages/PagedDataList.razor b/Material.Blazor.Website/Pages/PagedDataList.razor index 111fa41f9..905d6ec81 100644 --- a/Material.Blazor.Website/Pages/PagedDataList.razor +++ b/Material.Blazor.Website/Pages/PagedDataList.razor @@ -8,13 +8,17 @@ margin-bottom: 1rem; } - .my-float-right { + .my-float-end { float: right; } - .my-float-right .mb-paginator { - justify-content: flex-end; - } + [dir="rtl"] .my-float-end { + float: left; + } + + .my-float-end .mb-paginator { + justify-content: flex-end; + } .my-full-width { min-width: 100%; @@ -60,7 +64,7 @@ class="my-container" Data=@Colors ItemsPerPageSelection="@ColorsItemsPerPageSelection" - PaginatorClass="my-float-right" + PaginatorClass="my-float-end" @ref="@ColorsPagedDataList"> @@ -104,7 +108,7 @@ Data=@People ItemsPerPageSelection="@PersonItemsPerPageSelection" ListTemplateClass="my-container" - PaginatorClass="my-float-right" + PaginatorClass="my-float-end" @ref="TwinListData"> @@ -168,7 +172,7 @@ class="my-container" Data=@People ItemsPerPageSelection="@PersonItemsPerPageSelection" - PaginatorClass="my-float-right" + PaginatorClass="my-float-end" @ref="DataTableList"> @@ -215,7 +219,7 @@ class="my-container" Data=@People ItemsPerPageSelection="@PersonItemsPerPageSelection" - PaginatorClass="my-float-right"> + PaginatorClass="my-float-end"> @@ -262,7 +266,7 @@ class="my-container" Data=@People ItemsPerPageSelection="@PersonItemsPerPageSelection" - PaginatorClass="my-float-right"> + PaginatorClass="my-float-end">
  • @@ -293,7 +297,7 @@ class="my-container" Data=@People ItemsPerPageSelection="@PersonItemsPerPageSelection" - PaginatorClass="my-float-right"> + PaginatorClass="my-float-end">

    diff --git a/Material.Blazor.Website/Pages/Paginator.razor b/Material.Blazor.Website/Pages/Paginator.razor index b9eba166e..1ba4094ed 100644 --- a/Material.Blazor.Website/Pages/Paginator.razor +++ b/Material.Blazor.Website/Pages/Paginator.razor @@ -4,13 +4,17 @@ +

    + Selected items: @string.Join(" / ", PaginatorSelection) +

    +

    - -

    - Selected items: @string.Join(" / ", PaginatorSelection) -

    diff --git a/Material.Blazor.Website/Scripts/MBTheme.ts b/Material.Blazor.Website/Scripts/MBTheme.ts index bf37986cc..4059faf9c 100644 --- a/Material.Blazor.Website/Scripts/MBTheme.ts +++ b/Material.Blazor.Website/Scripts/MBTheme.ts @@ -7,3 +7,8 @@ document.getElementById("app-style")?.setAttribute("href", "_content/Material.Blazor.Website/css/" + sheetName + extension); } + +export function setHtmlBlockTextDirection(textDirection): void { + let htmlElement = document.documentElement; + htmlElement.setAttribute("dir", textDirection); +} \ No newline at end of file diff --git a/Material.Blazor.Website/Scripts/Material.Blazor.Website.ts b/Material.Blazor.Website/Scripts/Material.Blazor.Website.ts index ebbe8d29c..aee732167 100644 --- a/Material.Blazor.Website/Scripts/Material.Blazor.Website.ts +++ b/Material.Blazor.Website/Scripts/Material.Blazor.Website.ts @@ -2,4 +2,4 @@ (window).MaterialBlazorWebsite = { MBTheme -}; +}; \ No newline at end of file diff --git a/Material.Blazor.Website/Shared/DemonstrationPage.razor b/Material.Blazor.Website/Shared/DemonstrationPage.razor index d3227f512..da630cd1c 100644 --- a/Material.Blazor.Website/Shared/DemonstrationPage.razor +++ b/Material.Blazor.Website/Shared/DemonstrationPage.razor @@ -13,8 +13,8 @@ {

    + Context="item" + class="dr-table">

  • @@ -39,7 +39,7 @@ {

    + Items="@Densities" />

    } @@ -63,8 +63,4 @@ @PageContent - - - -@code { -} + \ No newline at end of file diff --git a/Material.Blazor.Website/Shared/DemonstrationPage.razor.cs b/Material.Blazor.Website/Shared/DemonstrationPage.razor.cs index 148bc3890..17dcb8050 100644 --- a/Material.Blazor.Website/Shared/DemonstrationPage.razor.cs +++ b/Material.Blazor.Website/Shared/DemonstrationPage.razor.cs @@ -1,8 +1,9 @@ using Microsoft.AspNetCore.Components; -using System; +using Microsoft.JSInterop; + using System.Collections.Generic; +using System.Globalization; using System.Linq; -using System.Text; using System.Threading.Tasks; namespace Material.Blazor.Website.Shared @@ -11,6 +12,7 @@ public partial class DemonstrationPage { [Inject] private NavigationManager NavigationManager { get; set; } + [CascadingParameter(Name = "MaterialDocRef")] private string MaterialDocRef { get; set; } [Parameter] public string ComponentAndPageName { get; set; } @@ -36,11 +38,7 @@ public partial class DemonstrationPage [Parameter] public string Title { get; set; } - private MBCascadingDefaults CascadingDefaults { get; set; } = new MBCascadingDefaults() - { - ThemeDensity = MBDensity.Default, - Disabled = false - }; + private MBCascadingDefaults CascadingDefaults { get; set; } private class ReferenceItem @@ -62,6 +60,9 @@ private class ReferenceItem (MaterialIOPage != null)); + private bool IsRTL { get; set; } = false; + + protected override void OnInitialized() { Items = new List(); @@ -73,7 +74,7 @@ protected override void OnInitialized() var baseURI = NavigationManager.BaseUri; - if ((ComponentAndPageName != null) && SuppressComponentDocumentation) + if ((ComponentAndPageName != null) && !SuppressComponentDocumentation) { Items.Add(new ReferenceItem { @@ -91,12 +92,6 @@ protected override void OnInitialized() }); } - Items.Add(new ReferenceItem - { - Title = "Source for This Page", - Content = $"GitHub source page link" - }); - if (DetailedArticle != null) { Items.Add(new ReferenceItem @@ -126,15 +121,23 @@ protected override void OnInitialized() }); } - Densities = new MBSelectElement[] - { - new MBSelectElement {SelectedValue = MBDensity.Default, Label = "Default", Disabled = false }, - new MBSelectElement {SelectedValue = MBDensity.Minus1, Label = "Minus 1", Disabled = MinDensity > MBDensity.Minus1 }, - new MBSelectElement {SelectedValue = MBDensity.Minus2, Label = "Minus 2", Disabled = MinDensity > MBDensity.Minus2 }, - new MBSelectElement {SelectedValue = MBDensity.Minus3, Label = "Minus 3", Disabled = MinDensity > MBDensity.Minus3 }, - new MBSelectElement {SelectedValue = MBDensity.Minus4, Label = "Minus 4", Disabled = MinDensity > MBDensity.Minus4 }, - new MBSelectElement {SelectedValue = MBDensity.Minus5, Label = "Minus 5", Disabled = MinDensity > MBDensity.Minus5 }, - }.Where(d => d.Disabled != true); + Densities = + [ + new() {SelectedValue = MBDensity.Default, Label = "Default", Disabled = false }, + new() {SelectedValue = MBDensity.Minus1, Label = "Minus 1", Disabled = MinDensity > MBDensity.Minus1 }, + new() {SelectedValue = MBDensity.Minus2, Label = "Minus 2", Disabled = MinDensity > MBDensity.Minus2 }, + new() {SelectedValue = MBDensity.Minus3, Label = "Minus 3", Disabled = MinDensity > MBDensity.Minus3 }, + new() {SelectedValue = MBDensity.Minus4, Label = "Minus 4", Disabled = MinDensity > MBDensity.Minus4 }, + new() {SelectedValue = MBDensity.Minus5, Label = "Minus 5", Disabled = MinDensity > MBDensity.Minus5 }, + ]; + + Densities = Densities.Where(d => d.Disabled != true); + + CascadingDefaults = new MBCascadingDefaults() + { + ThemeDensity = MBDensity.Default, + Disabled = false, + }; } } } diff --git a/Material.Blazor.Website/Shared/MainLayout.razor b/Material.Blazor.Website/Shared/MainLayout.razor index e7ae0171c..ce94d4ff5 100644 --- a/Material.Blazor.Website/Shared/MainLayout.razor +++ b/Material.Blazor.Website/Shared/MainLayout.razor @@ -75,6 +75,7 @@ class="app-bar mdc-top-app-bar--short-has-action-item mdc-elevation--z5"> diff --git a/Material.Blazor.Website/Shared/MainLayout.razor.cs b/Material.Blazor.Website/Shared/MainLayout.razor.cs index cd65bce1a..9ece913d6 100644 --- a/Material.Blazor.Website/Shared/MainLayout.razor.cs +++ b/Material.Blazor.Website/Shared/MainLayout.razor.cs @@ -1,15 +1,24 @@ -using Microsoft.JSInterop; +using Microsoft.AspNetCore.Components; +using Microsoft.JSInterop; + +using System.ComponentModel; using System.Threading.Tasks; namespace Material.Blazor.Website.Shared { public partial class MainLayout { + [Inject] private IJSRuntime JSRuntime { get; set; } + + + private const string materialDocRef = "https://github.com/material-components/material-components-web/tree/master/packages/"; private MBDrawer Drawer { get; set; } private MBMenu Menu { get; set; } private string Theme { get; set; } = "material-default-theme"; + private bool IsRTL { get; set; } = false; + private async Task OpenMenuAsync() { await Menu.ToggleAsync(); @@ -33,5 +42,11 @@ private void SideBarToggle() { Drawer.Toggle(); } + + private ValueTask ToggleRTL() + { + IsRTL = !IsRTL; + return JSRuntime.InvokeVoidAsync("MaterialBlazorWebsite.MBTheme.setHtmlBlockTextDirection", IsRTL ? "rtl" : "ltr"); + } } } diff --git a/Material.Blazor.Website/package-lock.json b/Material.Blazor.Website/package-lock.json index f8cca95bc..04eb0ddc3 100644 --- a/Material.Blazor.Website/package-lock.json +++ b/Material.Blazor.Website/package-lock.json @@ -21,21 +21,21 @@ "material-components-web": "14.0.0", "regexp": "^1.0.0", "sass": "1.39.2", - "terser": "^5.28.1", + "terser": "^5.29.1", "ts-loader": "^9.5.1", - "typescript": "^5.3.3", + "typescript": "^5.4.2", "webpack": "^5.90.3", "webpack-cli": "^5.1.4" } }, "node_modules/@ampproject/remapping": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", - "integrity": "sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", + "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", "dev": true, "dependencies": { - "@jridgewell/gen-mapping": "^0.3.0", - "@jridgewell/trace-mapping": "^0.3.9" + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" }, "engines": { "node": ">=6.0.0" @@ -1821,14 +1821,14 @@ } }, "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.4.tgz", - "integrity": "sha512-Oud2QPM5dHviZNn4y/WhhYKSXksv+1xLEIsNrAbGcFzUN3ubqWRFT5gwPchNc5NuzILOU4tPBDTZ4VwhL8Y7cw==", + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", "dev": true, "dependencies": { - "@jridgewell/set-array": "^1.0.1", + "@jridgewell/set-array": "^1.2.1", "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" + "@jridgewell/trace-mapping": "^0.3.24" }, "engines": { "node": ">=6.0.0" @@ -1869,9 +1869,9 @@ "dev": true }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.23", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.23.tgz", - "integrity": "sha512-9/4foRoUKp8s96tSkh8DlAAc5A0Ty8vLXld+l9gjKKY6ckwI8G15f0hskGmuLZu78ZlGa1vtsfOa+lnB4vG6Jg==", + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", "dev": true, "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", @@ -2702,9 +2702,9 @@ "dev": true }, "node_modules/@types/node": { - "version": "20.11.24", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.24.tgz", - "integrity": "sha512-Kza43ewS3xoLgCEpQrsT+xRo/EJej1y0kVYGiLFE1NEODXGzTfwiC6tXTLMQskn1X4/Rjlh0MQUvx9W+L9long==", + "version": "20.11.25", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.25.tgz", + "integrity": "sha512-TBHyJxk2b7HceLVGFcpAUjsa5zIdsPWlR6XHfyGzd0SFu+/NFgQgMAl96MSDZgQDvJAvV6BKsFOrt6zIL09JDw==", "dev": true, "dependencies": { "undici-types": "~5.26.4" @@ -3150,9 +3150,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001591", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001591.tgz", - "integrity": "sha512-PCzRMei/vXjJyL5mJtzNiUCKP59dm8Apqc3PH8gJkMnMXZGox93RbE76jHsmLwmIo6/3nsYIpJtx0O7u5PqFuQ==", + "version": "1.0.30001596", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001596.tgz", + "integrity": "sha512-zpkZ+kEr6We7w63ORkoJ2pOfBwBkY/bJrG/UZ90qNb45Isblu8wzDgevEOrRL1r9dWayHjYiiyCMEXPn4DweGQ==", "dev": true, "funding": [ { @@ -3358,9 +3358,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.4.687", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.687.tgz", - "integrity": "sha512-Ic85cOuXSP6h7KM0AIJ2hpJ98Bo4hyTUjc4yjMbkvD+8yTxEhfK9+8exT2KKYsSjnCn2tGsKVSZwE7ZgTORQCw==", + "version": "1.4.695", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.695.tgz", + "integrity": "sha512-eMijZmeqPtm774pCZIOrfUHMs/7ls++W1sLhxwqgu8KQ8E2WmMtzwyqOMt0XXUJ3HTIPfuwlfwF+I5cwnfItBA==", "dev": true }, "node_modules/enhanced-resolve": { @@ -4932,9 +4932,9 @@ } }, "node_modules/terser": { - "version": "5.28.1", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.28.1.tgz", - "integrity": "sha512-wM+bZp54v/E9eRRGXb5ZFDvinrJIOaTapx3WUokyVGZu5ucVCK55zEgGd5Dl2fSr3jUo5sDiERErUWLY6QPFyA==", + "version": "5.29.1", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.29.1.tgz", + "integrity": "sha512-lZQ/fyaIGxsbGxApKmoPTODIzELy3++mXhS5hOqaAWZjQtpq/hFHAc+rm29NND1rYRxRWKcjuARNwULNXa5RtQ==", "dev": true, "dependencies": { "@jridgewell/source-map": "^0.3.3", @@ -5198,9 +5198,9 @@ "dev": true }, "node_modules/typescript": { - "version": "5.3.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz", - "integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==", + "version": "5.4.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.2.tgz", + "integrity": "sha512-+2/g0Fds1ERlP6JsakQQDXjZdZMM+rqpamFZJEKh4kwTIn3iDkgKtby0CeNd5ATNZ4Ry1ax15TMx0W2V+miizQ==", "dev": true, "bin": { "tsc": "bin/tsc", diff --git a/Material.Blazor.Website/package.json b/Material.Blazor.Website/package.json index 6ccc05e5c..33e6b384c 100644 --- a/Material.Blazor.Website/package.json +++ b/Material.Blazor.Website/package.json @@ -32,9 +32,9 @@ "material-components-web": "14.0.0", "regexp": "^1.0.0", "sass": "1.39.2", - "terser": "^5.28.1", + "terser": "^5.29.1", "ts-loader": "^9.5.1", - "typescript": "^5.3.3", + "typescript": "^5.4.2", "webpack": "^5.90.3", "webpack-cli": "^5.1.4" } diff --git a/Material.Blazor.Website/wwwroot/icons/favicon-16x16.png b/Material.Blazor.Website/wwwroot/icons/favicon-16x16.png deleted file mode 100644 index b5bbe0dbc..000000000 Binary files a/Material.Blazor.Website/wwwroot/icons/favicon-16x16.png and /dev/null differ diff --git a/Material.Blazor.Website/wwwroot/icons/favicon-32x32.png b/Material.Blazor.Website/wwwroot/icons/favicon-32x32.png deleted file mode 100644 index 6a14e1c81..000000000 Binary files a/Material.Blazor.Website/wwwroot/icons/favicon-32x32.png and /dev/null differ diff --git a/Material.Blazor.Website/wwwroot/icons/icon-512.png b/Material.Blazor.Website/wwwroot/icons/icon-512.png deleted file mode 100644 index 579bd8815..000000000 Binary files a/Material.Blazor.Website/wwwroot/icons/icon-512.png and /dev/null differ diff --git a/Material.Blazor.Website/wwwroot/images/book-shelves.jpg b/Material.Blazor.Website/wwwroot/images/book-shelves.jpg deleted file mode 100644 index 983014461..000000000 Binary files a/Material.Blazor.Website/wwwroot/images/book-shelves.jpg and /dev/null differ diff --git a/Material.Blazor.Website/wwwroot/images/mac.jpg b/Material.Blazor.Website/wwwroot/images/mac.jpg deleted file mode 100644 index cad0a7c2f..000000000 Binary files a/Material.Blazor.Website/wwwroot/images/mac.jpg and /dev/null differ diff --git a/Material.Blazor.Website/wwwroot/js/material.blazor.website.js b/Material.Blazor.Website/wwwroot/js/material.blazor.website.js index e381696ba..f48f6e77f 100644 --- a/Material.Blazor.Website/wwwroot/js/material.blazor.website.js +++ b/Material.Blazor.Website/wwwroot/js/material.blazor.website.js @@ -39,6 +39,7 @@ var __webpack_exports__ = {}; var MBTheme_namespaceObject = {}; __webpack_require__.r(MBTheme_namespaceObject); __webpack_require__.d(MBTheme_namespaceObject, { + setHtmlBlockTextDirection: () => (setHtmlBlockTextDirection), setTheme: () => (setTheme) }); @@ -51,6 +52,10 @@ function setTheme(sheetName, minify) { } (_document$getElementB = document.getElementById("app-style")) === null || _document$getElementB === void 0 || _document$getElementB.setAttribute("href", "_content/Material.Blazor.Website/css/" + sheetName + extension); } +function setHtmlBlockTextDirection(textDirection) { + var htmlElement = document.documentElement; + htmlElement.setAttribute("dir", textDirection); +} ;// CONCATENATED MODULE: ./scripts/material.blazor.website.ts window.MaterialBlazorWebsite = { diff --git a/Material.Blazor.Website/wwwroot/js/material.blazor.website.min.js b/Material.Blazor.Website/wwwroot/js/material.blazor.website.min.js index 67f99a3a6..3a6a849ed 100644 --- a/Material.Blazor.Website/wwwroot/js/material.blazor.website.min.js +++ b/Material.Blazor.Website/wwwroot/js/material.blazor.website.min.js @@ -1 +1 @@ -(()=>{"use strict";var e={d:(t,o)=>{for(var r in o)e.o(o,r)&&!e.o(t,r)&&Object.defineProperty(t,r,{enumerable:!0,get:o[r]})},o:(e,t)=>Object.prototype.hasOwnProperty.call(e,t),r:e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})}},t={};function o(e,t){var o,r=".css";!0===t&&(r=".min.css"),null===(o=document.getElementById("app-style"))||void 0===o||o.setAttribute("href","_content/Material.Blazor.Website/css/"+e+r)}e.r(t),e.d(t,{setTheme:()=>o}),window.MaterialBlazorWebsite={MBTheme:t}})(); \ No newline at end of file +(()=>{"use strict";var e={d:(t,o)=>{for(var r in o)e.o(o,r)&&!e.o(t,r)&&Object.defineProperty(t,r,{enumerable:!0,get:o[r]})},o:(e,t)=>Object.prototype.hasOwnProperty.call(e,t),r:e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})}},t={};function o(e,t){var o,r=".css";!0===t&&(r=".min.css"),null===(o=document.getElementById("app-style"))||void 0===o||o.setAttribute("href","_content/Material.Blazor.Website/css/"+e+r)}function r(e){document.documentElement.setAttribute("dir",e)}e.r(t),e.d(t,{setHtmlBlockTextDirection:()=>r,setTheme:()=>o}),window.MaterialBlazorWebsite={MBTheme:t}})(); \ No newline at end of file diff --git a/Material.Blazor/Components/AutocompleteTextField/MBAutocompleteTextField.razor.cs b/Material.Blazor/Components/AutocompleteTextField/MBAutocompleteTextField.razor.cs index 3b276b512..26e4d0983 100644 --- a/Material.Blazor/Components/AutocompleteTextField/MBAutocompleteTextField.razor.cs +++ b/Material.Blazor/Components/AutocompleteTextField/MBAutocompleteTextField.razor.cs @@ -214,9 +214,12 @@ private void SetParameters() private SelectionInfo BuildSelectList(string fieldText) { + + var escapedFieldText = Regex.Escape(fieldText ?? ""); + var regexOptions = RegexOptions.IgnoreCase | (IgnoreWhitespace ? RegexOptions.IgnorePatternWhitespace : 0); - var fullMatchRegex = new Regex($"^{fieldText}$", regexOptions); + var fullMatchRegex = new Regex($"^{escapedFieldText}$", regexOptions); var fullMatches = (from f in DisplaySelectionItems where fullMatchRegex.Matches(f.SearchTarget).Count > 0 select f.Item).ToArray(); @@ -231,14 +234,14 @@ where fullMatchRegex.Matches(f.SearchTarget).Count > 0 } var startMatch = MatchFromItemStart ? "^" : ""; - var partialMatchRegex = new Regex($"{startMatch}{fieldText}", regexOptions); + var partialMatchRegex = new Regex($"{startMatch}{escapedFieldText}", regexOptions); var partialMatches = (from f in DisplaySelectionItems where partialMatchRegex.Matches(f.SearchTarget).Count > 0 select f.Item).ToArray(); - var firstValueIsCustomValue = AllowCustomValue && fieldText != null && !partialMatches.Contains(fieldText); + var firstValueIsCustomValue = AllowCustomValue && escapedFieldText != null && !partialMatches.Contains(escapedFieldText); if (firstValueIsCustomValue) { - partialMatches = partialMatches.Prepend(fieldText).ToArray(); + partialMatches = partialMatches.Prepend(escapedFieldText).ToArray(); } return new SelectionInfo() diff --git a/Material.Blazor/Components/Badge/MBBadge.scss b/Material.Blazor/Components/Badge/MBBadge.scss index fad15e4ed..88a1c41f2 100644 --- a/Material.Blazor/Components/Badge/MBBadge.scss +++ b/Material.Blazor/Components/Badge/MBBadge.scss @@ -28,11 +28,21 @@ $icon-button-offset: 4px; pointer-events: none; } +[dir="rtl"] .mb-badge-container { + left: auto; + right: 0; +} + .mdc-icon-button { .mb-badge-container { top: $icon-button-offset; left: -$icon-button-offset; } + + [dir="rtl"] .mb-badge-container { + left: auto; + right: -$icon-button-offset; + } } .mb-badge { @@ -71,6 +81,17 @@ $icon-button-offset: 4px; } } +[dir="rtl"] .mb-badge { + float: left; + right: auto; + left: -$regular-offset; + + &.mb-badge--dot { + left: -$dot-offset; + right: auto; + } +} + .mb-badge-value { padding: 0px 6px; } diff --git a/Material.Blazor/Components/Carousel/MBCarousel.razor b/Material.Blazor/Components/Carousel/MBCarousel.razor index ef4ca8f4e..93d89377d 100644 --- a/Material.Blazor/Components/Carousel/MBCarousel.razor +++ b/Material.Blazor/Components/Carousel/MBCarousel.razor @@ -4,7 +4,8 @@ @typeparam TItem @@ -93,7 +93,7 @@ {
    - @foreach (var d in DaysOfWeek) + @foreach (var d in DaysOfWeek()) { @d } diff --git a/Material.Blazor/Components/DatePicker/InternalDatePickerPanel.razor.cs b/Material.Blazor/Components/DatePicker/InternalDatePickerPanel.razor.cs index e2be6c5ff..75bf91a5b 100644 --- a/Material.Blazor/Components/DatePicker/InternalDatePickerPanel.razor.cs +++ b/Material.Blazor/Components/DatePicker/InternalDatePickerPanel.razor.cs @@ -89,9 +89,13 @@ public partial class InternalDatePickerPanel : InputComponent [Parameter] public string DateFormat { get; set; } - private bool ScrollToYear { get; set; } = false; + /// + /// The that determines the culture-specific format of displaying dates according to the . + /// + [Parameter] public CultureInfo CultureInfo { get; set; } - private string[] DaysOfWeek { get; set; } + + private bool ScrollToYear { get; set; } = false; private bool PreviousMonthDisabled => false || (StartOfDisplayMonth.Year == DateTime.MinValue.Year && StartOfDisplayMonth.Month == DateTime.MinValue.Month) @@ -118,7 +122,7 @@ internal bool ShowYearPad private List YearsInGroupsOfFour { get; set; } = new List(); - private string ValueText => Utilities.DateToString(Value, DateFormat); + private string ValueText => Utilities.DateToString(Value, DateFormat, CultureInfo); private int MonthsOffset { get; set; } = 0; @@ -126,11 +130,15 @@ internal bool ShowYearPad private bool HasBeenOpened { get; set; } = false; - private string MonthText => StartOfDisplayMonth.ToString("MMMM yyyy"); + private string MonthText => StartOfDisplayMonth.ToString("MMMM yyyy", CultureInfo); private readonly string currentYearId = Utilities.GenerateUniqueElementName(); - private readonly IMBIconFoundry foundry = MBIconHelper.MIFoundry(MBIconMITheme.Filled); + private readonly IMBIconFoundry foundry = MBIconHelper.MSFoundry(fill: true, gradient: MBIconMSGradient.NormalEmphasis, size: MBIconMSSize.Size24, style: MBIconMSStyle.Outlined, weight: MBIconMSWeight.W400); + private bool IsRTL { get; set; } + private string BackIcon => IsRTL ? "chevron_right" : "chevron_left"; + private string UndoIcon => IsRTL ? "redo" : "undo"; + private string ForwardIcon => IsRTL ? "chevron_left" : "chevron_right"; // Would like to use however DocFX cannot resolve to references outside Material.Blazor @@ -138,13 +146,6 @@ protected override async Task OnInitializedAsync() { await base.OnInitializedAsync(); - DaysOfWeek = CultureInfo.CurrentCulture.DateTimeFormat.AbbreviatedDayNames.Select(d => d[0..1]).ToArray(); - var rotate_by = (int)CultureInfo.CurrentCulture.DateTimeFormat.FirstDayOfWeek; - if (rotate_by > 0) - { - DaysOfWeek = DaysOfWeek.Skip(rotate_by).Concat(DaysOfWeek.Take(rotate_by)).ToArray(); - } - AllowAllRenders(); } @@ -154,6 +155,8 @@ protected override async Task OnParametersSetAsync() { await base.OnParametersSetAsync(); + IsRTL = await IsElementRTL(Parent.ElementReference); + SetParameters(); } @@ -192,7 +195,7 @@ internal void SetParameters(DateTime? newValue = null) { startDate = StartOfDisplayMonth = new DateTime(DateTime.MaxValue.Year, DateTime.MaxValue.Month, 1); } - while (startDate.Date > DateTime.MinValue.Date && startDate.DayOfWeek != CultureInfo.CurrentCulture.DateTimeFormat.FirstDayOfWeek) + while (startDate.Date > DateTime.MinValue.Date && startDate.DayOfWeek != CascadingDefaults.AppliedCultureInfo(null).DateTimeFormat.FirstDayOfWeek) { startDate = startDate.AddDays(-1); } @@ -244,10 +247,24 @@ public async Task NotifyOpened() } + private string[] DaysOfWeek() + { + var result = CascadingDefaults.AppliedCultureInfo(null).DateTimeFormat.AbbreviatedDayNames.Select(d => d[0..1]).ToArray(); + var rotate_by = (int)CascadingDefaults.AppliedCultureInfo(null).DateTimeFormat.FirstDayOfWeek; + + if (rotate_by > 0) + { + result = result.Skip(rotate_by).Concat(result.Take(rotate_by)).ToArray(); + } + + return result; + } + + private async Task OnDayItemClickAsync(DateTime dateTime) { // Invoke JS first. if ComponentValue is set first we are at risk of this element being re-rendered before this line is run, making ListItemReference stale and causing a JS exception. - await InvokeJsVoidAsync("MaterialBlazor.MBDatePicker.listItemClick", ListItemReference, Utilities.DateToString(dateTime, DateFormat)); + await InvokeJsVoidAsync("MaterialBlazor.MBDatePicker.listItemClick", ListItemReference, Utilities.DateToString(dateTime, DateFormat, CultureInfo)); ComponentValue = dateTime; MonthsOffset = 0; Parent.NotifyValueChanged(); @@ -295,4 +312,5 @@ protected override async Task OnAfterRenderAsync(bool firstRender) // TODO: this await InvokeJsVoidAsync("MaterialBlazor.MBDatePicker.scrollToYear", currentYearId); } } + } diff --git a/Material.Blazor/Components/DatePicker/MBDatePicker.razor b/Material.Blazor/Components/DatePicker/MBDatePicker.razor index e28387c49..53d5c062c 100644 --- a/Material.Blazor/Components/DatePicker/MBDatePicker.razor +++ b/Material.Blazor/Components/DatePicker/MBDatePicker.razor @@ -87,6 +87,7 @@ @ref="@MenuSurfaceElementReference"> private string AdditionalStyle { get; set; } = ""; private MBDensity AppliedDensity => CascadingDefaults.AppliedSelectDensity(Density); private string AppliedDateFormat => CascadingDefaults.AppliedDateFormat(DateFormat); + private CultureInfo AppliedCultureInfo => CascadingDefaults.AppliedCultureInfo(CultureInfo); private MBSelectInputStyle AppliedInputStyle => CascadingDefaults.AppliedStyle(SelectInputStyle); - private ElementReference ElementReference { get; set; } + internal ElementReference ElementReference { get; set; } private ElementReference MenuSurfaceElementReference { get; set; } private DotNetObjectReference ObjectReference { get; set; } private string MenuClass => MBMenu.GetMenuSurfacePositioningClass(MenuSurfacePositioning == MBMenuSurfacePositioning.Fixed ? MBMenuSurfacePositioning.Fixed : MBMenuSurfacePositioning.Regular) + ((Panel?.ShowYearPad ?? true) ? " mb-dp-menu__day-menu" : " mb-dp-menu__year-menu"); @@ -44,6 +46,12 @@ public partial class MBDatePicker : InputComponent [Parameter] public string DateFormat { get; set; } + /// + /// The that determines the culture-specific format for dates according to the . + /// + [Parameter] public CultureInfo? CultureInfo { get; set; } + + #nullable enable annotations internal static readonly Func DateIsSelectableNotUsed = (_) => true; /// @@ -69,6 +77,7 @@ public partial class MBDatePicker : InputComponent /// The label. /// [Parameter] public string Label { get; set; } + private string _cachedLabel; /// @@ -205,6 +214,8 @@ protected override async Task OnInitializedAsync() AllowAllRenders(); ObjectReference = DotNetObjectReference.Create(this); + + _cachedLabel = Label; } #endregion @@ -248,6 +259,12 @@ protected override async Task OnParametersSetAsync() EnqueueJSInteropAction(() => Badge.SetValueAndExited(BadgeValue, BadgeExited)); } } + + if (_cachedLabel != Label) + { + _cachedLabel = Label; + AllowNextRender(true); + } } @@ -266,7 +283,7 @@ protected private override async Task SetComponentValueAsync() await InvokeAsync(StateHasChanged).ConfigureAwait(false); } - await InvokeJsVoidAsync("MaterialBlazor.MBDatePicker.listItemClick", Panel.ListItemReference, Utilities.DateToString(Value, AppliedDateFormat)).ConfigureAwait(false); + await InvokeJsVoidAsync("MaterialBlazor.MBDatePicker.listItemClick", Panel.ListItemReference, Utilities.DateToString(Value, AppliedDateFormat, AppliedCultureInfo)).ConfigureAwait(false); } diff --git a/Material.Blazor/Components/DatePicker/MBDatePicker.scss b/Material.Blazor/Components/DatePicker/MBDatePicker.scss index e594d3585..525e51200 100644 --- a/Material.Blazor/Components/DatePicker/MBDatePicker.scss +++ b/Material.Blazor/Components/DatePicker/MBDatePicker.scss @@ -27,13 +27,13 @@ $dp-day-pad-bottom-margin: 8px; $dp-panel-width: 7 * ($dp-button-size + 2 * $dp-button-margin) + 2 * $dp-day-pad-horizontal-margin; $dp-year-pad-padding-top: 4px; -$dp-year-pad-padding-right: 0; +$dp-year-pad-padding-end: 0px; $dp-year-pad-padding-bottom: 8px; -$dp-year-pad-padding-left: 12px; +$dp-year-pad-padding-start: 12px; $dp-year-pad-clear-space-right: 20px; $dp-day-button-width: $dp-button-size; -$dp-year-button-width: math.div(($dp-panel-width - $dp-year-pad-padding-left - $dp-year-pad-clear-space-right), 4) - 2 * $dp-button-margin; +$dp-year-button-width: math.div(($dp-panel-width - $dp-year-pad-padding-start - $dp-year-pad-clear-space-right), 4) - 2 * $dp-button-margin; $dp-blank-filler-height: 7 * $dp-day-button-width; @@ -65,6 +65,7 @@ $dp-blank-filler-height: 7 * $dp-day-button-width; $dp-menu-height: 52px; $dp-menu-padding: 16px 8px 12px 24px; +$dp-menu-padding-rtl: 16px 24px 12px 8px; $dp-menu-icon-button-margin: 4px; $dp-panel-height: 6 * ($dp-button-size + 2 * $dp-button-margin) + ($dp-button-size + $dp-button-margin) + (2 * $dp-day-pad-bottom-margin) + $dp-menu-height; @@ -72,6 +73,7 @@ $dp-panel-height: 6 * ($dp-button-size + 2 * $dp-button-margin) + ($dp-button-si .mb-dp-menu { display: flex; flex-flow: row nowrap; + align-items: center; justify-content: space-between; box-sizing: border-box; padding: $dp-menu-padding; @@ -81,12 +83,21 @@ $dp-panel-height: 6 * ($dp-button-size + 2 * $dp-button-margin) + ($dp-button-si width: $dp-panel-width; min-width: $dp-panel-width; overflow: visible !important; + + .mdc-touch-target-wrapper { + display: inline-flex; + } +} + +[dir="rtl"] .mb-dp-menu { + padding: $dp-menu-padding-rtl; } .mb-dp-menu__left { display: flex; flex-flow: row nowrap; + align-items: center; justify-content: flex-start; } @@ -94,6 +105,7 @@ $dp-panel-height: 6 * ($dp-button-size + 2 * $dp-button-margin) + ($dp-button-si .mb-dp-menu__right { display: flex; flex-flow: row nowrap; + align-items: center; justify-content: flex-end; } @@ -106,13 +118,16 @@ $dp-panel-height: 6 * ($dp-button-size + 2 * $dp-button-margin) + ($dp-button-si .mb-dp-menu__icon-button.spaced { - margin-left: $dp-menu-icon-button-margin; + margin: 0 0 0 $dp-menu-icon-button-margin; } +[dir="rtl"] .mb-dp-menu__icon-button.spaced { + margin: 0 $dp-menu-icon-button-margin 0 0; +} /* Day pad -*/ + */ $dp-day-pad-weekdays-margin-bottom: 8px; $dp-day-pad-weekdays-size: $dp-button-size + $dp-button-margin; @@ -171,11 +186,11 @@ $dp-day-pad-weekdays-size: $dp-button-size + $dp-button-margin; .mb-dp-day-pad__button_earlier_month { visibility: hidden; } + .mb-dp-day-pad__button_later_month { visibility: hidden; } - /* Year pad */ @@ -185,13 +200,18 @@ $dp-year-pad-rows: 7; .mb-dp-year-pad { display: flex; flex-flow: row wrap; - padding: $dp-year-pad-padding-top $dp-year-pad-padding-right $dp-year-pad-padding-bottom $dp-year-pad-padding-left; + padding: $dp-year-pad-padding-top $dp-year-pad-padding-end $dp-year-pad-padding-bottom $dp-year-pad-padding-start; user-select: none; overflow-x: hidden; overflow-y: scroll; max-height: $dp-year-pad-rows * ($dp-button-size + 2 * $dp-button-margin); } +[dir="rtl"] .mb-dp-year-pad { + padding-right: $dp-year-pad-padding-start; + padding-left: $dp-year-pad-padding-end; +} + .mb-dp-year-pad__button { height: $dp-button-size !important; min-height: $dp-button-size !important; @@ -206,12 +226,9 @@ $dp-year-pad-rows: 7; border-radius: $dp-button-border-radius; } } - - /************************************************ Applied to MBDatePicker.razor ************************************************/ - /*$dp-menu-day-menu-height: $dp-menu-height + 7 * ($dp-button-size + 2 * $dp-button-margin) + $dp-button-margin + $dp-day-pad-bottom-margin; $dp-menu-year-menu-height: $dp-menu-height + $dp-year-pad-rows * ($dp-button-size + 2 * $dp-button-margin) + $dp-year-pad-padding-top + $dp-year-pad-padding-bottom;*/ @@ -241,4 +258,4 @@ $dp-menu-year-menu-height: $dp-menu-height + $dp-year-pad-rows * ($dp-button-siz .mb-dp-blank-filler { width: $dp-panel-width; height: $dp-panel-height; -} \ No newline at end of file +} diff --git a/Material.Blazor/Components/DatePicker/MBDatePicker.ts b/Material.Blazor/Components/DatePicker/MBDatePicker.ts index ab2e3af50..9720ed644 100644 --- a/Material.Blazor/Components/DatePicker/MBDatePicker.ts +++ b/Material.Blazor/Components/DatePicker/MBDatePicker.ts @@ -48,4 +48,4 @@ function tryScrollToYear(id, attempt: number) { export function scrollToYear(id) { // we allow up to 10 attempts every 16ms, because Virtualize may have not yet rendered the year we want to scroll to. tryScrollToYear(id, 0); -} +} \ No newline at end of file diff --git a/Material.Blazor/Components/FileUpload/MBFileUpload.scss b/Material.Blazor/Components/FileUpload/MBFileUpload.scss index d9ada3314..7b6de8432 100644 --- a/Material.Blazor/Components/FileUpload/MBFileUpload.scss +++ b/Material.Blazor/Components/FileUpload/MBFileUpload.scss @@ -63,10 +63,27 @@ } .mb-file-upload__leading-icon { - margin-right: 8px; + margin: 0 8px 0 0; } .mb-file-upload__trailing-icon { - margin-left: 8px; + margin: 0 0 0 8px; + } +} + +[dir="rtl"] .mb-file-upload--drag-and-drop { + & .mb-file-upload__card-content { + & .mb-file-upload__filename { + left: 6px; + right: auto; + } + } + + .mb-file-upload__leading-icon { + margin: 0 0 0 8px; + } + + .mb-file-upload__trailing-icon { + margin: 0 8px 0 0; } } diff --git a/Material.Blazor/Components/NumericDecimalField/MBNumericDecimalField.razor.cs b/Material.Blazor/Components/NumericDecimalField/MBNumericDecimalField.razor.cs index 24f2b8ea3..161f960f0 100644 --- a/Material.Blazor/Components/NumericDecimalField/MBNumericDecimalField.razor.cs +++ b/Material.Blazor/Components/NumericDecimalField/MBNumericDecimalField.razor.cs @@ -3,6 +3,7 @@ using Microsoft.AspNetCore.Components; using System; +using System.Globalization; using System.Linq.Expressions; using System.Text.RegularExpressions; using System.Threading.Tasks; @@ -95,6 +96,12 @@ public partial class MBNumericDecimalField : InputComponent [Parameter] public string NumericFormat { get; set; } + /// + /// The that determines the culture-specific format for numbers to the . + /// + [Parameter] public CultureInfo? CultureInfo { get; set; } + + /// /// Alternative format for a singular number if required. An example is "1 month" /// vs "3 months". @@ -144,6 +151,7 @@ public partial class MBNumericDecimalField : InputComponent private decimal AppliedMultiplier => HasFocus ? FocusedMultiplier : UnfocusedMultiplier; + private CultureInfo AppliedCultureInfo => CascadingDefaults.AppliedCultureInfo(CultureInfo); private decimal FocusedMultiplier { get; set; } = 1; private int MyDecimalPlaces { get; set; } = 0; private Regex Regex { get; set; } @@ -246,7 +254,7 @@ private async Task OnFocusOutAsync() } - private string StringValue(decimal? value) => (Convert.ToDecimal(value) * AppliedMultiplier).ToString(AppliedFormat); + private string StringValue(decimal? value) => (Convert.ToDecimal(value) * AppliedMultiplier).ToString(AppliedFormat, AppliedCultureInfo); private decimal NumericValue(string displayText) diff --git a/Material.Blazor/Components/NumericDoubleField/MBNumericDoubleField.razor b/Material.Blazor/Components/NumericDoubleField/MBNumericDoubleField.razor index 5071271a2..3dbf7f5d1 100644 --- a/Material.Blazor/Components/NumericDoubleField/MBNumericDoubleField.razor +++ b/Material.Blazor/Components/NumericDoubleField/MBNumericDoubleField.razor @@ -7,6 +7,7 @@ id="@id" @attributes="@AttributesToSplat()" @bind-Value="@DecimalValue" + CultureInfo="@CultureInfo" DecimalPlaces="@DecimalPlaces" Density="@Density" Disabled="@AppliedDisabled" diff --git a/Material.Blazor/Components/NumericDoubleField/MBNumericDoubleField.razor.cs b/Material.Blazor/Components/NumericDoubleField/MBNumericDoubleField.razor.cs index e05f44d0d..65057e708 100644 --- a/Material.Blazor/Components/NumericDoubleField/MBNumericDoubleField.razor.cs +++ b/Material.Blazor/Components/NumericDoubleField/MBNumericDoubleField.razor.cs @@ -1,6 +1,7 @@ using Material.Blazor.Internal; using Microsoft.AspNetCore.Components; using System; +using System.Globalization; using System.Linq.Expressions; using System.Threading.Tasks; @@ -91,6 +92,12 @@ public partial class MBNumericDoubleField : InputComponent [Parameter] public string NumericFormat { get; set; } + /// + /// The that determines the culture-specific format for numbers to the . + /// + [Parameter] public CultureInfo? CultureInfo { get; set; } + + /// /// Alternative format for a singular number if required. An example is "1 month" /// vs "3 months". diff --git a/Material.Blazor/Components/NumericIntField/MBNumericIntField.razor b/Material.Blazor/Components/NumericIntField/MBNumericIntField.razor index 4b76ff9c7..a228e4f23 100644 --- a/Material.Blazor/Components/NumericIntField/MBNumericIntField.razor +++ b/Material.Blazor/Components/NumericIntField/MBNumericIntField.razor @@ -7,6 +7,7 @@ id="@id" @attributes="@AttributesToSplat()" @bind-Value="@DecimalValue" + CultureInfo="@CultureInfo" DecimalPlaces="0" Density="@Density" Disabled="@AppliedDisabled" diff --git a/Material.Blazor/Components/NumericIntField/MBNumericIntField.razor.cs b/Material.Blazor/Components/NumericIntField/MBNumericIntField.razor.cs index 754d9566d..346e1c244 100644 --- a/Material.Blazor/Components/NumericIntField/MBNumericIntField.razor.cs +++ b/Material.Blazor/Components/NumericIntField/MBNumericIntField.razor.cs @@ -1,6 +1,7 @@ using Material.Blazor.Internal; using Microsoft.AspNetCore.Components; using System; +using System.Globalization; using System.Linq.Expressions; using System.Threading.Tasks; @@ -91,6 +92,12 @@ public partial class MBNumericIntField : InputComponent [Parameter] public string NumericFormat { get; set; } + /// + /// The that determines the culture-specific format for numbers to the . + /// + [Parameter] public CultureInfo? CultureInfo { get; set; } + + /// /// Alternative format for a singular number if required. An example is "1 month" /// vs "3 months". diff --git a/Material.Blazor/Components/PagedDataList/MBPagedDataList.razor b/Material.Blazor/Components/PagedDataList/MBPagedDataList.razor index dfcbe6278..fffcd3a39 100644 --- a/Material.Blazor/Components/PagedDataList/MBPagedDataList.razor +++ b/Material.Blazor/Components/PagedDataList/MBPagedDataList.razor @@ -6,7 +6,8 @@
    + @attributes="@AttributesToSplat()" + @ref="@ElementReference">
    @ListTemplate( @@ -43,5 +44,7 @@ { ListTemplate = (childContent) => @
      @childContent
    ; } + + IsRTL = await IsElementRTL(ElementReference); } } \ No newline at end of file diff --git a/Material.Blazor/Components/PagedDataList/MBPagedDataList.razor.cs b/Material.Blazor/Components/PagedDataList/MBPagedDataList.razor.cs index e39f219d4..676180f29 100644 --- a/Material.Blazor/Components/PagedDataList/MBPagedDataList.razor.cs +++ b/Material.Blazor/Components/PagedDataList/MBPagedDataList.razor.cs @@ -118,10 +118,13 @@ private int BackingItemsPerPage [Parameter] public EventCallback ItemsPerPageChanged { get; set; } + private MBPaginator Paginator { get; set; } + private ElementReference ElementReference { get; set; } private IEnumerable CheckedData => Data ?? Array.Empty(); private string ContentClass { get; set; } = ""; public IEnumerable CurrentPage => CheckedData.Skip(PageNumber * ItemsPerPage).Take(ItemsPerPage); private bool HasRendered { get; set; } = false; + private bool IsRTL { get; set; } = false; private bool IsHidden { get; set; } = false; private Func KeyGenerator { get; set; } @@ -131,13 +134,13 @@ private async Task OnPageNumberChange(int oldPageNumber, int newPageNumber) string nextClass; if (newPageNumber < oldPageNumber) { - nextClass = MBSlidingContent.InFromLeft; - ContentClass = MBSlidingContent.OutToRight; + nextClass = MBSlidingContent.InFromPrevious(IsRTL); + ContentClass = MBSlidingContent.OutToNext(IsRTL); } else { - nextClass = MBSlidingContent.InFromRight; - ContentClass = MBSlidingContent.OutToLeft; + nextClass = MBSlidingContent.InFromNext(IsRTL); + ContentClass = MBSlidingContent.OutToPrevious(IsRTL); } await Task.Delay(100); diff --git a/Material.Blazor/Components/Paginator/MBPaginator.razor b/Material.Blazor/Components/Paginator/MBPaginator.razor index ed6cacab9..2e8e2001a 100644 --- a/Material.Blazor/Components/Paginator/MBPaginator.razor +++ b/Material.Blazor/Components/Paginator/MBPaginator.razor @@ -5,10 +5,12 @@
    + @attributes="@AttributesToSplat()" + @ref="@ContainerReference"> +
    -
    +
    @ItemsText
    @@ -36,17 +38,17 @@
    @* This hidden element serves to give the actual position text a constant width equal to the maximum width that may be required *@ -
    +
    @PositionText
    - - - - + + + +
    \ No newline at end of file diff --git a/Material.Blazor/Components/Paginator/MBPaginator.razor.cs b/Material.Blazor/Components/Paginator/MBPaginator.razor.cs index b52369060..8ef6cf83f 100644 --- a/Material.Blazor/Components/Paginator/MBPaginator.razor.cs +++ b/Material.Blazor/Components/Paginator/MBPaginator.razor.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.Linq; using System.Threading.Tasks; @@ -95,19 +96,52 @@ private int BackingPageNumber [Parameter] public EventCallback PageNumberChanged { get; set; } + /// + /// A function delegate that formats the items per page text in the language of your choice. The two parameters are number of items per page and the applicable culture respectively. + /// When neither set nor overrided by cascading defaults, is used. + /// + [Parameter] public Func ItemsPerPageFormatter { get; set; } = null; + + + /// + /// A function delegate that formats the position text in the language of your choice. The four parameters are the first item number, the last item number, the total item count and the applicable culture respectively. + /// When neither set nor overrided by cascading defaults, is used. + /// + [Parameter] public Func PositionFormatter { get; set; } = null; + + + /// + /// The that determines the culture-specific format for dates according to the . + /// + [Parameter] public CultureInfo CultureInfo { get; set; } = null; + + private bool HasRendered { get; set; } = false; + private Func AppliedItemsPerPageFormatter => CascadingDefaults.AppliedPaginatorItemsPerPageFormatter(ItemsPerPageFormatter); + private Func AppliedPositionFormatter => CascadingDefaults.AppliedPaginatorPositionFormatter(PositionFormatter); + private CultureInfo AppliedCultureInfo => CascadingDefaults.AppliedCultureInfo(CultureInfo); + private ElementReference ContainerReference { get; set; } private MBIconButtonToggle IconButtonToggle { get; set; } private MBSelectElement[] ItemsPerPageItems { get; set; } - private string ItemsText => $"{ItemsPerPage:G0} items per page"; private int MaxPageNumber => ItemsPerPage == 0 ? 0 : Math.Max(0, Convert.ToInt32(Math.Ceiling((double)ItemCount / ItemsPerPage)) - 1); private string MaxPositionText => PositionTextString(MaxPageNumber); private MBMenu Menu { get; set; } private bool NextDisabled => PageNumber >= MaxPageNumber; private string PositionText => PositionTextString(PageNumber); private bool PreviousDisabled => PageNumber <= 0; - private string PositionTextString(int pageNumber) => $"{pageNumber * ItemsPerPage + 1:G0}-{Math.Min(ItemCount, (pageNumber + 1) * ItemsPerPage):G0} of {ItemCount:G0}"; - - + private string ItemsText => AppliedItemsPerPageFormatter(ItemsPerPage, AppliedCultureInfo); + private string PositionTextString(int pageNumber) => AppliedPositionFormatter(pageNumber * ItemsPerPage + 1, Math.Min(ItemCount, (pageNumber + 1) * ItemsPerPage), ItemCount, AppliedCultureInfo); + + + + private bool IsRTL { get; set; } + private string FirstItemIcon => IsRTL ? "last_page" : "first_page"; + private string BackIcon => IsRTL ? "chevron_right" : "chevron_left"; + private string ForwardIcon => IsRTL ? "chevron_left" : "chevron_right"; + private string LastItemIcon => IsRTL ? "first_page" : "last_page"; + + + private bool toggleOn; private bool ToggleOn { @@ -159,6 +193,8 @@ protected override async Task OnParametersSetAsync() { await base.OnParametersSetAsync().ConfigureAwait(false); + IsRTL = await IsElementRTL(ContainerReference); + if (_cachedItemCount != ItemCount) { _cachedItemCount = ItemCount; @@ -213,4 +249,16 @@ private void OnLastClick() { BackingPageNumber = MaxPageNumber; } + + + public static string DefaultItemsPerPageFormatter(int itemsPerPage, CultureInfo cultureInfo) + { + return $"{itemsPerPage.ToString("G0", cultureInfo)} items per page"; + } + + + public static string DefaultPositionFormatter(int firstItemNumber, int lastItemNumber, int itemCount, CultureInfo cultureInfo) + { + return $"{firstItemNumber.ToString("G0", cultureInfo)}-{lastItemNumber.ToString("G0", cultureInfo)} of {itemCount.ToString("G0", cultureInfo)}"; + } } diff --git a/Material.Blazor/Components/Paginator/MBPaginator.scss b/Material.Blazor/Components/Paginator/MBPaginator.scss index fd04ce728..0579e9421 100644 --- a/Material.Blazor/Components/Paginator/MBPaginator.scss +++ b/Material.Blazor/Components/Paginator/MBPaginator.scss @@ -1,14 +1,20 @@ $paginator-height: 48px; $paginator-spacing: 18px; $position-text-spacing: 6px; +$margin: 12px; .mdc-data-table__pagination-rows-per-page { margin-right: 0 !important; } .mdc-data-table__pagination-navigation { - margin-left: 12px !important; + margin: 0 0 0 $margin !important; } + +[dir="rtl"] .mdc-data-table__pagination-navigation { + margin: 0 $margin 0 0 !important; +} + .mdc-data-table__pagination-button { margin-right: 0 !important; } diff --git a/Material.Blazor/Components/SegmentedButtonMulti/MBSegmentedButtonMulti.razor.cs b/Material.Blazor/Components/SegmentedButtonMulti/MBSegmentedButtonMulti.razor.cs index b3accb7a9..bedecd685 100644 --- a/Material.Blazor/Components/SegmentedButtonMulti/MBSegmentedButtonMulti.razor.cs +++ b/Material.Blazor/Components/SegmentedButtonMulti/MBSegmentedButtonMulti.razor.cs @@ -77,6 +77,26 @@ protected override async Task OnInitializedAsync() ConditionalCssClasses .AddIf("mdc-segmented-button--single-select", () => IsSingleSelect); + ObjectReference = DotNetObjectReference.Create(this); + } + + + // Would like to use however DocFX cannot resolve to references outside Material.Blazor + protected override async Task OnParametersSetAsync() + { + await base.OnParametersSetAsync().ConfigureAwait(false); + + if (_cachedBadgeValue != BadgeValue || _cachedBadgeExited != BadgeExited) + { + _cachedBadgeValue = BadgeValue; + _cachedBadgeExited = BadgeExited; + + if (Badge is not null) + { + EnqueueJSInteropAction(() => Badge.SetValueAndExited(BadgeValue, BadgeExited)); + } + } + ItemsArray = Items.ToArray(); SegmentAttributes = new Dictionary[ItemsArray.Length]; @@ -99,26 +119,6 @@ protected override async Task OnInitializedAsync() SegmentAttributes[i].Add("aria-pressed", selected.ToString().ToLower()); } } - - ObjectReference = DotNetObjectReference.Create(this); - } - - - // Would like to use however DocFX cannot resolve to references outside Material.Blazor - protected override async Task OnParametersSetAsync() - { - await base.OnParametersSetAsync().ConfigureAwait(false); - - if (_cachedBadgeValue != BadgeValue || _cachedBadgeExited != BadgeExited) - { - _cachedBadgeValue = BadgeValue; - _cachedBadgeExited = BadgeExited; - - if (Badge is not null) - { - EnqueueJSInteropAction(() => Badge.SetValueAndExited(BadgeValue, BadgeExited)); - } - } } diff --git a/Material.Blazor/Components/SegmentedButtonMulti/MBSegmentedButtonMulti.scss b/Material.Blazor/Components/SegmentedButtonMulti/MBSegmentedButtonMulti.scss index 8690fa229..06b2832ea 100644 --- a/Material.Blazor/Components/SegmentedButtonMulti/MBSegmentedButtonMulti.scss +++ b/Material.Blazor/Components/SegmentedButtonMulti/MBSegmentedButtonMulti.scss @@ -1,7 +1,29 @@ -.mb-segmented-button__container { +@use '@material/segmented-button/segment/_segment-theme'; + +.mb-segmented-button__container { display: inline-block; position: relative; width: fit-content; height: fit-content; overflow: visible; } + +/* + * The following is a workaround for the fact that the MDC SegmentedButton does not support RTL. + * It is a copy of the MDC SegmentedButton styles with the addition of the [dir="rtl"] selector. +*/ +[dir="rtl"] .mdc-segmented-button .mdc-touch-target-wrapper { + .mdc-segmented-button__segment { + border-left-width: 0; + border-right-width: segment-theme.$border-width; + } + + &:first-child .mdc-segmented-button__segment { + border-radius: 0 segment-theme.$border-radius segment-theme.$border-radius 0; + } + + &:last-child .mdc-segmented-button__segment { + border-radius: segment-theme.$border-radius 0 0 segment-theme.$border-radius; + border-left-width: segment-theme.$border-width; + } +} diff --git a/Material.Blazor/Components/Select/MBSelect.razor.cs b/Material.Blazor/Components/Select/MBSelect.razor.cs index 6b360d1ea..d977e3073 100644 --- a/Material.Blazor/Components/Select/MBSelect.razor.cs +++ b/Material.Blazor/Components/Select/MBSelect.razor.cs @@ -16,6 +16,7 @@ public partial class MBSelect : SingleSelectComponent [Parameter] public string Label { get; set; } + private string _cachedLabel; /// @@ -167,6 +168,8 @@ protected override async Task OnInitializedAsync() .AddIf("mdc-select--disabled", () => AppliedDisabled); ObjectReference = DotNetObjectReference.Create(this); + + _cachedLabel = Label; } @@ -186,6 +189,12 @@ protected override async Task OnParametersSetAsync() } } + if (_cachedLabel != Label) + { + _cachedLabel = Label; + AllowNextRender(true); + } + KeyGenerator = GetKeysFunc ?? delegate (TItem item) { return item; }; } diff --git a/Material.Blazor/Components/Shield/MBShield.scss b/Material.Blazor/Components/Shield/MBShield.scss index 8b91f91ba..651474f26 100644 --- a/Material.Blazor/Components/Shield/MBShield.scss +++ b/Material.Blazor/Components/Shield/MBShield.scss @@ -42,6 +42,10 @@ $shield-icon-right-margin: 3px; margin: 0 $shield-icon-right-margin 0 $shield-icon-left-margin; } +[dir="rtl"] .mb-shield i { + margin: 0 $shield-icon-left-margin 0 $shield-icon-right-margin; +} + .mb-shield--label { display: inline-flex; flex-flow: row nowrap; @@ -55,6 +59,10 @@ $shield-icon-right-margin: 3px; border: 0; } +[dir="rtl"] .mb-shield--label { + padding: 0 $shield-outer-padding 0 $shield-inner-padding; +} + .mb-shield--value { display: inline-flex; flex-flow: row nowrap; @@ -67,3 +75,7 @@ $shield-icon-right-margin: 3px; padding: 0 $shield-outer-padding 0 $shield-inner-padding; border: 0; } + +[dir="rtl"] .mb-shield--value { + padding: 0 $shield-inner-padding 0 $shield-outer-padding; +} diff --git a/Material.Blazor/Components/Slider/MBSlider.razor b/Material.Blazor/Components/Slider/MBSlider.razor index 330bd6e35..3bc43db81 100644 --- a/Material.Blazor/Components/Slider/MBSlider.razor +++ b/Material.Blazor/Components/Slider/MBSlider.razor @@ -1,7 +1,7 @@ @namespace Material.Blazor @inherits InputComponent -
    -
    +
    @@ -52,7 +52,7 @@
    } -
    +
    Reference Link Source