From 5dac4983a797c4529d8f190e9e1ee26be333c0ea Mon Sep 17 00:00:00 2001 From: msynk Date: Wed, 19 Aug 2026 15:48:04 +0330 Subject: [PATCH 1/9] fix WASM thread issues on safari #12929 --- .../Components/Map/Providers/BitMapLeaflet.ts | 16 ++++++ .../Map/Providers/BitMapOpenLayers.ts | 16 ++++++ .../Bit.BlazorUI.Extras/Scripts/Extras.ts | 51 +++++++++++++++--- .../Bit.BlazorUI.Legacy/Scripts/Legacy.ts | 51 +++++++++++++++--- .../Startup/Middlewares.cs | 46 ++++++++++++++-- .../Components/Extras/Map/BitMapDemo.razor | 7 +++ .../BitRichTextEditorDemo.razor | 7 +++ .../_BitChoiceGroupCustomDemo.razor.cs | 16 +++--- ..._BitChoiceGroupCustomDemo.razor.samples.cs | 32 +++++------ .../_BitChoiceGroupItemDemo.razor.cs | 16 +++--- .../_BitChoiceGroupItemDemo.razor.samples.cs | 32 +++++------ .../_BitChoiceGroupOptionDemo.razor | 24 ++++----- ..._BitChoiceGroupOptionDemo.razor.samples.cs | 24 ++++----- .../BitCircularTimePickerDemo.razor | 2 +- ...BitCircularTimePickerDemo.razor.samples.cs | 2 +- .../Inputs/TimePicker/BitTimePickerDemo.razor | 2 +- .../BitTimePickerDemo.razor.samples.cs | 2 +- .../Lists/BasicList/BitBasicListDemo.razor | 4 +- .../BitBasicListDemo.razor.samples.cs | 4 +- .../Timeline/_BitTimelineCustomDemo.razor | 4 +- .../_BitTimelineCustomDemo.razor.samples.cs | 4 +- .../Lists/Timeline/_BitTimelineItemDemo.razor | 4 +- .../_BitTimelineItemDemo.razor.samples.cs | 4 +- .../Timeline/_BitTimelineOptionDemo.razor | 8 +-- .../_BitTimelineOptionDemo.razor.samples.cs | 4 +- .../Progress/Shimmer/BitShimmerDemo.razor | 2 +- .../Progress/Shimmer/BitShimmerDemo.razor.cs | 2 +- .../choicegroup/choicegroup-bar-selected.png | Bin 0 -> 1215 bytes .../choicegroup-bar-unselected.png | Bin 0 -> 1206 bytes .../choicegroup/choicegroup-pie-selected.png | Bin 0 -> 3736 bytes .../choicegroup-pie-unselected.png | Bin 0 -> 3406 bytes .../wwwroot/images/icon/clock.svg | 1 + .../wwwroot/images/persona/persona-male.png | Bin 0 -> 18425 bytes 33 files changed, 270 insertions(+), 117 deletions(-) create mode 100644 src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/wwwroot/images/choicegroup/choicegroup-bar-selected.png create mode 100644 src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/wwwroot/images/choicegroup/choicegroup-bar-unselected.png create mode 100644 src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/wwwroot/images/choicegroup/choicegroup-pie-selected.png create mode 100644 src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/wwwroot/images/choicegroup/choicegroup-pie-unselected.png create mode 100644 src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/wwwroot/images/icon/clock.svg create mode 100644 src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/wwwroot/images/persona/persona-male.png diff --git a/src/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitMapLeaflet.ts b/src/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitMapLeaflet.ts index 9ccefaa775a..f789fb0b7db 100644 --- a/src/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitMapLeaflet.ts +++ b/src/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitMapLeaflet.ts @@ -38,6 +38,19 @@ namespace BitBlazorUI { } export class BitMapLeaflet { + /** + * crossOrigin value applied to every tile layer. + * + * When the host page is cross-origin isolated (COOP/COEP headers, required for the + * multi-threaded WebAssembly runtime) and the browser only supports + * COEP: require-corp (Safari/WebKit), plain no-cors tile requests to a server that + * does not send a Cross-Origin-Resource-Policy header are blocked, so tiles are + * requested in CORS mode instead (public tile servers such as OSM, Carto and + * OpenTopoMap all send Access-Control-Allow-Origin: *). On a non-isolated page the + * default no-cors mode is kept so tile servers without CORS headers keep working. + */ + private static readonly _tileCrossOrigin: string | undefined = self.crossOriginIsolated ? 'anonymous' : undefined; + private static _maps: { [id: string]: LeafletState } = {}; public static async init(id: string, canvasId: string, element: HTMLElement, dotnetObj: DotNetObject | null | undefined, options: any) { @@ -84,6 +97,7 @@ namespace BitBlazorUI { tileOpacity: o.tileOpacity ?? 1, }; const baseTileLayer = L.tileLayer(tileOptions.tileUrl, { + crossOrigin: BitMapLeaflet._tileCrossOrigin, maxZoom: tileOptions.tileMaxZoom, attribution: tileOptions.tileAttribution, opacity: tileOptions.tileOpacity, @@ -163,6 +177,7 @@ namespace BitBlazorUI { if (tileChanged) { if (s.baseTileLayer) s.map.removeLayer(s.baseTileLayer); s.baseTileLayer = L.tileLayer(next.tileUrl, { + crossOrigin: BitMapLeaflet._tileCrossOrigin, maxZoom: next.tileMaxZoom, attribution: next.tileAttribution, opacity: next.tileOpacity, @@ -427,6 +442,7 @@ namespace BitBlazorUI { delete s.tileOverlays[opts.id]; } const tl = L.tileLayer(opts.urlTemplate, { + crossOrigin: BitMapLeaflet._tileCrossOrigin, opacity: opts.opacity ?? 1, zIndex: opts.zIndex ?? 100, maxZoom: opts.maxZoom ?? 19, diff --git a/src/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitMapOpenLayers.ts b/src/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitMapOpenLayers.ts index 01564f73bfa..2bd1fcf442a 100644 --- a/src/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitMapOpenLayers.ts +++ b/src/BlazorUI/Bit.BlazorUI.Extras/Components/Map/Providers/BitMapOpenLayers.ts @@ -5,6 +5,19 @@ namespace BitBlazorUI { * Mirrors the public surface used by every BitMap provider. */ export class BitMapOpenLayers { + /** + * crossOrigin value applied to every tile layer. + * + * When the host page is cross-origin isolated (COOP/COEP headers, required for the + * multi-threaded WebAssembly runtime) and the browser only supports + * COEP: require-corp (Safari/WebKit), plain no-cors tile requests to a server that + * does not send a Cross-Origin-Resource-Policy header are blocked, so tiles are + * requested in CORS mode instead (public tile servers such as OSM, Carto and + * OpenTopoMap all send Access-Control-Allow-Origin: *). On a non-isolated page the + * default no-cors mode is kept so tile servers without CORS headers keep working. + */ + private static readonly _tileCrossOrigin: string | undefined = self.crossOriginIsolated ? 'anonymous' : undefined; + private static _olLoadPromise: Promise | null = null; private static _maps: { [id: string]: { @@ -53,6 +66,7 @@ namespace BitBlazorUI { const baseTile = new ol.TileLayer({ source: new ol.XYZ({ + crossOrigin: BitMapOpenLayers._tileCrossOrigin, url: tileUrl, maxZoom: tileMaxZoom, attributions: tileAttribution, @@ -210,6 +224,7 @@ namespace BitBlazorUI { nextTileMaxZoom !== s.tileMaxZoom || nextTileAttribution !== s.tileAttribution) { s.baseTileLayer.setSource(new ol.XYZ({ + crossOrigin: BitMapOpenLayers._tileCrossOrigin, url: nextTileUrl, maxZoom: nextTileMaxZoom, attributions: nextTileAttribution, @@ -461,6 +476,7 @@ namespace BitBlazorUI { } const tl = new ol.TileLayer({ source: new ol.XYZ({ + crossOrigin: BitMapOpenLayers._tileCrossOrigin, url: (opts.urlTemplate || '').replace('{s}', 'a'), maxZoom: opts.maxZoom ?? 19, attributions: opts.attribution || '', diff --git a/src/BlazorUI/Bit.BlazorUI.Extras/Scripts/Extras.ts b/src/BlazorUI/Bit.BlazorUI.Extras/Scripts/Extras.ts index f5f215e6288..cc621cb30db 100644 --- a/src/BlazorUI/Bit.BlazorUI.Extras/Scripts/Extras.ts +++ b/src/BlazorUI/Bit.BlazorUI.Extras/Scripts/Extras.ts @@ -90,16 +90,19 @@ namespace BitBlazorUI { return promise; async function addScript(url: string) { - return new Promise((res, rej) => { + return Extras.loadWithCorsFallback(url, crossOrigin => new Promise((res, rej) => { const script = document.createElement('script'); script.src = url; if (isModule) { script.type = 'module'; } - script.onload = res; - script.onerror = rej; + if (crossOrigin) { + script.crossOrigin = 'anonymous'; + } + script.onload = () => res(script); + script.onerror = () => { script.remove(); rej(new Error(`Failed to load script: ${url}`)); }; document.body.appendChild(script); - }) + })); } } @@ -128,14 +131,46 @@ namespace BitBlazorUI { return promise; async function addStylesheet(url: string) { - return new Promise((res, rej) => { + return Extras.loadWithCorsFallback(url, crossOrigin => new Promise((res, rej) => { const link = document.createElement('link'); link.href = url; link.rel = 'stylesheet'; - link.onload = res; - link.onerror = rej; + if (crossOrigin) { + link.crossOrigin = 'anonymous'; + } + link.onload = () => res(link); + link.onerror = () => { link.remove(); rej(new Error(`Failed to load stylesheet: ${url}`)); }; document.head.appendChild(link); - }) + })); + } + } + + /** + * Loads a resource in no-cors mode first and, when that fails for a cross-origin URL, + * retries once in CORS mode (crossorigin="anonymous"). + * + * When the page is cross-origin isolated with Cross-Origin-Embedder-Policy: require-corp + * (the only COEP value Safari supports, needed for the multi-threaded WebAssembly runtime), + * a cross-origin script/stylesheet is blocked unless its response carries a + * Cross-Origin-Resource-Policy header or it is requested in CORS mode. Most CDNs send + * Access-Control-Allow-Origin: * but not CORP, so the CORS retry makes them load. Under + * COEP: credentialless (Chromium/Firefox) the first attempt succeeds and no retry happens, + * so hosts without CORS headers keep working there. + */ + private static async loadWithCorsFallback(url: string, load: (crossOrigin: boolean) => Promise): Promise { + try { + return await load(false); + } catch (e) { + if (!Extras.isCrossOrigin(url)) throw e; + return await load(true); + } + } + + private static isCrossOrigin(url: string): boolean { + try { + return new URL(url, document.baseURI).origin !== window.location.origin; + } catch { + return false; } } diff --git a/src/BlazorUI/Bit.BlazorUI.Legacy/Scripts/Legacy.ts b/src/BlazorUI/Bit.BlazorUI.Legacy/Scripts/Legacy.ts index 1ad2bb8e07e..8012188778d 100644 --- a/src/BlazorUI/Bit.BlazorUI.Legacy/Scripts/Legacy.ts +++ b/src/BlazorUI/Bit.BlazorUI.Legacy/Scripts/Legacy.ts @@ -25,16 +25,19 @@ namespace BitBlazorUI.Legacy { return promise; async function addScript(url: string) { - return new Promise((res, rej) => { + return Utils.loadWithCorsFallback(url, crossOrigin => new Promise((res, rej) => { const script = document.createElement('script'); script.src = url; if (isModule) { script.type = 'module'; } - script.onload = res; - script.onerror = rej; + if (crossOrigin) { + script.crossOrigin = 'anonymous'; + } + script.onload = () => res(script); + script.onerror = () => { script.remove(); rej(new Error(`Failed to load script: ${url}`)); }; document.body.appendChild(script); - }) + })); } } @@ -63,14 +66,46 @@ namespace BitBlazorUI.Legacy { return promise; async function addStylesheet(url: string) { - return new Promise((res, rej) => { + return Utils.loadWithCorsFallback(url, crossOrigin => new Promise((res, rej) => { const link = document.createElement('link'); link.href = url; link.rel = 'stylesheet'; - link.onload = res; - link.onerror = rej; + if (crossOrigin) { + link.crossOrigin = 'anonymous'; + } + link.onload = () => res(link); + link.onerror = () => { link.remove(); rej(new Error(`Failed to load stylesheet: ${url}`)); }; document.head.appendChild(link); - }) + })); + } + } + + /** + * Loads a resource in no-cors mode first and, when that fails for a cross-origin URL, + * retries once in CORS mode (crossorigin="anonymous"). + * + * When the page is cross-origin isolated with Cross-Origin-Embedder-Policy: require-corp + * (the only COEP value Safari supports, needed for the multi-threaded WebAssembly runtime), + * a cross-origin script/stylesheet is blocked unless its response carries a + * Cross-Origin-Resource-Policy header or it is requested in CORS mode. Most CDNs send + * Access-Control-Allow-Origin: * but not CORP, so the CORS retry makes them load. Under + * COEP: credentialless (Chromium/Firefox) the first attempt succeeds and no retry happens, + * so hosts without CORS headers keep working there. + */ + private static async loadWithCorsFallback(url: string, load: (crossOrigin: boolean) => Promise): Promise { + try { + return await load(false); + } catch (e) { + if (!Utils.isCrossOrigin(url)) throw e; + return await load(true); + } + } + + private static isCrossOrigin(url: string): boolean { + try { + return new URL(url, document.baseURI).origin !== window.location.origin; + } catch { + return false; } } diff --git a/src/BlazorUI/Demo/Bit.BlazorUI.Demo.Server/Startup/Middlewares.cs b/src/BlazorUI/Demo/Bit.BlazorUI.Demo.Server/Startup/Middlewares.cs index 8a5507a76b2..d1ae4c0952f 100644 --- a/src/BlazorUI/Demo/Bit.BlazorUI.Demo.Server/Startup/Middlewares.cs +++ b/src/BlazorUI/Demo/Bit.BlazorUI.Demo.Server/Startup/Middlewares.cs @@ -19,14 +19,32 @@ public static void Use(WebApplication app, IWebHostEnvironment env, IConfigurati // Cross-origin isolation, required for the multi-threaded WebAssembly runtime // (WasmEnableThreads in Bit.BlazorUI.Demo.Client.Web) to use SharedArrayBuffer. // Without these headers on the top-level document, crossOriginIsolated stays - // false and the runtime silently falls back to a single thread. COEP - // 'credentialless' is used instead of 'require-corp' so cross-origin - // subresources (fonts, images) keep loading without their own CORP/CORS headers; - // it enables isolation on Chromium and Firefox (Safari needs 'require-corp'). + // false and the threaded runtime refuses to start ("SharedArrayBuffer is not + // enabled on this page"). COEP 'credentialless' is preferred over 'require-corp' + // because it lets cross-origin subresources (fonts, images, scripts) load without + // their own CORP/CORS headers. Safari (WebKit, i.e. every browser on iOS) does not + // understand 'credentialless' and treats it as 'unsafe-none', so it never becomes + // cross-origin isolated and the runtime fails to boot; for WebKit the stricter + // 'require-corp' is sent instead. Under 'require-corp' every cross-origin + // subresource must either carry a Cross-Origin-Resource-Policy header or be + // loaded in CORS mode (crossorigin="anonymous"), which is why the demo pages use + // local images and the Extras/Legacy script loaders request CORS mode. app.Use(async (context, next) => { context.Response.Headers["Cross-Origin-Opener-Policy"] = "same-origin"; - context.Response.Headers["Cross-Origin-Embedder-Policy"] = "credentialless"; + context.Response.Headers["Cross-Origin-Embedder-Policy"] = IsWebKit(context.Request) ? "require-corp" : "credentialless"; + context.Response.OnStarting(() => + { + // COEP is only read from the top-level document response, so the UA-dependent value + // only matters for HTML; "Vary: User-Agent" keeps a shared cache/CDN from serving one + // browser's document to another. Static assets (the only publicly cached responses) + // deliberately get no Vary so their cache is not fragmented per User-Agent. + if (context.Response.ContentType?.StartsWith("text/html", StringComparison.OrdinalIgnoreCase) is true) + { + context.Response.Headers.Append("Vary", "User-Agent"); + } + return Task.CompletedTask; + }); await next.Invoke(context); }); @@ -115,6 +133,24 @@ public static void Use(WebApplication app, IWebHostEnvironment env, IConfigurati .AddAdditionalAssemblies(AssemblyLoadContext.Default.Assemblies.Where(asm => asm.GetName().Name?.Contains("Bit.BlazorUI.Demo") is true).Except([Assembly.GetExecutingAssembly()]).ToArray()); } + /// + /// Detects WebKit-based browsers: Safari on macOS and iOS/iPadOS, in-app WKWebViews (whose UA lacks the + /// "Safari" token) and every third-party browser on iOS (Chrome, Firefox, Edge... all report + /// "CriOS"/"FxiOS"/"EdgiOS" on top of AppleWebKit). Chromium-based browsers also carry "AppleWebKit" in + /// their UA, so they are excluded by the "Chrome"/"Chromium" token (desktop Edge/Opera/Brave/Samsung all + /// include "Chrome"); desktop Firefox does not contain "AppleWebKit" at all. + /// + private static bool IsWebKit(HttpRequest request) + { + var ua = request.Headers.UserAgent.ToString(); + + if (ua.Contains("AppleWebKit", StringComparison.OrdinalIgnoreCase) is false) return false; + + return ua.Contains("Chrome", StringComparison.OrdinalIgnoreCase) is false + && ua.Contains("Chromium", StringComparison.OrdinalIgnoreCase) is false + && ua.Contains("Firefox", StringComparison.OrdinalIgnoreCase) is false; + } + /// /// Prior to the introduction of .NET 8, the Blazor router effectively managed NotFound and NotAuthorized components during pre-rendering. /// However, the current behavior has changed, and it now exclusively returns 401, 403, and 404 status codes with an empty body response! diff --git a/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/Map/BitMapDemo.razor b/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/Map/BitMapDemo.razor index 48b054d0655..282d15db06c 100644 --- a/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/Map/BitMapDemo.razor +++ b/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/Map/BitMapDemo.razor @@ -247,6 +247,13 @@ Cesium ion dashboard, grant only the asset access it needs, and add your production domains to the token's allowed URLs list so a copied token cannot be used from other origins. +

+ Note (Safari): this demo site is served cross-origin isolated (COOP/COEP headers) to enable the + multi-threaded WebAssembly runtime. Safari only supports Cross-Origin-Embedder-Policy: require-corp, + under which cross-origin scripts must be sent with a Cross-Origin-Resource-Policy or CORS header. + The CesiumJS script on cesium.com sends neither, so the browser blocks it and this example does + not render in Safari (macOS/iOS). It works on Chromium and Firefox, and in your own app as long as you do not + send COEP require-corp, or self-host CesiumJS.
diff --git a/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/RichTextEditor/BitRichTextEditorDemo.razor b/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/RichTextEditor/BitRichTextEditorDemo.razor index 0b62771b81a..952fdf8b6b8 100644 --- a/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/RichTextEditor/BitRichTextEditorDemo.razor +++ b/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/RichTextEditor/BitRichTextEditorDemo.razor @@ -216,6 +216,13 @@ The Media group embeds a direct audio/video URL as a native video/audio element. The Rule group inserts a horizontal divider. Note: iframe embeds (e.g. YouTube/Vimeo) are not kept by the default sanitization policy, so supply a custom policy that allows the iframe tag if you need such embeds. +

+ Note: this demo site is served cross-origin isolated (COOP/COEP headers) to enable the + multi-threaded WebAssembly runtime. Under COEP a cross-origin iframe (YouTube/Vimeo) is blocked unless + the embedded page opts in, and in Safari (which only supports require-corp) a cross-origin + audio/video URL is also blocked unless its server sends a Cross-Origin-Resource-Policy or + CORS header. Media from your own origin, or from hosts that send those headers, is unaffected; so is any + app that does not send COEP.

+ ImageSrc="/_content/Bit.BlazorUI.Demo.Client.Core/images/choicegroup/choicegroup-bar-unselected.png" + SelectedImageSrc="/_content/Bit.BlazorUI.Demo.Client.Core/images/choicegroup/choicegroup-bar-selected.png" /> + ImageSrc="/_content/Bit.BlazorUI.Demo.Client.Core/images/choicegroup/choicegroup-pie-unselected.png" + SelectedImageSrc="/_content/Bit.BlazorUI.Demo.Client.Core/images/choicegroup/choicegroup-pie-selected.png" /> + ImageSrc="/_content/Bit.BlazorUI.Demo.Client.Core/images/choicegroup/choicegroup-bar-unselected.png" + SelectedImageSrc="/_content/Bit.BlazorUI.Demo.Client.Core/images/choicegroup/choicegroup-bar-selected.png" /> + ImageSrc="/_content/Bit.BlazorUI.Demo.Client.Core/images/choicegroup/choicegroup-pie-unselected.png" + SelectedImageSrc="/_content/Bit.BlazorUI.Demo.Client.Core/images/choicegroup/choicegroup-pie-selected.png" /> + ImageSrc="/_content/Bit.BlazorUI.Demo.Client.Core/images/choicegroup/choicegroup-bar-unselected.png" + SelectedImageSrc="/_content/Bit.BlazorUI.Demo.Client.Core/images/choicegroup/choicegroup-bar-selected.png" /> + ImageSrc="/_content/Bit.BlazorUI.Demo.Client.Core/images/choicegroup/choicegroup-pie-unselected.png" + SelectedImageSrc="/_content/Bit.BlazorUI.Demo.Client.Core/images/choicegroup/choicegroup-pie-selected.png" /> diff --git a/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/ChoiceGroup/_BitChoiceGroupOptionDemo.razor.samples.cs b/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/ChoiceGroup/_BitChoiceGroupOptionDemo.razor.samples.cs index 47e8fa48689..a5a93b8eb0e 100644 --- a/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/ChoiceGroup/_BitChoiceGroupOptionDemo.razor.samples.cs +++ b/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/ChoiceGroup/_BitChoiceGroupOptionDemo.razor.samples.cs @@ -45,14 +45,14 @@ public partial class _BitChoiceGroupOptionDemo Value=""@(""Bar"")"" ImageAlt=""Alt for Bar image"" ImageSize=""@(new BitImageSize(32, 32))"" - ImageSrc=""https://static2.sharepointonline.com/files/fabric/office-ui-fabric-react-assets/choicegroup-bar-unselected.png"" - SelectedImageSrc=""https://static2.sharepointonline.com/files/fabric/office-ui-fabric-react-assets/choicegroup-bar-selected.png"" /> + ImageSrc=""/_content/Bit.BlazorUI.Demo.Client.Core/images/choicegroup/choicegroup-bar-unselected.png"" + SelectedImageSrc=""/_content/Bit.BlazorUI.Demo.Client.Core/images/choicegroup/choicegroup-bar-selected.png"" /> + ImageSrc=""/_content/Bit.BlazorUI.Demo.Client.Core/images/choicegroup/choicegroup-pie-unselected.png"" + SelectedImageSrc=""/_content/Bit.BlazorUI.Demo.Client.Core/images/choicegroup/choicegroup-pie-selected.png"" /> + ImageSrc=""/_content/Bit.BlazorUI.Demo.Client.Core/images/choicegroup/choicegroup-bar-unselected.png"" + SelectedImageSrc=""/_content/Bit.BlazorUI.Demo.Client.Core/images/choicegroup/choicegroup-bar-selected.png"" /> + ImageSrc=""/_content/Bit.BlazorUI.Demo.Client.Core/images/choicegroup/choicegroup-pie-unselected.png"" + SelectedImageSrc=""/_content/Bit.BlazorUI.Demo.Client.Core/images/choicegroup/choicegroup-pie-selected.png"" /> + ImageSrc=""/_content/Bit.BlazorUI.Demo.Client.Core/images/choicegroup/choicegroup-bar-unselected.png"" + SelectedImageSrc=""/_content/Bit.BlazorUI.Demo.Client.Core/images/choicegroup/choicegroup-bar-selected.png"" /> + ImageSrc=""/_content/Bit.BlazorUI.Demo.Client.Core/images/choicegroup/choicegroup-pie-unselected.png"" + SelectedImageSrc=""/_content/Bit.BlazorUI.Demo.Client.Core/images/choicegroup/choicegroup-pie-selected.png"" /> "" TValue=""string"" DefaultValue=""@(""Day"")"" Horizontal> diff --git a/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/CircularTimePicker/BitCircularTimePickerDemo.razor b/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/CircularTimePicker/BitCircularTimePickerDemo.razor index 45972d2b5c0..ee7fb3bf185 100644 --- a/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/CircularTimePicker/BitCircularTimePickerDemo.razor +++ b/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/CircularTimePicker/BitCircularTimePickerDemo.razor @@ -337,7 +337,7 @@ - +


diff --git a/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/CircularTimePicker/BitCircularTimePickerDemo.razor.samples.cs b/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/CircularTimePicker/BitCircularTimePickerDemo.razor.samples.cs index 350e31d57d2..4cf6e5ffda3 100644 --- a/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/CircularTimePicker/BitCircularTimePickerDemo.razor.samples.cs +++ b/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/CircularTimePicker/BitCircularTimePickerDemo.razor.samples.cs @@ -202,7 +202,7 @@ private static BitTimeFormat GetTimeFormatOf(CultureInfo culture) IconLocation=""BitIconLocation.Left"" Placeholder=""Select a time""> - + diff --git a/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/TimePicker/BitTimePickerDemo.razor b/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/TimePicker/BitTimePickerDemo.razor index 2961e94954a..c78c2c4cded 100644 --- a/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/TimePicker/BitTimePickerDemo.razor +++ b/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/TimePicker/BitTimePickerDemo.razor @@ -542,7 +542,7 @@

- +

diff --git a/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/TimePicker/BitTimePickerDemo.razor.samples.cs b/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/TimePicker/BitTimePickerDemo.razor.samples.cs index 22106e31983..b9ca6fc56b3 100644 --- a/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/TimePicker/BitTimePickerDemo.razor.samples.cs +++ b/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/TimePicker/BitTimePickerDemo.razor.samples.cs @@ -309,7 +309,7 @@ private void Log(string message) - + diff --git a/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Lists/BasicList/BitBasicListDemo.razor b/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Lists/BasicList/BitBasicListDemo.razor index be27c120f1a..20d33c133f1 100644 --- a/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Lists/BasicList/BitBasicListDemo.razor +++ b/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Lists/BasicList/BitBasicListDemo.razor @@ -124,7 +124,7 @@ Style="border: 1px #a19f9d solid; border-radius: 4px;">
- +

Id: @person.Id

Full Name: @person.FirstName @person.LastName

@@ -150,7 +150,7 @@ Style="border: 1px #a19f9d solid; border-radius: 4px;">
- +

Id: @person.Id

Full Name: @person.FirstName @person.LastName

diff --git a/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Lists/BasicList/BitBasicListDemo.razor.samples.cs b/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Lists/BasicList/BitBasicListDemo.razor.samples.cs index 01c6194b09f..9bc1177b835 100644 --- a/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Lists/BasicList/BitBasicListDemo.razor.samples.cs +++ b/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Lists/BasicList/BitBasicListDemo.razor.samples.cs @@ -137,7 +137,7 @@ public class Person Style=""border: 1px #a19f9d solid; border-radius: 4px;"">
- +

Id: @person.Id

Full Name: @person.FirstName @person.LastName

@@ -171,7 +171,7 @@ public class Person Style=""border: 1px #a19f9d solid; border-radius: 4px;"">
- +

Id: @person.Id

Full Name: @person.FirstName @person.LastName

diff --git a/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Lists/Timeline/_BitTimelineCustomDemo.razor b/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Lists/Timeline/_BitTimelineCustomDemo.razor index 5048b03cf72..0149d258cfe 100644 --- a/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Lists/Timeline/_BitTimelineCustomDemo.razor +++ b/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Lists/Timeline/_BitTimelineCustomDemo.razor @@ -419,7 +419,7 @@ FirstContent = (item => @), + ImageUrl="/_content/Bit.BlazorUI.Demo.Client.Core/images/persona/persona-female.png" />), DotContent = (item => @
), @@ -447,7 +447,7 @@ FirstContent = (item => @), + ImageUrl="/_content/Bit.BlazorUI.Demo.Client.Core/images/persona/persona-male.png" />), DotContent = (item => @
), diff --git a/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Lists/Timeline/_BitTimelineCustomDemo.razor.samples.cs b/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Lists/Timeline/_BitTimelineCustomDemo.razor.samples.cs index 1364a4cbfb9..fd8dee8aa62 100644 --- a/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Lists/Timeline/_BitTimelineCustomDemo.razor.samples.cs +++ b/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Lists/Timeline/_BitTimelineCustomDemo.razor.samples.cs @@ -267,7 +267,7 @@ public class Event FirstContent = (item => @), + ImageUrl=""/_content/Bit.BlazorUI.Demo.Client.Core/images/persona/persona-female.png"" />), DotContent = (item => @
), @@ -295,7 +295,7 @@ public class Event FirstContent = (item => @), + ImageUrl=""/_content/Bit.BlazorUI.Demo.Client.Core/images/persona/persona-male.png"" />), DotContent = (item => @
), diff --git a/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Lists/Timeline/_BitTimelineItemDemo.razor b/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Lists/Timeline/_BitTimelineItemDemo.razor index 4fbd2b48d7f..bc0ca2a1b2f 100644 --- a/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Lists/Timeline/_BitTimelineItemDemo.razor +++ b/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Lists/Timeline/_BitTimelineItemDemo.razor @@ -418,7 +418,7 @@ PrimaryContent = (item => @), + ImageUrl="/_content/Bit.BlazorUI.Demo.Client.Core/images/persona/persona-female.png" />), DotTemplate = (item => @
), @@ -446,7 +446,7 @@ PrimaryContent = (item => @), + ImageUrl="/_content/Bit.BlazorUI.Demo.Client.Core/images/persona/persona-male.png" />), DotTemplate = (item => @
), diff --git a/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Lists/Timeline/_BitTimelineItemDemo.razor.samples.cs b/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Lists/Timeline/_BitTimelineItemDemo.razor.samples.cs index d5eca229a5d..8a272a0c146 100644 --- a/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Lists/Timeline/_BitTimelineItemDemo.razor.samples.cs +++ b/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Lists/Timeline/_BitTimelineItemDemo.razor.samples.cs @@ -207,7 +207,7 @@ public partial class _BitTimelineItemDemo PrimaryContent = (item => @), + ImageUrl=""/_content/Bit.BlazorUI.Demo.Client.Core/images/persona/persona-female.png"" />), DotTemplate = (item => @
), @@ -235,7 +235,7 @@ public partial class _BitTimelineItemDemo PrimaryContent = (item => @), + ImageUrl=""/_content/Bit.BlazorUI.Demo.Client.Core/images/persona/persona-male.png"" />), DotTemplate = (item => @
), diff --git a/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Lists/Timeline/_BitTimelineOptionDemo.razor b/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Lists/Timeline/_BitTimelineOptionDemo.razor index b1dccde8190..a8559bb9680 100644 --- a/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Lists/Timeline/_BitTimelineOptionDemo.razor +++ b/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Lists/Timeline/_BitTimelineOptionDemo.razor @@ -291,7 +291,7 @@ + ImageUrl="/_content/Bit.BlazorUI.Demo.Client.Core/images/persona/persona-female.png" />
@@ -328,7 +328,7 @@ + ImageUrl="/_content/Bit.BlazorUI.Demo.Client.Core/images/persona/persona-male.png" />
@@ -351,7 +351,7 @@ + ImageUrl="/_content/Bit.BlazorUI.Demo.Client.Core/images/persona/persona-female.png" />
@@ -388,7 +388,7 @@ + ImageUrl="/_content/Bit.BlazorUI.Demo.Client.Core/images/persona/persona-male.png" />
diff --git a/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Lists/Timeline/_BitTimelineOptionDemo.razor.samples.cs b/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Lists/Timeline/_BitTimelineOptionDemo.razor.samples.cs index 90bfcec1f8c..aae3235b592 100644 --- a/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Lists/Timeline/_BitTimelineOptionDemo.razor.samples.cs +++ b/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Lists/Timeline/_BitTimelineOptionDemo.razor.samples.cs @@ -215,7 +215,7 @@ public partial class _BitTimelineOptionDemo + ImageUrl=""/_content/Bit.BlazorUI.Demo.Client.Core/images/persona/persona-female.png"" />
@@ -252,7 +252,7 @@ public partial class _BitTimelineOptionDemo + ImageUrl=""/_content/Bit.BlazorUI.Demo.Client.Core/images/persona/persona-male.png"" />
diff --git a/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Progress/Shimmer/BitShimmerDemo.razor b/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Progress/Shimmer/BitShimmerDemo.razor index f2c0872a3bc..93200656380 100644 --- a/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Progress/Shimmer/BitShimmerDemo.razor +++ b/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Progress/Shimmer/BitShimmerDemo.razor @@ -73,7 +73,7 @@ SecondaryText="Software Engineer" Size="@BitPersonaSize.Size56" Presence="@BitPersonaPresence.Online" - ImageUrl="https://static2.sharepointonline.com/files/fabric/office-ui-fabric-react-assets/persona-female.png" /> + ImageUrl="/_content/Bit.BlazorUI.Demo.Client.Core/images/persona/persona-female.png" />