diff --git a/src/Masa.Blazor.JS/src/components/overlay/scrollStrategies.ts b/src/Masa.Blazor.JS/src/components/overlay/scrollStrategies.ts index 489bc062f9..a75dbf1a99 100644 --- a/src/Masa.Blazor.JS/src/components/overlay/scrollStrategies.ts +++ b/src/Masa.Blazor.JS/src/components/overlay/scrollStrategies.ts @@ -1,72 +1,79 @@ import { getScrollParents, hasScrollbar } from "utils/getScrollParent"; import { convertToUnit } from "utils/helper"; -export interface StrategyProps { - strategy: "none" | "block"; // | "close" | "reposition" +type StrategyProps = { + strategy: "none" | "block" | "close" | "reposition"; contained: boolean | undefined; -} - -class ScrollStrategies { - root: HTMLElement; - contentEl: HTMLElement; - options: StrategyProps; - - // maybe only used for block strategy - scrollElements: HTMLElement[]; - scrollableParent: Element | null; - - constructor( - root: HTMLElement, - contentEl: HTMLElement, - options: StrategyProps - ) { - if (!root) { - return; - } - - this.root = root; - this.contentEl = contentEl; - this.options = options; - } - - bind() { - if (this.options.strategy === "block") { - this._prepareBlock(); - this._blockScroll(); - } - } - - unbind() { - if (this.options.strategy === "block") { - this._unblockScroll(); - } - } - - _prepareBlock() { - const offsetParent = this.root.offsetParent; - this.scrollElements = [ - ...new Set([ - ...getScrollParents( - this.contentEl, - this.options.contained ? offsetParent : undefined - ), - ]), - ]; - - this.scrollableParent = ((el) => hasScrollbar(el) && el)( - offsetParent || document.documentElement +}; + +type ScrollStrategyData = { + root: HTMLElement | undefined; + contentEl: HTMLElement | undefined; + targetEl: HTMLElement | undefined; + invoker?: DotNet.DotNetObject; +}; + +type ScrollStrategyResult = { + bind?: () => void; + unbind: () => void; +}; + +export function useScrollStrategies( + props: StrategyProps, + root: HTMLElement | undefined, + contentEl: HTMLElement | undefined, + targetEl: HTMLElement | undefined, + dotNet?: DotNet.DotNetObject +): ScrollStrategyResult { + if (props.strategy === "block") { + return useBlockScrollStrategy( + { + root, + contentEl, + targetEl, + }, + props + ); + } else { + return useInvokerScrollStrategy( + { + root, + contentEl, + targetEl, + invoker: dotNet, + }, + props ); } +} - _blockScroll() { - if (this.scrollableParent) { - this.root.classList.add("m-overlay--scroll-blocked"); +function useBlockScrollStrategy( + data: ScrollStrategyData, + options: StrategyProps +): ScrollStrategyResult { + const offsetParent = data.root.offsetParent; + const scrollElements = [ + ...new Set([ + ...getScrollParents( + data.contentEl, + options.contained ? offsetParent : undefined + ), + ]), + ]; + + const scrollableParent = ((el) => hasScrollbar(el) && el)( + offsetParent || document.documentElement + ); + + const bind = () => { + if (scrollableParent) { + data.root.classList.add("m-overlay--scroll-blocked"); } const scrollbarWidth = window.innerWidth - document.documentElement.offsetWidth; - this.scrollElements + scrollElements .filter((el) => !el.classList.contains("m-overlay-scroll-blocked")) .forEach((el, i) => { el.style.setProperty( @@ -84,37 +91,64 @@ class ScrollStrategies { el.classList.add("m-overlay-scroll-blocked"); }); - } - - _unblockScroll() { - this.scrollElements - .filter((el) => el.classList.contains("m-overlay-scroll-blocked")) - .forEach((el, i) => { - const x = parseFloat(el.style.getPropertyValue("--m-body-scroll-x")); - const y = parseFloat(el.style.getPropertyValue("--m-body-scroll-y")); - - const scrollBehavior = el.style.scrollBehavior; - - el.style.scrollBehavior = "auto"; - el.style.removeProperty("--m-body-scroll-x"); - el.style.removeProperty("--m-body-scroll-y"); - el.style.removeProperty("--m-scrollbar-offset"); - el.classList.remove("m-overlay-scroll-blocked"); - - el.scrollLeft = -x; - el.scrollTop = -y; - - el.style.scrollBehavior = scrollBehavior; - }); - - if (this.scrollableParent) { - this.root.classList.remove("m-overlay--scroll-blocked"); - } - } + }; + + bind(); + + return { + bind, + unbind: () => { + scrollElements + .filter((el) => el.classList.contains("m-overlay-scroll-blocked")) + .forEach((el, i) => { + const x = parseFloat(el.style.getPropertyValue("--m-body-scroll-x")); + const y = parseFloat(el.style.getPropertyValue("--m-body-scroll-y")); + + const scrollBehavior = el.style.scrollBehavior; + + el.style.scrollBehavior = "auto"; + el.style.removeProperty("--m-body-scroll-x"); + el.style.removeProperty("--m-body-scroll-y"); + el.style.removeProperty("--m-scrollbar-offset"); + el.classList.remove("m-overlay-scroll-blocked"); + + el.scrollLeft = -x; + el.scrollTop = -y; + + el.style.scrollBehavior = scrollBehavior; + }); + + if (scrollableParent) { + data.root.classList.remove("m-overlay--scroll-blocked"); + } + }, + }; } -function init(root: HTMLElement, contentEl: HTMLElement, props: StrategyProps) { - return new ScrollStrategies(root, contentEl, props); -} +function useInvokerScrollStrategy( + data: ScrollStrategyData, + options: StrategyProps +) { + const el = data.targetEl ?? data.contentEl; -export { init }; + const onScroll = () => { + data.invoker?.invokeMethodAsync( + "ScrollStrategy_OnScroll", + options.strategy + ); + }; + + const scrollElements = [document, ...getScrollParents(el)]; + scrollElements.forEach((el) => + el.addEventListener("scroll", onScroll, { passive: true }) + ); + + return { + unbind: () => { + data.invoker?.dispose(); + scrollElements.forEach((el) => + el.removeEventListener("scroll", onScroll) + ); + }, + }; +} diff --git a/src/Masa.Blazor/Components/Menu/MMenu.razor.cs b/src/Masa.Blazor/Components/Menu/MMenu.razor.cs index 59de5c1fbd..1c96133876 100644 --- a/src/Masa.Blazor/Components/Menu/MMenu.razor.cs +++ b/src/Masa.Blazor/Components/Menu/MMenu.razor.cs @@ -1,5 +1,5 @@ -using Masa.Blazor.Mixins; -using Masa.Blazor.Mixins.Menuable; +using Masa.Blazor.Mixins.Menuable; +using Masa.Blazor.Mixins.ScrollStrategy; namespace Masa.Blazor { @@ -7,6 +7,8 @@ public partial class MMenu : MMenuable, IDependent { [Inject] private OutsideClickJSModule OutsideClickJSModule { get; set; } = null!; + [Inject] private ScrollStrategyJSModule ScrollStrategyJSModule { get; set; } = default!; + [CascadingParameter] public IDependent? CascadingDependent { get; set; } [CascadingParameter(Name = "AppIsDark")] @@ -35,7 +37,7 @@ public bool CloseOnContentClick [Parameter] [MasaApiParameter("auto")] public StringNumber MaxHeight { get; set; } = "auto"; [Parameter] public EventCallback OnScroll { get; set; } - + [Parameter] public EventCallback OnOutsideClick { get; set; } [Parameter] public string? Origin { get; set; } @@ -50,6 +52,10 @@ public bool CloseOnContentClick [Parameter] public bool Light { get; set; } + [Parameter] + [MasaApiParameter(ReleasedOn = "v1.8.0")] + public ScrollStrategy ScrollStrategy { get; set; } = ScrollStrategy.Reposition; + private static Block _block = new("m-menu"); private ModifierBuilder _modifierBuilder = _block.CreateModifierBuilder(); private ModifierBuilder _contentModifierBuilder = _block.Element("content").CreateModifierBuilder(); @@ -58,6 +64,8 @@ public bool CloseOnContentClick private readonly List _dependents = new(); private bool _isPopupEventsRegistered; + private ScrollStrategyResult? _scrollStrategyResult; + private DotNetObjectReference? _dotNetObjectReference; public bool IsDark { @@ -231,6 +239,14 @@ protected override async Task WhenIsActiveUpdating(bool value) _isPopupEventsRegistered = true; RegisterPopupEvents(ContentElement.GetSelector()!, CloseOnContentClick); + + if (ScrollStrategy != ScrollStrategy.None || (Absolute && ScrollStrategy != ScrollStrategy.Reposition)) + { + _dotNetObjectReference ??= DotNetObjectReference.Create(this); + + _scrollStrategyResult = await ScrollStrategyJSModule.CreateScrollStrategy(Ref, ContentElement, + new ScrollStrategyOptions(ScrollStrategy.Reposition), _dotNetObjectReference); + } } if (!OpenOnHover && CloseOnClick && OutsideClickJSModule is { Initialized: false }) @@ -239,6 +255,24 @@ protected override async Task WhenIsActiveUpdating(bool value) } } + [JSInvokable("ScrollStrategy_OnScroll")] + public async Task ScrollStrategy_OnScroll(string strategy) + { + switch (strategy) + { + case "close": + RunDirectly(false); + break; + case "reposition": + await UpdateDimensionsAsync(); + StateHasChanged(); + break; + default: + Logger.LogWarning("Unknown scroll strategy: {0}", strategy); + break; + } + } + private Func>? CloseConditional { get; set; } private Func? Handler { get; set; } @@ -273,6 +307,8 @@ private double CalcLeftAuto() protected override async ValueTask DisposeAsyncCore() { await OutsideClickJSModule.UnbindAndDisposeAsync(); + _scrollStrategyResult?.Unbind?.Invoke(); + _scrollStrategyResult?.Dispose?.Invoke(); await base.DisposeAsyncCore(); } } diff --git a/src/Masa.Blazor/Components/Overlay/MOverlay.razor.cs b/src/Masa.Blazor/Components/Overlay/MOverlay.razor.cs index 961f708a25..783750afed 100644 --- a/src/Masa.Blazor/Components/Overlay/MOverlay.razor.cs +++ b/src/Masa.Blazor/Components/Overlay/MOverlay.razor.cs @@ -133,27 +133,30 @@ protected override IEnumerable BuildComponentStyle() } } + private ScrollStrategyResult? _scrollStrategyResult; + private async Task HideScroll() { - if (!ScrollStrategyJSModule.Initialized) + if (_scrollStrategyResult is null) { - await ScrollStrategyJSModule.InitializeAsync(Ref, ContentRef, - new(ScrollStrategy.Block, Contained)); + _scrollStrategyResult = + await ScrollStrategyJSModule.CreateScrollStrategy(Ref, ContentRef, + new(ScrollStrategy.Block, Contained)); + } + else + { + _scrollStrategyResult.Bind?.Invoke(); } - - await ScrollStrategyJSModule.BindAsync(); } private async Task ShowScroll() { - await ScrollStrategyJSModule.UnbindAsync(); + _scrollStrategyResult?.Unbind?.Invoke(); } protected override async ValueTask DisposeAsyncCore() { - if (ScrollStrategyJSModule.Initialized) - { - await ShowScroll(); - } + _scrollStrategyResult?.Unbind?.Invoke(); + _scrollStrategyResult?.Dispose?.Invoke(); } } \ No newline at end of file diff --git a/src/Masa.Blazor/Extensions/DependencyInjection/ServiceCollectionExtensions.cs b/src/Masa.Blazor/Extensions/DependencyInjection/ServiceCollectionExtensions.cs index e176a53446..d0d9fc8233 100644 --- a/src/Masa.Blazor/Extensions/DependencyInjection/ServiceCollectionExtensions.cs +++ b/src/Masa.Blazor/Extensions/DependencyInjection/ServiceCollectionExtensions.cs @@ -95,7 +95,7 @@ private static IMasaBlazorBuilder AddMasaBlazorInternal(this IServiceCollection services.TryAddTransient(); services.TryAddTransient(); services.TryAddTransient(); - services.TryAddTransient(); + services.TryAddScoped(); services.TryAddScoped(); services.TryAddScoped(); diff --git a/src/Masa.Blazor/Mixins/ScrollStrategy/ScrollStrategy.cs b/src/Masa.Blazor/Mixins/ScrollStrategy/ScrollStrategy.cs new file mode 100644 index 0000000000..bf44bd9121 --- /dev/null +++ b/src/Masa.Blazor/Mixins/ScrollStrategy/ScrollStrategy.cs @@ -0,0 +1,9 @@ +namespace Masa.Blazor; + +public enum ScrollStrategy +{ + None, + Block, + Close, + Reposition +} \ No newline at end of file diff --git a/src/Masa.Blazor/Mixins/ScrollStrategy/ScrollStrategyJSModule.cs b/src/Masa.Blazor/Mixins/ScrollStrategy/ScrollStrategyJSModule.cs index ebb377a041..7f11381f01 100644 --- a/src/Masa.Blazor/Mixins/ScrollStrategy/ScrollStrategyJSModule.cs +++ b/src/Masa.Blazor/Mixins/ScrollStrategy/ScrollStrategyJSModule.cs @@ -2,30 +2,32 @@ namespace Masa.Blazor.Mixins; -public class ScrollStrategyJSModule : JSModule +public class ScrollStrategyJSModule(IJSRuntime js) + : JSModule(js, "./_content/Masa.Blazor/js/scrollStrategies.js?version=2") { - private IJSObjectReference? _instance; - - public ScrollStrategyJSModule(IJSRuntime js) : base(js, "./_content/Masa.Blazor/js/scrollStrategies.js") - { - } - - public bool Initialized { get; private set; } - - public async Task InitializeAsync(ElementReference root, ElementReference contentRef, ScrollStrategyOptions options) + public async ValueTask CreateScrollStrategy(ElementReference root, + ElementReference contentRef, ScrollStrategyOptions options) { - _instance = await InvokeAsync("init", root, contentRef, options); - - Initialized = true; - } + var instance = await InvokeAsync("useScrollStrategies", options, root, contentRef, null); - public async Task BindAsync() - { - await _instance.TryInvokeVoidAsync("bind"); + return new ScrollStrategyResult( + () => _ = instance!.InvokeVoidAsync("bind"), + () => _ = instance!.InvokeVoidAsync("unbind"), + () => _ = instance!.DisposeAsync() + ); } - public async Task UnbindAsync() + public async ValueTask CreateScrollStrategy(ElementReference root, + ElementReference contentRef, ScrollStrategyOptions options, + DotNetObjectReference dotNetObjectReference) where TComponent : class { - await _instance.TryInvokeVoidAsync("unbind"); + var instance = await InvokeAsync("useScrollStrategies", options, root, contentRef, null, + dotNetObjectReference); + + return new ScrollStrategyResult( + () => _ = instance!.InvokeVoidAsync("bind"), + () => _ = instance!.InvokeVoidAsync("unbind"), + () => _ = instance!.DisposeAsync() + ); } } \ No newline at end of file diff --git a/src/Masa.Blazor/Mixins/ScrollStrategy/ScrollStrategyOptions.cs b/src/Masa.Blazor/Mixins/ScrollStrategy/ScrollStrategyOptions.cs index 42ad1486dd..46f2537a07 100644 --- a/src/Masa.Blazor/Mixins/ScrollStrategy/ScrollStrategyOptions.cs +++ b/src/Masa.Blazor/Mixins/ScrollStrategy/ScrollStrategyOptions.cs @@ -1,20 +1,9 @@ namespace Masa.Blazor.Mixins.ScrollStrategy; -public class ScrollStrategyOptions +public class ScrollStrategyOptions(Blazor.ScrollStrategy strategy, bool contained = false) { - public ScrollStrategyOptions(ScrollStrategy strategy, bool contained) - { - Strategy = strategy; - Contained = contained; - } - [JsonConverter(typeof(JsonCamelStringEnumConverter))] - public ScrollStrategy Strategy { get; set; } - - public bool Contained { get; set; } -} + public Blazor.ScrollStrategy Strategy { get; set; } = strategy; -public enum ScrollStrategy -{ - Block + public bool Contained { get; set; } = contained; } \ No newline at end of file diff --git a/src/Masa.Blazor/Mixins/ScrollStrategy/ScrollStrategyResult.cs b/src/Masa.Blazor/Mixins/ScrollStrategy/ScrollStrategyResult.cs new file mode 100644 index 0000000000..d72ba8826e --- /dev/null +++ b/src/Masa.Blazor/Mixins/ScrollStrategy/ScrollStrategyResult.cs @@ -0,0 +1,3 @@ +namespace Masa.Blazor.Mixins.ScrollStrategy; + +public record ScrollStrategyResult(Action? Bind, Action? Unbind, Action? Dispose); \ No newline at end of file diff --git a/src/Masa.Blazor/wwwroot/js/scrollStrategies.js b/src/Masa.Blazor/wwwroot/js/scrollStrategies.js index e241862bf0..01ac8baba4 100644 --- a/src/Masa.Blazor/wwwroot/js/scrollStrategies.js +++ b/src/Masa.Blazor/wwwroot/js/scrollStrategies.js @@ -1,2 +1,2 @@ -function e(e,o){const l=[];if(o&&e&&!o.contains(e))return l;for(;e&&(t(e)&&l.push(e),e!==o);)e=e.parentElement;return l}function t(e){if(!e||e.nodeType!==Node.ELEMENT_NODE)return!1;const t=window.getComputedStyle(e);return"scroll"===t.overflowY||"auto"===t.overflowY&&e.scrollHeight>e.clientHeight}let o=!1;try{if("undefined"!=typeof window){const e=Object.defineProperty({},"passive",{get:()=>{o=!0}});window.addEventListener("testListener",e,e),window.removeEventListener("testListener",e,e)}}catch(e){console.warn(e)}function l(e,t="px"){return null==e||""===e?void 0:isNaN(+e)?String(e):isFinite(+e)?`${Number(e)}${t}`:void 0}Object.freeze({enter:13,tab:9,delete:46,esc:27,space:32,up:38,down:40,left:37,right:39,end:35,home:36,del:46,backspace:8,insert:45,pageup:33,pagedown:34,shift:16});class s{constructor(e,t,o){e&&(this.root=e,this.contentEl=t,this.options=o)}bind(){"block"===this.options.strategy&&(this._prepareBlock(),this._blockScroll())}unbind(){"block"===this.options.strategy&&this._unblockScroll()}_prepareBlock(){const o=this.root.offsetParent;var l;this.scrollElements=[...new Set([...e(this.contentEl,this.options.contained?o:void 0)])],this.scrollableParent=t(l=o||document.documentElement)&&l}_blockScroll(){this.scrollableParent&&this.root.classList.add("m-overlay--scroll-blocked");const e=window.innerWidth-document.documentElement.offsetWidth;this.scrollElements.filter((e=>!e.classList.contains("m-overlay-scroll-blocked"))).forEach(((t,o)=>{t.style.setProperty("--m-body-scroll-x",l(-t.scrollLeft)),t.style.setProperty("--m-body-scroll-y",l(-t.scrollTop)),t!==document.documentElement&&t.style.setProperty("--m-scrollbar-offset",l(e)),t.classList.add("m-overlay-scroll-blocked")}))}_unblockScroll(){this.scrollElements.filter((e=>e.classList.contains("m-overlay-scroll-blocked"))).forEach(((e,t)=>{const o=parseFloat(e.style.getPropertyValue("--m-body-scroll-x")),l=parseFloat(e.style.getPropertyValue("--m-body-scroll-y")),s=e.style.scrollBehavior;e.style.scrollBehavior="auto",e.style.removeProperty("--m-body-scroll-x"),e.style.removeProperty("--m-body-scroll-y"),e.style.removeProperty("--m-scrollbar-offset"),e.classList.remove("m-overlay-scroll-blocked"),e.scrollLeft=-o,e.scrollTop=-l,e.style.scrollBehavior=s})),this.scrollableParent&&this.root.classList.remove("m-overlay--scroll-blocked")}}function r(e,t,o){return new s(e,t,o)}export{r as init}; +function e(e,t){const r=[];if(t&&e&&!t.contains(e))return r;for(;e&&(o(e)&&r.push(e),e!==t);)e=e.parentElement;return r}function o(e){if(!e||e.nodeType!==Node.ELEMENT_NODE)return!1;const o=window.getComputedStyle(e);return"scroll"===o.overflowY||"auto"===o.overflowY&&e.scrollHeight>e.clientHeight}const t="undefined"!=typeof window;let r=!1;try{if(t){const e=Object.defineProperty({},"passive",{get:()=>{r=!0}});window.addEventListener("testListener",e,e),window.removeEventListener("testListener",e,e)}}catch(e){console.warn(e)}function l(e,o="px"){return null==e||""===e?void 0:isNaN(+e)?String(e):isFinite(+e)?`${Number(e)}${o}`:void 0}function n(t,r,n,s,c){return"block"===t.strategy?function(t,r){const n=t.root.offsetParent,s=[...new Set([...e(t.contentEl,r.contained?n:void 0)])],c=(a=n||document.documentElement,o(a)&&a),i=()=>{c&&t.root.classList.add("m-overlay--scroll-blocked");const e=window.innerWidth-document.documentElement.offsetWidth;s.filter((e=>!e.classList.contains("m-overlay-scroll-blocked"))).forEach(((o,t)=>{o.style.setProperty("--m-body-scroll-x",l(-o.scrollLeft)),o.style.setProperty("--m-body-scroll-y",l(-o.scrollTop)),o!==document.documentElement&&o.style.setProperty("--m-scrollbar-offset",l(e)),o.classList.add("m-overlay-scroll-blocked")}))};var a;return i(),{bind:i,unbind:()=>{s.filter((e=>e.classList.contains("m-overlay-scroll-blocked"))).forEach(((e,o)=>{const t=parseFloat(e.style.getPropertyValue("--m-body-scroll-x")),r=parseFloat(e.style.getPropertyValue("--m-body-scroll-y")),l=e.style.scrollBehavior;e.style.scrollBehavior="auto",e.style.removeProperty("--m-body-scroll-x"),e.style.removeProperty("--m-body-scroll-y"),e.style.removeProperty("--m-scrollbar-offset"),e.classList.remove("m-overlay-scroll-blocked"),e.scrollLeft=-t,e.scrollTop=-r,e.style.scrollBehavior=l})),c&&t.root.classList.remove("m-overlay--scroll-blocked")}}}({root:r,contentEl:n,targetEl:s},t):function(o,t){var r;const l=null!==(r=o.targetEl)&&void 0!==r?r:o.contentEl,n=()=>{var e;null===(e=o.invoker)||void 0===e||e.invokeMethodAsync("ScrollStrategy_OnScroll",t.strategy)},s=[document,...e(l)];return s.forEach((e=>e.addEventListener("scroll",n,{passive:!0}))),{unbind:()=>{var e;null===(e=o.invoker)||void 0===e||e.dispose(),s.forEach((e=>e.removeEventListener("scroll",n)))}}}({root:r,contentEl:n,targetEl:s,invoker:c},t)}Object.freeze({enter:13,tab:9,delete:46,esc:27,space:32,up:38,down:40,left:37,right:39,end:35,home:36,del:46,backspace:8,insert:45,pageup:33,pagedown:34,shift:16});export{n as useScrollStrategies}; //# sourceMappingURL=scrollStrategies.js.map diff --git a/src/Masa.Blazor/wwwroot/js/scrollStrategies.js.map b/src/Masa.Blazor/wwwroot/js/scrollStrategies.js.map index 2a546c03d9..c223597a92 100644 --- a/src/Masa.Blazor/wwwroot/js/scrollStrategies.js.map +++ b/src/Masa.Blazor/wwwroot/js/scrollStrategies.js.map @@ -1 +1 @@ -{"version":3,"file":"scrollStrategies.js","sources":["../../../Masa.Blazor.JS/src/utils/getScrollParent.ts","../../../Masa.Blazor.JS/src/utils/helper.ts","../../../Masa.Blazor.JS/src/components/overlay/scrollStrategies.ts"],"sourcesContent":["export function getScrollParent (el?: HTMLElement) {\r\n while (el) {\r\n if (hasScrollbar(el)) return el\r\n el = el.parentElement!\r\n }\r\n\r\n return document.scrollingElement as HTMLElement\r\n}\r\n\r\nexport function getScrollParents (el?: Element | null, stopAt?: Element | null) {\r\n const elements: HTMLElement[] = []\r\n\r\n if (stopAt && el && !stopAt.contains(el)) return elements\r\n\r\n while (el) {\r\n if (hasScrollbar(el)) elements.push(el as HTMLElement)\r\n if (el === stopAt) break\r\n el = el.parentElement!\r\n }\r\n\r\n return elements\r\n}\r\n\r\nexport function hasScrollbar (el?: Element | null) {\r\n if (!el || el.nodeType !== Node.ELEMENT_NODE) return false\r\n\r\n const style = window.getComputedStyle(el)\r\n return style.overflowY === 'scroll' || (style.overflowY === 'auto' && el.scrollHeight > el.clientHeight)\r\n}\r\n","export function addOnceEventListener (\r\n el: EventTarget,\r\n eventName: string,\r\n cb: (event: Event) => void,\r\n options: boolean | AddEventListenerOptions = false\r\n): void {\r\n const once = (event: Event) => {\r\n cb(event)\r\n el.removeEventListener(eventName, once, options)\r\n }\r\n\r\n el.addEventListener(eventName, once, options)\r\n}\r\n\r\nlet passiveSupported = false\r\ntry {\r\n if (typeof window !== 'undefined') {\r\n const testListenerOpts = Object.defineProperty({}, 'passive', {\r\n get: () => {\r\n passiveSupported = true\r\n },\r\n })\r\n\r\n window.addEventListener('testListener' as any, testListenerOpts as any, testListenerOpts)\r\n window.removeEventListener('testListener' as any, testListenerOpts as any, testListenerOpts)\r\n }\r\n} catch (e) { console.warn(e) } /* eslint-disable-line no-console */\r\nexport { passiveSupported }\r\n\r\nexport function addPassiveEventListener (\r\n el: EventTarget,\r\n event: string,\r\n cb: ((e: any) => void),\r\n options: {}\r\n): void {\r\n el.addEventListener(event, cb, passiveSupported ? options : false)\r\n}\r\n\r\nexport function getZIndex (el?: Element | null): number {\r\n if (!el || el.nodeType !== Node.ELEMENT_NODE) return 0\r\n\r\n const index = +window.getComputedStyle(el).getPropertyValue('z-index')\r\n\r\n if (!index) return getZIndex(el.parentNode as Element)\r\n return index\r\n}\r\n\r\n// KeyboardEvent.keyCode aliases\r\nexport const keyCodes = Object.freeze({\r\n enter: 13,\r\n tab: 9,\r\n delete: 46,\r\n esc: 27,\r\n space: 32,\r\n up: 38,\r\n down: 40,\r\n left: 37,\r\n right: 39,\r\n end: 35,\r\n home: 36,\r\n del: 46,\r\n backspace: 8,\r\n insert: 45,\r\n pageup: 33,\r\n pagedown: 34,\r\n shift: 16,\r\n})\r\n\r\n/** Polyfill for Event.prototype.composedPath */\r\nexport function composedPath (e: Event): EventTarget[] {\r\n if (e.composedPath) return e.composedPath()\r\n\r\n const path = []\r\n let el = e.target as Element\r\n\r\n while (el) {\r\n path.push(el)\r\n\r\n if (el.tagName === 'HTML') {\r\n path.push(document)\r\n path.push(window)\r\n\r\n return path\r\n }\r\n\r\n el = el.parentElement!\r\n }\r\n return path\r\n}\r\n\r\nexport function getBlazorId(el) {\r\n if (!el) {\r\n return null;\r\n }\r\n let _bl_ = el.getAttributeNames().find(a => a.startsWith('_bl_'))\r\n if (_bl_) {\r\n _bl_ = _bl_.substring(4);\r\n }\r\n\r\n return _bl_;\r\n}\r\n\r\nexport function getElementSelector(el) {\r\n if (!(el instanceof Element))\r\n return;\r\n var path = [];\r\n while (el.nodeType === Node.ELEMENT_NODE) {\r\n var selector = el.nodeName.toLowerCase();\r\n if (el.id) {\r\n selector = '#' + el.id;\r\n path.unshift(selector);\r\n break;\r\n } else {\r\n var sib = el, nth = 1;\r\n while (sib = sib.previousElementSibling) {\r\n if (sib.nodeName.toLowerCase() == selector)\r\n nth++;\r\n }\r\n if (nth != 1)\r\n selector += \":nth-of-type(\" + nth + \")\";\r\n }\r\n path.unshift(selector);\r\n el = el.parentNode;\r\n }\r\n return path.join(\" > \");\r\n}\r\n\r\nexport function getEventTarget(target: HTMLElement | EventTarget) {\r\n const el = target as HTMLElement;\r\n const eventTarget: MbEventTarget = {};\r\n const elementReferenceId = el\r\n .getAttributeNames()\r\n .find((a) => a.startsWith(\"_bl_\"));\r\n if (elementReferenceId) {\r\n eventTarget.elementReferenceId = elementReferenceId;\r\n eventTarget.selector = `[${elementReferenceId}]`;\r\n } else {\r\n eventTarget.selector = getElementSelector(el);\r\n }\r\n\r\n eventTarget.class = el.getAttribute(\"class\");\r\n\r\n return eventTarget;\r\n}\r\n\r\nexport function getDom(elOrString: Element | string | undefined) {\r\n let element: HTMLElement;\r\n\r\n try {\r\n if (!elOrString) {\r\n element = document.body;\r\n } else if (typeof elOrString === \"string\") {\r\n if (elOrString === \"document\") {\r\n element = document.documentElement;\r\n } else if (elOrString.indexOf(\"__.__\") > 0) {\r\n // for example: el__.__parentElement\r\n let array = elOrString.split(\"__.__\");\r\n let i = 0;\r\n let el = document.querySelector(array[i++]);\r\n\r\n if (el) {\r\n while (array[i]) {\r\n el = el[array[i]];\r\n i++;\r\n }\r\n }\r\n\r\n if (el instanceof HTMLElement) {\r\n element = el;\r\n }\r\n } else {\r\n element = document.querySelector(elOrString);\r\n }\r\n } else {\r\n element = elOrString as HTMLElement;\r\n }\r\n\r\n } catch (error) {\r\n console.error(error)\r\n }\r\n\r\n return element;\r\n}\r\n\r\nexport const canUseDom = !!(\r\n typeof window !== 'undefined' &&\r\n typeof document !== 'undefined' &&\r\n window.document &&\r\n window.document.createElement\r\n)\r\n\r\nexport function convertToUnit (str: number, unit?: string): string\r\nexport function convertToUnit (str: string | number | null | undefined, unit?: string): string | undefined\r\nexport function convertToUnit (str: string | number | null | undefined, unit = 'px'): string | undefined {\r\n if (str == null || str === '') {\r\n return undefined\r\n } else if (isNaN(+str!)) {\r\n return String(str)\r\n } else if (!isFinite(+str!)) {\r\n return undefined\r\n } else {\r\n return `${Number(str)}${unit}`\r\n }\r\n}","import { getScrollParents, hasScrollbar } from \"utils/getScrollParent\";\r\nimport { convertToUnit } from \"utils/helper\";\r\n\r\nexport interface StrategyProps {\r\n strategy: \"none\" | \"block\"; // | \"close\" | \"reposition\"\r\n contained: boolean | undefined;\r\n}\r\n\r\nclass ScrollStrategies {\r\n root: HTMLElement;\r\n contentEl: HTMLElement;\r\n options: StrategyProps;\r\n\r\n // maybe only used for block strategy\r\n scrollElements: HTMLElement[];\r\n scrollableParent: Element | null;\r\n\r\n constructor(\r\n root: HTMLElement,\r\n contentEl: HTMLElement,\r\n options: StrategyProps\r\n ) {\r\n if (!root) {\r\n return;\r\n }\r\n\r\n this.root = root;\r\n this.contentEl = contentEl;\r\n this.options = options;\r\n }\r\n\r\n bind() {\r\n if (this.options.strategy === \"block\") {\r\n this._prepareBlock();\r\n this._blockScroll();\r\n }\r\n }\r\n\r\n unbind() {\r\n if (this.options.strategy === \"block\") {\r\n this._unblockScroll();\r\n }\r\n }\r\n\r\n _prepareBlock() {\r\n const offsetParent = this.root.offsetParent;\r\n this.scrollElements = [\r\n ...new Set([\r\n ...getScrollParents(\r\n this.contentEl,\r\n this.options.contained ? offsetParent : undefined\r\n ),\r\n ]),\r\n ];\r\n\r\n this.scrollableParent = ((el) => hasScrollbar(el) && el)(\r\n offsetParent || document.documentElement\r\n );\r\n }\r\n\r\n _blockScroll() {\r\n if (this.scrollableParent) {\r\n this.root.classList.add(\"m-overlay--scroll-blocked\");\r\n }\r\n\r\n const scrollbarWidth =\r\n window.innerWidth - document.documentElement.offsetWidth;\r\n\r\n this.scrollElements\r\n .filter((el) => !el.classList.contains(\"m-overlay-scroll-blocked\"))\r\n .forEach((el, i) => {\r\n el.style.setProperty(\r\n \"--m-body-scroll-x\",\r\n convertToUnit(-el.scrollLeft)\r\n );\r\n el.style.setProperty(\"--m-body-scroll-y\", convertToUnit(-el.scrollTop));\r\n\r\n if (el !== document.documentElement) {\r\n el.style.setProperty(\r\n \"--m-scrollbar-offset\",\r\n convertToUnit(scrollbarWidth)\r\n );\r\n }\r\n\r\n el.classList.add(\"m-overlay-scroll-blocked\");\r\n });\r\n }\r\n\r\n _unblockScroll() {\r\n this.scrollElements\r\n .filter((el) => el.classList.contains(\"m-overlay-scroll-blocked\"))\r\n .forEach((el, i) => {\r\n const x = parseFloat(el.style.getPropertyValue(\"--m-body-scroll-x\"));\r\n const y = parseFloat(el.style.getPropertyValue(\"--m-body-scroll-y\"));\r\n\r\n const scrollBehavior = el.style.scrollBehavior;\r\n\r\n el.style.scrollBehavior = \"auto\";\r\n el.style.removeProperty(\"--m-body-scroll-x\");\r\n el.style.removeProperty(\"--m-body-scroll-y\");\r\n el.style.removeProperty(\"--m-scrollbar-offset\");\r\n el.classList.remove(\"m-overlay-scroll-blocked\");\r\n\r\n el.scrollLeft = -x;\r\n el.scrollTop = -y;\r\n\r\n el.style.scrollBehavior = scrollBehavior;\r\n });\r\n\r\n if (this.scrollableParent) {\r\n this.root.classList.remove(\"m-overlay--scroll-blocked\");\r\n }\r\n }\r\n}\r\n\r\nfunction init(root: HTMLElement, contentEl: HTMLElement, props: StrategyProps) {\r\n return new ScrollStrategies(root, contentEl, props);\r\n}\r\n\r\nexport { init };\r\n"],"names":["getScrollParents","el","stopAt","elements","contains","hasScrollbar","push","parentElement","nodeType","Node","ELEMENT_NODE","style","window","getComputedStyle","overflowY","scrollHeight","clientHeight","passiveSupported","testListenerOpts","Object","defineProperty","get","addEventListener","removeEventListener","e","console","warn","convertToUnit","str","unit","isNaN","String","isFinite","Number","freeze","enter","tab","delete","esc","space","up","down","left","right","end","home","del","backspace","insert","pageup","pagedown","shift","ScrollStrategies","constructor","root","contentEl","options","this","bind","strategy","_prepareBlock","_blockScroll","unbind","_unblockScroll","offsetParent","scrollElements","Set","contained","undefined","scrollableParent","document","documentElement","classList","add","scrollbarWidth","innerWidth","offsetWidth","filter","forEach","i","setProperty","scrollLeft","scrollTop","x","parseFloat","getPropertyValue","y","scrollBehavior","removeProperty","remove","init","props"],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"scrollStrategies.js","sources":["../../../Masa.Blazor.JS/src/utils/getScrollParent.ts","../../../Masa.Blazor.JS/src/utils/helper.ts","../../../Masa.Blazor.JS/src/components/overlay/scrollStrategies.ts"],"sourcesContent":["export function getScrollParent (el?: HTMLElement) {\r\n while (el) {\r\n if (hasScrollbar(el)) return el\r\n el = el.parentElement!\r\n }\r\n\r\n return document.scrollingElement as HTMLElement\r\n}\r\n\r\nexport function getScrollParents (el?: Element | null, stopAt?: Element | null) {\r\n const elements: HTMLElement[] = []\r\n\r\n if (stopAt && el && !stopAt.contains(el)) return elements\r\n\r\n while (el) {\r\n if (hasScrollbar(el)) elements.push(el as HTMLElement)\r\n if (el === stopAt) break\r\n el = el.parentElement!\r\n }\r\n\r\n return elements\r\n}\r\n\r\nexport function hasScrollbar (el?: Element | null) {\r\n if (!el || el.nodeType !== Node.ELEMENT_NODE) return false\r\n\r\n const style = window.getComputedStyle(el)\r\n return style.overflowY === 'scroll' || (style.overflowY === 'auto' && el.scrollHeight > el.clientHeight)\r\n}\r\n","export const IN_BROWSER = typeof window !== 'undefined'\r\n\r\nexport function addOnceEventListener (\r\n el: EventTarget,\r\n eventName: string,\r\n cb: (event: Event) => void,\r\n options: boolean | AddEventListenerOptions = false\r\n): void {\r\n const once = (event: Event) => {\r\n cb(event)\r\n el.removeEventListener(eventName, once, options)\r\n }\r\n\r\n el.addEventListener(eventName, once, options)\r\n}\r\n\r\nlet passiveSupported = false\r\ntry {\r\n if (IN_BROWSER) {\r\n const testListenerOpts = Object.defineProperty({}, 'passive', {\r\n get: () => {\r\n passiveSupported = true\r\n },\r\n })\r\n\r\n window.addEventListener('testListener' as any, testListenerOpts as any, testListenerOpts)\r\n window.removeEventListener('testListener' as any, testListenerOpts as any, testListenerOpts)\r\n }\r\n} catch (e) { console.warn(e) } /* eslint-disable-line no-console */\r\nexport { passiveSupported }\r\n\r\nexport function addPassiveEventListener (\r\n el: EventTarget,\r\n event: string,\r\n cb: ((e: any) => void),\r\n options: {}\r\n): void {\r\n el.addEventListener(event, cb, passiveSupported ? options : false)\r\n}\r\n\r\nexport function getZIndex (el?: Element | null): number {\r\n if (!el || el.nodeType !== Node.ELEMENT_NODE) return 0\r\n\r\n const index = +window.getComputedStyle(el).getPropertyValue('z-index')\r\n\r\n if (!index) return getZIndex(el.parentNode as Element)\r\n return index\r\n}\r\n\r\n// KeyboardEvent.keyCode aliases\r\nexport const keyCodes = Object.freeze({\r\n enter: 13,\r\n tab: 9,\r\n delete: 46,\r\n esc: 27,\r\n space: 32,\r\n up: 38,\r\n down: 40,\r\n left: 37,\r\n right: 39,\r\n end: 35,\r\n home: 36,\r\n del: 46,\r\n backspace: 8,\r\n insert: 45,\r\n pageup: 33,\r\n pagedown: 34,\r\n shift: 16,\r\n})\r\n\r\n/** Polyfill for Event.prototype.composedPath */\r\nexport function composedPath (e: Event): EventTarget[] {\r\n if (e.composedPath) return e.composedPath()\r\n\r\n const path = []\r\n let el = e.target as Element\r\n\r\n while (el) {\r\n path.push(el)\r\n\r\n if (el.tagName === 'HTML') {\r\n path.push(document)\r\n path.push(window)\r\n\r\n return path\r\n }\r\n\r\n el = el.parentElement!\r\n }\r\n return path\r\n}\r\n\r\nexport function getBlazorId(el) {\r\n if (!el) {\r\n return null;\r\n }\r\n let _bl_ = el.getAttributeNames().find(a => a.startsWith('_bl_'))\r\n if (_bl_) {\r\n _bl_ = _bl_.substring(4);\r\n }\r\n\r\n return _bl_;\r\n}\r\n\r\nexport function getElementSelector(el) {\r\n if (!(el instanceof Element))\r\n return;\r\n var path = [];\r\n while (el.nodeType === Node.ELEMENT_NODE) {\r\n var selector = el.nodeName.toLowerCase();\r\n if (el.id) {\r\n selector = '#' + el.id;\r\n path.unshift(selector);\r\n break;\r\n } else {\r\n var sib = el, nth = 1;\r\n while (sib = sib.previousElementSibling) {\r\n if (sib.nodeName.toLowerCase() == selector)\r\n nth++;\r\n }\r\n if (nth != 1)\r\n selector += \":nth-of-type(\" + nth + \")\";\r\n }\r\n path.unshift(selector);\r\n el = el.parentNode;\r\n }\r\n return path.join(\" > \");\r\n}\r\n\r\nexport function getEventTarget(target: HTMLElement | EventTarget) {\r\n const el = target as HTMLElement;\r\n const eventTarget: MbEventTarget = {};\r\n const elementReferenceId = el\r\n .getAttributeNames()\r\n .find((a) => a.startsWith(\"_bl_\"));\r\n if (elementReferenceId) {\r\n eventTarget.elementReferenceId = elementReferenceId;\r\n eventTarget.selector = `[${elementReferenceId}]`;\r\n } else {\r\n eventTarget.selector = getElementSelector(el);\r\n }\r\n\r\n eventTarget.class = el.getAttribute(\"class\");\r\n\r\n return eventTarget;\r\n}\r\n\r\nexport function getDom(elOrString: Element | string | undefined) {\r\n let element: HTMLElement;\r\n\r\n try {\r\n if (!elOrString) {\r\n element = document.body;\r\n } else if (typeof elOrString === \"string\") {\r\n if (elOrString === \"document\") {\r\n element = document.documentElement;\r\n } else if (elOrString.indexOf(\"__.__\") > 0) {\r\n // for example: el__.__parentElement\r\n let array = elOrString.split(\"__.__\");\r\n let i = 0;\r\n let el = document.querySelector(array[i++]);\r\n\r\n if (el) {\r\n while (array[i]) {\r\n el = el[array[i]];\r\n i++;\r\n }\r\n }\r\n\r\n if (el instanceof HTMLElement) {\r\n element = el;\r\n }\r\n } else {\r\n element = document.querySelector(elOrString);\r\n }\r\n } else {\r\n element = elOrString as HTMLElement;\r\n }\r\n\r\n } catch (error) {\r\n console.error(error)\r\n }\r\n\r\n return element;\r\n}\r\n\r\nexport const canUseDom = !!(\r\n IN_BROWSER &&\r\n typeof document !== 'undefined' &&\r\n window.document &&\r\n window.document.createElement\r\n)\r\n\r\nexport function convertToUnit (str: number, unit?: string): string\r\nexport function convertToUnit (str: string | number | null | undefined, unit?: string): string | undefined\r\nexport function convertToUnit (str: string | number | null | undefined, unit = 'px'): string | undefined {\r\n if (str == null || str === '') {\r\n return undefined\r\n } else if (isNaN(+str!)) {\r\n return String(str)\r\n } else if (!isFinite(+str!)) {\r\n return undefined\r\n } else {\r\n return `${Number(str)}${unit}`\r\n }\r\n}","import { getScrollParents, hasScrollbar } from \"utils/getScrollParent\";\nimport { convertToUnit } from \"utils/helper\";\n\ntype StrategyProps = {\n strategy: \"block\" | \"close\";\n contained: boolean | undefined;\n};\n\ntype ScrollStrategyData = {\n root: HTMLElement | undefined;\n contentEl: HTMLElement | undefined;\n targetEl: HTMLElement | undefined;\n invoker?: DotNet.DotNetObject;\n};\n\ntype ScrollStrategyResult = {\n bind?: () => void;\n unbind: () => void;\n};\n\nexport function useScrollStrategies(\n props: StrategyProps,\n root: HTMLElement | undefined,\n contentEl: HTMLElement | undefined,\n targetEl: HTMLElement | undefined,\n dotNet?: DotNet.DotNetObject\n): ScrollStrategyResult {\n if (props.strategy === \"block\") {\n return useBlockScrollStrategy(\n {\n root,\n contentEl,\n targetEl,\n },\n props\n );\n } else {\n return useInvokerScrollStrategy(\n {\n root,\n contentEl,\n targetEl,\n invoker: dotNet,\n },\n props\n );\n }\n}\n\nfunction useBlockScrollStrategy(\n data: ScrollStrategyData,\n options: StrategyProps\n): ScrollStrategyResult {\n const offsetParent = data.root.offsetParent;\n const scrollElements = [\n ...new Set([\n ...getScrollParents(\n data.contentEl,\n options.contained ? offsetParent : undefined\n ),\n ]),\n ];\n\n const scrollableParent = ((el) => hasScrollbar(el) && el)(\n offsetParent || document.documentElement\n );\n\n const bind = () => {\n if (scrollableParent) {\n data.root.classList.add(\"m-overlay--scroll-blocked\");\n }\n\n const scrollbarWidth =\n window.innerWidth - document.documentElement.offsetWidth;\n\n scrollElements\n .filter((el) => !el.classList.contains(\"m-overlay-scroll-blocked\"))\n .forEach((el, i) => {\n el.style.setProperty(\n \"--m-body-scroll-x\",\n convertToUnit(-el.scrollLeft)\n );\n el.style.setProperty(\"--m-body-scroll-y\", convertToUnit(-el.scrollTop));\n\n if (el !== document.documentElement) {\n el.style.setProperty(\n \"--m-scrollbar-offset\",\n convertToUnit(scrollbarWidth)\n );\n }\n\n el.classList.add(\"m-overlay-scroll-blocked\");\n });\n };\n\n bind();\n\n return {\n bind,\n unbind: () => {\n scrollElements\n .filter((el) => el.classList.contains(\"m-overlay-scroll-blocked\"))\n .forEach((el, i) => {\n const x = parseFloat(el.style.getPropertyValue(\"--m-body-scroll-x\"));\n const y = parseFloat(el.style.getPropertyValue(\"--m-body-scroll-y\"));\n\n const scrollBehavior = el.style.scrollBehavior;\n\n el.style.scrollBehavior = \"auto\";\n el.style.removeProperty(\"--m-body-scroll-x\");\n el.style.removeProperty(\"--m-body-scroll-y\");\n el.style.removeProperty(\"--m-scrollbar-offset\");\n el.classList.remove(\"m-overlay-scroll-blocked\");\n\n el.scrollLeft = -x;\n el.scrollTop = -y;\n\n el.style.scrollBehavior = scrollBehavior;\n });\n\n if (scrollableParent) {\n data.root.classList.remove(\"m-overlay--scroll-blocked\");\n }\n },\n };\n}\n\nfunction useInvokerScrollStrategy(\n data: ScrollStrategyData,\n options: StrategyProps\n) {\n const el = data.targetEl ?? data.contentEl;\n\n const onScroll = () => {\n data.invoker?.invokeMethodAsync(\n \"ScrollStrategy_OnScroll\",\n options.strategy\n );\n };\n\n const scrollElements = [document, ...getScrollParents(el)];\n scrollElements.forEach((el) =>\n el.addEventListener(\"scroll\", onScroll, { passive: true })\n );\n\n return {\n unbind: () => {\n data.invoker?.dispose();\n scrollElements.forEach((el) =>\n el.removeEventListener(\"scroll\", onScroll)\n );\n },\n };\n}\n"],"names":["getScrollParents","el","stopAt","elements","contains","hasScrollbar","push","parentElement","nodeType","Node","ELEMENT_NODE","style","window","getComputedStyle","overflowY","scrollHeight","clientHeight","IN_BROWSER","passiveSupported","testListenerOpts","Object","defineProperty","get","addEventListener","removeEventListener","e","console","warn","convertToUnit","str","unit","isNaN","String","isFinite","Number","useScrollStrategies","props","root","contentEl","targetEl","dotNet","strategy","data","options","offsetParent","scrollElements","Set","contained","undefined","scrollableParent","document","documentElement","bind","classList","add","scrollbarWidth","innerWidth","offsetWidth","filter","forEach","i","setProperty","scrollLeft","scrollTop","unbind","x","parseFloat","getPropertyValue","y","scrollBehavior","removeProperty","remove","useBlockScrollStrategy","_a","onScroll","invoker","invokeMethodAsync","passive","dispose","useInvokerScrollStrategy","freeze","enter","tab","delete","esc","space","up","down","left","right","end","home","del","backspace","insert","pageup","pagedown","shift"],"mappings":"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"} \ No newline at end of file