diff --git a/src/Uno.UI.Wasm/WasmScripts/Uno.UI.d.ts b/src/Uno.UI.Wasm/WasmScripts/Uno.UI.d.ts index cb0497d8be5c..d9344972cb9e 100644 --- a/src/Uno.UI.Wasm/WasmScripts/Uno.UI.d.ts +++ b/src/Uno.UI.Wasm/WasmScripts/Uno.UI.d.ts @@ -294,7 +294,12 @@ declare namespace Uno.UI { resetStyleNative(pParams: number): boolean; private resetStyleInternal; /** - * Set CSS classes on an element + * Set + Unset CSS classes on an element + */ + setUnsetClasses(elementId: number, cssClassesToSet: string[], cssClassesToUnset: string[]): void; + setUnsetClassesNative(pParams: number): boolean; + /** + * Set CSS classes on an element from a specified list */ setClasses(elementId: number, cssClassesList: string[], classIndex: number): string; setClassesNative(pParams: number): boolean; @@ -796,6 +801,14 @@ declare class WindowManagerSetSvgElementRectParams { HtmlId: number; static unmarshal(pData: number): WindowManagerSetSvgElementRectParams; } +declare class WindowManagerSetUnsetClassesParams { + HtmlId: number; + CssClassesToSet_Length: number; + CssClassesToSet: Array; + CssClassesToUnset_Length: number; + CssClassesToUnset: Array; + static unmarshal(pData: number): WindowManagerSetUnsetClassesParams; +} declare class WindowManagerSetXUidParams { HtmlId: number; Uid: string; diff --git a/src/Uno.UI.Wasm/WasmScripts/Uno.UI.js b/src/Uno.UI.Wasm/WasmScripts/Uno.UI.js index 3956b0ed5611..0dfd8a580ede 100644 --- a/src/Uno.UI.Wasm/WasmScripts/Uno.UI.js +++ b/src/Uno.UI.Wasm/WasmScripts/Uno.UI.js @@ -747,7 +747,28 @@ var Uno; } } /** - * Set CSS classes on an element + * Set + Unset CSS classes on an element + */ + setUnsetClasses(elementId, cssClassesToSet, cssClassesToUnset) { + const element = this.getView(elementId); + if (cssClassesToSet) { + cssClassesToSet.forEach(c => { + element.classList.add(c); + }); + } + if (cssClassesToUnset) { + cssClassesToUnset.forEach(c => { + element.classList.remove(c); + }); + } + } + setUnsetClassesNative(pParams) { + const params = WindowManagerSetUnsetClassesParams.unmarshal(pParams); + this.setUnsetClasses(params.HtmlId, params.CssClassesToSet, params.CssClassesToUnset); + return true; + } + /** + * Set CSS classes on an element from a specified list */ setClasses(elementId, cssClassesList, classIndex) { const element = this.getView(elementId); @@ -2651,6 +2672,58 @@ class WindowManagerSetSvgElementRectParams { } } /* TSBindingsGenerator Generated code -- this code is regenerated on each build */ +class WindowManagerSetUnsetClassesParams { + static unmarshal(pData) { + const ret = new WindowManagerSetUnsetClassesParams(); + { + ret.HtmlId = Number(Module.getValue(pData + 0, "*")); + } + { + ret.CssClassesToSet_Length = Number(Module.getValue(pData + 4, "i32")); + } + { + const pArray = Module.getValue(pData + 8, "*"); + if (pArray !== 0) { + ret.CssClassesToSet = new Array(); + for (var i = 0; i < ret.CssClassesToSet_Length; i++) { + const value = Module.getValue(pArray + i * 4, "*"); + if (value !== 0) { + ret.CssClassesToSet.push(String(MonoRuntime.conv_string(value))); + } + else { + ret.CssClassesToSet.push(null); + } + } + } + else { + ret.CssClassesToSet = null; + } + } + { + ret.CssClassesToUnset_Length = Number(Module.getValue(pData + 12, "i32")); + } + { + const pArray = Module.getValue(pData + 16, "*"); + if (pArray !== 0) { + ret.CssClassesToUnset = new Array(); + for (var i = 0; i < ret.CssClassesToUnset_Length; i++) { + const value = Module.getValue(pArray + i * 4, "*"); + if (value !== 0) { + ret.CssClassesToUnset.push(String(MonoRuntime.conv_string(value))); + } + else { + ret.CssClassesToUnset.push(null); + } + } + } + else { + ret.CssClassesToUnset = null; + } + } + return ret; + } +} +/* TSBindingsGenerator Generated code -- this code is regenerated on each build */ class WindowManagerSetXUidParams { static unmarshal(pData) { const ret = new WindowManagerSetXUidParams(); diff --git a/src/Uno.UI.Wasm/ts/WindowManager.ts b/src/Uno.UI.Wasm/ts/WindowManager.ts index e6c80325a7c5..bfab81823437 100644 --- a/src/Uno.UI.Wasm/ts/WindowManager.ts +++ b/src/Uno.UI.Wasm/ts/WindowManager.ts @@ -583,9 +583,33 @@ namespace Uno.UI { element.style.setProperty(name, ""); } } + /** + * Set + Unset CSS classes on an element + */ + + public setUnsetClasses(elementId: number, cssClassesToSet: string[], cssClassesToUnset: string[]) { + const element = this.getView(elementId); + + if (cssClassesToSet) { + cssClassesToSet.forEach(c => { + element.classList.add(c); + }); + } + if (cssClassesToUnset) { + cssClassesToUnset.forEach(c => { + element.classList.remove(c); + }); + } + } + + public setUnsetClassesNative(pParams: number): boolean { + const params = WindowManagerSetUnsetClassesParams.unmarshal(pParams); + this.setUnsetClasses(params.HtmlId, params.CssClassesToSet, params.CssClassesToUnset); + return true; + } /** - * Set CSS classes on an element + * Set CSS classes on an element from a specified list */ public setClasses(elementId: number, cssClassesList: string[], classIndex: number): string { const element = this.getView(elementId); diff --git a/src/Uno.UI.Wasm/tsBindings/WindowManagerSetUnsetClassesParams.ts b/src/Uno.UI.Wasm/tsBindings/WindowManagerSetUnsetClassesParams.ts new file mode 100644 index 000000000000..29b4436986cf --- /dev/null +++ b/src/Uno.UI.Wasm/tsBindings/WindowManagerSetUnsetClassesParams.ts @@ -0,0 +1,79 @@ +/* TSBindingsGenerator Generated code -- this code is regenerated on each build */ +class WindowManagerSetUnsetClassesParams +{ + /* Pack=4 */ + public HtmlId : number; + public CssClassesToSet_Length : number; + public CssClassesToSet : Array; + public CssClassesToUnset_Length : number; + public CssClassesToUnset : Array; + public static unmarshal(pData:number) : WindowManagerSetUnsetClassesParams + { + const ret = new WindowManagerSetUnsetClassesParams(); + + { + ret.HtmlId = Number(Module.getValue(pData + 0, "*")); + } + + { + ret.CssClassesToSet_Length = Number(Module.getValue(pData + 4, "i32")); + } + + { + const pArray = Module.getValue(pData + 8, "*"); + if(pArray !== 0) + { + ret.CssClassesToSet = new Array(); + for(var i=0; i(); + for(var i=0; i + /// Add/Set CSS classes to the HTML element. + /// + /// + /// No effect for classes already present on the element. + /// + protected internal void SetCssClasses(params string[] classesToSet) + { + Uno.UI.Xaml.WindowManagerInterop.SetUnsetCssClasses(HtmlId, classesToSet, null); + } + + /// + /// Remove/Unset CSS classes to the HTML element. + /// + /// + /// No effect for classes already absent from the element. + /// + protected internal void UnsetCssClasses(params string[] classesToUnset) + { + Uno.UI.Xaml.WindowManagerInterop.SetUnsetCssClasses(HtmlId, null, classesToUnset); + + } + + /// + /// Set and Unset css classes on a HTML element in a single operation. + /// + /// + /// Identical to calling followed by . + /// + protected internal void SetUnsetCssClasses(string[] classesToSet, string[] classesToUnset) + { + Uno.UI.Xaml.WindowManagerInterop.SetUnsetCssClasses(HtmlId, classesToSet, classesToUnset); + } + /// /// Set a specified CSS class to an element from a set of possible values. /// All other possible values will be removed from the element. diff --git a/src/Uno.UI/UI/Xaml/WindowManagerInterop.wasm.cs b/src/Uno.UI/UI/Xaml/WindowManagerInterop.wasm.cs index 6b99e61711b3..81b2450d1977 100644 --- a/src/Uno.UI/UI/Xaml/WindowManagerInterop.wasm.cs +++ b/src/Uno.UI/UI/Xaml/WindowManagerInterop.wasm.cs @@ -434,6 +434,63 @@ private static void SetArrangeProperties(IntPtr htmlId, bool requiresClipping) WebAssemblyRuntime.InvokeJS(command); } + #region SetUnsetCssClasses + internal static void SetUnsetCssClasses(IntPtr htmlId, string[] cssClassesToSet, string[] cssClassesToUnset) + { + if (UseJavascriptEval) + { + var setClasses = + cssClassesToSet == null + ? "null" + : "[" + + string.Join(", ", cssClassesToSet + .Select(WebAssemblyRuntime.EscapeJs) + .Select(s => "\"" + s + "\"")) + + "]"; + var unsetClasses = + cssClassesToUnset == null + ? "null" + : "[" + + string.Join(", ", cssClassesToUnset + .Select(WebAssemblyRuntime.EscapeJs) + .Select(s => "\"" + s + "\"")) + + "]"; + var command = "Uno.UI.WindowManager.current.setUnsetClasses(" + htmlId + ", " + setClasses + ", " + unsetClasses + ");"; + WebAssemblyRuntime.InvokeJS(command); + } + else + { + var parms = new WindowManagerSetUnsetClassesParams + { + HtmlId = htmlId, + CssClassesToSet = cssClassesToSet, + CssClassesToSet_Length = cssClassesToSet?.Length ?? 0, + CssClassesToUnset = cssClassesToUnset, + CssClassesToUnset_Length = cssClassesToUnset?.Length ?? 0 + }; + + TSInteropMarshaller.InvokeJS("Uno:setUnsetClassesNative", parms); + } + } + + [TSInteropMessage] + [StructLayout(LayoutKind.Sequential, Pack = 4)] + private struct WindowManagerSetUnsetClassesParams + { + public IntPtr HtmlId; + + public int CssClassesToSet_Length; + + [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPStr)] + public string[] CssClassesToSet; + + public int CssClassesToUnset_Length; + + [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPStr)] + public string[] CssClassesToUnset; + } + #endregion + #region SetClasses internal static void SetClasses(IntPtr htmlId, string[] cssClasses, int index)