diff --git a/.gitignore b/.gitignore index 43711f4..9259d82 100644 --- a/.gitignore +++ b/.gitignore @@ -234,4 +234,5 @@ _Pvt_Extensions .paket/paket.exe # FAKE - F# Make -.fake/ \ No newline at end of file +.fake/ +*.DotSettings diff --git a/Material/src/Material.csproj b/Material/src/Material.csproj index e6cd153..b3d2153 100644 --- a/Material/src/Material.csproj +++ b/Material/src/Material.csproj @@ -35,6 +35,7 @@ + diff --git a/Material/src/MaterialScripts.razor b/Material/src/MaterialScripts.razor index 54e1389..0760adc 100644 --- a/Material/src/MaterialScripts.razor +++ b/Material/src/MaterialScripts.razor @@ -1,2 +1,3 @@ - \ No newline at end of file + + diff --git a/Material/src/MaterialStyles.razor b/Material/src/MaterialStyles.razor index a8278a4..3c36e6f 100644 --- a/Material/src/MaterialStyles.razor +++ b/Material/src/MaterialStyles.razor @@ -25,4 +25,5 @@ - \ No newline at end of file + + diff --git a/Material/src/_Imports.razor b/Material/src/_Imports.razor index a093e3c..61d98fe 100644 --- a/Material/src/_Imports.razor +++ b/Material/src/_Imports.razor @@ -39,5 +39,6 @@ @using Skclusive.Material.Menu @using Skclusive.Material.Tab @using Skclusive.Material.Container +@using Skclusive.Material.Tooltip -@using Skclusive.Script.DomHelpers \ No newline at end of file +@using Skclusive.Script.DomHelpers diff --git a/Skclusive.Material.Component.sln b/Skclusive.Material.Component.sln index 2355090..6a4c6de 100644 --- a/Skclusive.Material.Component.sln +++ b/Skclusive.Material.Component.sln @@ -131,6 +131,10 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Container", "Container", "{ EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Container", "Container\src\Container.csproj", "{D3836F1B-3554-4F71-B450-FC23F467CD0A}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tooltip", "Tooltip", "{0290CE1B-D02B-4A3A-BA30-8B84D65AFA17}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Tooltip", "Tooltip\src\Tooltip.csproj", "{20C5D585-318C-4545-9808-23FFEC7676C6}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -140,9 +144,6 @@ Global Release|x64 = Release|x64 Release|x86 = Release|x86 EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {95D5904F-C4F1-40A2-A563-31D80424EB90}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {95D5904F-C4F1-40A2-A563-31D80424EB90}.Debug|Any CPU.Build.0 = Debug|Any CPU @@ -528,6 +529,21 @@ Global {D3836F1B-3554-4F71-B450-FC23F467CD0A}.Release|x64.Build.0 = Release|Any CPU {D3836F1B-3554-4F71-B450-FC23F467CD0A}.Release|x86.ActiveCfg = Release|Any CPU {D3836F1B-3554-4F71-B450-FC23F467CD0A}.Release|x86.Build.0 = Release|Any CPU + {20C5D585-318C-4545-9808-23FFEC7676C6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {20C5D585-318C-4545-9808-23FFEC7676C6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {20C5D585-318C-4545-9808-23FFEC7676C6}.Debug|x64.ActiveCfg = Debug|Any CPU + {20C5D585-318C-4545-9808-23FFEC7676C6}.Debug|x64.Build.0 = Debug|Any CPU + {20C5D585-318C-4545-9808-23FFEC7676C6}.Debug|x86.ActiveCfg = Debug|Any CPU + {20C5D585-318C-4545-9808-23FFEC7676C6}.Debug|x86.Build.0 = Debug|Any CPU + {20C5D585-318C-4545-9808-23FFEC7676C6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {20C5D585-318C-4545-9808-23FFEC7676C6}.Release|Any CPU.Build.0 = Release|Any CPU + {20C5D585-318C-4545-9808-23FFEC7676C6}.Release|x64.ActiveCfg = Release|Any CPU + {20C5D585-318C-4545-9808-23FFEC7676C6}.Release|x64.Build.0 = Release|Any CPU + {20C5D585-318C-4545-9808-23FFEC7676C6}.Release|x86.ActiveCfg = Release|Any CPU + {20C5D585-318C-4545-9808-23FFEC7676C6}.Release|x86.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE EndGlobalSection GlobalSection(NestedProjects) = preSolution {95D5904F-C4F1-40A2-A563-31D80424EB90} = {6AFD1E9C-D89B-4385-8954-2BCEF239FA91} @@ -562,5 +578,9 @@ Global {B8556016-D55D-4C84-B331-5369129D6A5F} = {91687B8F-58F5-4BD4-ADD5-F5F6D9A643BF} {2D6C4BA5-BA0D-4C6D-BC29-FF5C80D85198} = {FD4AC138-9A66-4E84-B512-319A59FDDC0A} {D3836F1B-3554-4F71-B450-FC23F467CD0A} = {BA2B6EE0-729F-40F7-9B63-8823B69D4571} + {20C5D585-318C-4545-9808-23FFEC7676C6} = {0290CE1B-D02B-4A3A-BA30-8B84D65AFA17} + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {BFE8C835-5479-476A-A98F-721CC3740275} EndGlobalSection EndGlobal diff --git a/Theme/src/Theme/ThemeBuilder.cs b/Theme/src/Theme/ThemeBuilder.cs index 83e3731..be9835c 100644 --- a/Theme/src/Theme/ThemeBuilder.cs +++ b/Theme/src/Theme/ThemeBuilder.cs @@ -30,6 +30,8 @@ public static ThemeConfig BuildCommon() ZindexDrawer = "1200", + ZindexTooltip = "1500", + Shadow0 = "none", Shadow1 = "0px 2px 1px -1px rgba(0, 0, 0, 0.2), 0px 1px 1px 0px rgba(0, 0, 0, 0.14), 0px 1px 3px 0px rgba(0, 0, 0, 0.12)", diff --git a/Theme/src/Theme/ThemeConfig.cs b/Theme/src/Theme/ThemeConfig.cs index e143bf2..0060092 100644 --- a/Theme/src/Theme/ThemeConfig.cs +++ b/Theme/src/Theme/ThemeConfig.cs @@ -18,6 +18,8 @@ public class ThemeConfig public string ZindexDrawer { set; get; } + public string ZindexTooltip { set; get; } + public string Shadow0 { set; get; } public string Shadow1 { set; get; } diff --git a/Theme/src/Theme/ThemeProducer.cs b/Theme/src/Theme/ThemeProducer.cs index b562546..28196ad 100644 --- a/Theme/src/Theme/ThemeProducer.cs +++ b/Theme/src/Theme/ThemeProducer.cs @@ -36,6 +36,7 @@ public static string BuildCommon(ThemeConfig theme) --theme-html-font-size: {theme.HtmlFontSize}; --theme-zindex-appbar: {theme.ZindexAppBar}; --theme-zindex-drawer: {theme.ZindexDrawer}; + --theme-zindex-tooltip: {theme.ZindexTooltip}; --theme-font-size-coef: calc(var(--theme-font-size) / 14); --theme-font-size-rem-factor: calc( var(--theme-font-size-coef) / var(--theme-html-font-size) diff --git a/Tooltip/src/Popper/IPopperContext.cs b/Tooltip/src/Popper/IPopperContext.cs new file mode 100644 index 0000000..df3efff --- /dev/null +++ b/Tooltip/src/Popper/IPopperContext.cs @@ -0,0 +1,67 @@ +using System; +using System.Collections.Generic; +using System.Text; +using Skclusive.Core.Component; + +namespace Skclusive.Material.Tooltip +{ + public interface IPopperContext : IComponentContext + { + bool Open { get; } + Action OnEnter { get; } + Action OnExited { get; } + } + + public class PopperContextBuilder : ComponentContextBuilder + { + public class PopperContext : ComponentContext, IPopperContext + { + public bool Open { get; internal set; } + public Action OnEnter { get; internal set; } + public Action OnExited { get; internal set; } + } + + protected PopperContext MContext => base.Context as PopperContext; + + public PopperContextBuilder() : base(new PopperContext()) + { + } + + public PopperContextBuilder WithOpen(bool open) + { + MContext.Open = open; + + return this; + } + + public PopperContextBuilder WithOnEnter(Action onEnter) + { + MContext.OnEnter = onEnter; + + return this; + } + + public PopperContextBuilder WithOnExited(Action onExited) + { + MContext.OnExited = onExited; + + return this; + } + + public override PopperContextBuilder With(IPopperContext context) + { + base.With(context) + .WithOpen(context.Open) + .WithRefBack(context.RefBack) + .WithOnEnter(context.OnEnter) + .WithOnExited(context.OnExited); + + return this; + } + + protected override PopperContextBuilder This() + { + return this; + } + } +} diff --git a/Tooltip/src/Popper/Popper.razor b/Tooltip/src/Popper/Popper.razor new file mode 100644 index 0000000..12e3220 --- /dev/null +++ b/Tooltip/src/Popper/Popper.razor @@ -0,0 +1,17 @@ +@namespace Skclusive.Material.Tooltip +@inherits MaterialComponentBase + +@if (!KeepMounted && !Open && (!Transition || TransitionExited())) +{ +} +else +{ + + + @ChildContent.Invoke(GetPopperContext(context)) + + +} diff --git a/Tooltip/src/Popper/Popper.razor.cs b/Tooltip/src/Popper/Popper.razor.cs new file mode 100644 index 0000000..903f58e --- /dev/null +++ b/Tooltip/src/Popper/Popper.razor.cs @@ -0,0 +1,199 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Components; +using Microsoft.JSInterop; +using NLog; +using Skclusive.Core.Component; + +namespace Skclusive.Material.Tooltip +{ + public partial class Popper + { + private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); + + [Inject] + public IJSRuntime JsRuntime { get; set; } + + [Parameter] + public IReference AnchorRef { get; set; } = new Reference(); + + [Parameter] + public bool DisablePortal { get; set; } = false; + + [Parameter] + public bool Open { get; set; } = false; + + [Parameter] + public bool KeepMounted { get; set; } = false; + + [Parameter] + public IReference Container { get; set; } + + [Parameter] + public PopperPlacement Placement { get; set; } + + [Parameter] + public bool Transition { get; set; } + + [Parameter] + public PopperOptions PopperOptions { get; set; } = new PopperOptions(); + + [Parameter] + public IReference ChildRef { get; set; } = new Reference(); + + [Parameter] + public RenderFragment ChildContent { get; set; } + + public PopperInstance PopperInstance { get; private set; } + + protected bool Exited { get; private set; } = true; + + + public Popper() : base("Popper") + { + } + + + private PopperContextBuilder PopperContextBuilder => new PopperContextBuilder().WithRefBack(ChildRef) + .WithOpen(Open) + .WithOnEnter(HandleEnter) + .WithOnExited(HandleExited); + + protected IPopperContext GetPopperContext(IComponentContext context) + { + return PopperContextBuilder.WithRefBack(new DelegateReference(ChildRef, context.RefBack)) + .Build(); + } + + private bool TransitionExited() + { + return Exited; + } + + protected void HandleEnter(IReference reference, bool appear) + { + Exited = false; + + // StateHasChanged(); + } + + protected void HandleExited(IReference reference) + { + Exited = true; + + // StateHasChanged(); + + //if (CloseAfterTransition) + //{ + // HandleClose(); + //} + } + + public override async Task SetParametersAsync(ParameterView parameters) + { + if (PopperInstance != null) + { + var newAnchorRef = parameters.GetValueOrDefault(nameof(AnchorRef)); + if (newAnchorRef?.Current?.Id != AnchorRef?.Current?.Id) + { + await DestroyPopper(PopperInstance.Id); + PopperInstance = null; + } + } + + await base.SetParametersAsync(parameters); + } + + protected override async Task OnAfterRenderAsync() + { + if (!KeepMounted && !Open && PopperInstance != null && TransitionExited()) + { + await HandleClose(); + } + + if (Open && PopperInstance == null) + { + InitializeOptions(); + PopperInstance = await CreatePopper(AnchorRef?.Current ?? RootRef.Current.Value, RootRef.Current.Value, PopperOptions); + } + + if (PopperInstance != null) + { + await UpdatePopper(PopperInstance.Id); + } + } + + private async Task HandleClose() + { + Logger.Info($"Popper:handleClose {TransitionExited()}"); + await DestroyPopper(PopperInstance.Id); + PopperInstance = null; + } + + private void InitializeOptions() + { + if (PopperOptions == null) + { + PopperOptions = new PopperOptions(); + } + + PopperOptions.Placement = Placement.MapToString(); + } + + private async Task CreatePopper(ElementReference reference, ElementReference popper, PopperOptions options) + { + var obj = await JsRuntime.InvokeAsync("Skclusive.Material.Tooltip.createBlazorPopper", reference, popper, options); + return obj; + } + + private ValueTask UpdatePopper(int id) + { + return JsRuntime.InvokeVoidAsync("Skclusive.Material.Tooltip.updatePopper", id); + } + + private ValueTask DestroyPopper(int id) + { + return JsRuntime.InvokeVoidAsync("Skclusive.Material.Tooltip.destroyPopper", id); + } + + protected override IEnumerable> Styles + { + get + { + foreach (var item in base.Styles) + yield return item; + + yield return Tuple.Create("position", "fixed"); + yield return Tuple.Create("top", "0"); + yield return Tuple.Create("left", "0"); + if (!Open && KeepMounted && !Transition) + { + yield return Tuple.Create("display", "none"); + } + } + } + + protected override void Dispose() + { + if (PopperInstance != null) + { + DestroyPopper(PopperInstance.Id); + } + + base.Dispose(); + } + + // TODO in .NET 5 + // https://github.com/dotnet/aspnetcore/issues/9960 + //public ValueTask DisposeAsync() + //{ + // if (PopperInstance != null) + // { + // return DestroyPopper(PopperInstance.Id); + // } + + // return default; + //} + } +} diff --git a/Tooltip/src/Popper/PopperInstance.cs b/Tooltip/src/Popper/PopperInstance.cs new file mode 100644 index 0000000..bdd7b6b --- /dev/null +++ b/Tooltip/src/Popper/PopperInstance.cs @@ -0,0 +1,13 @@ +namespace Skclusive.Material.Tooltip +{ + public class PopperInstance + { + public int Id { get; set; } + public PopperState State { get; set; } + + public object SetState { get; set; } + public object ForceUpdate { get; set; } + public object Update { get; set; } + public object Destroy { get; set; } + } +} diff --git a/Tooltip/src/Popper/PopperOptions.cs b/Tooltip/src/Popper/PopperOptions.cs new file mode 100644 index 0000000..c91d73d --- /dev/null +++ b/Tooltip/src/Popper/PopperOptions.cs @@ -0,0 +1,16 @@ +using System.Collections.Generic; + +namespace Skclusive.Material.Tooltip +{ + public class PopperOptions + { + public string Placement { get; set; } = PopperPlacementStrings.Bottom; + public IList Modifiers { get; } = new List(); // Not supported + public string Strategy { get; set; } = PopperStrategyStrings.Absolute; + + public override string ToString() + { + return $"{Placement} (Strategy: {Strategy})"; + } + } +} diff --git a/Tooltip/src/Popper/PopperPlacement.cs b/Tooltip/src/Popper/PopperPlacement.cs new file mode 100644 index 0000000..4ed196a --- /dev/null +++ b/Tooltip/src/Popper/PopperPlacement.cs @@ -0,0 +1,21 @@ +namespace Skclusive.Material.Tooltip +{ + public enum PopperPlacement + { + Auto, + AutoStart, + AutoEnd, + Top, + TopStart, + TopEnd, + Bottom, + BottomStart, + BottomEnd, + Right, + RightStart, + RightEnd, + Left, + LeftStart, + LeftEnd, + } +} diff --git a/Tooltip/src/Popper/PopperPlacementStrings.cs b/Tooltip/src/Popper/PopperPlacementStrings.cs new file mode 100644 index 0000000..a631f51 --- /dev/null +++ b/Tooltip/src/Popper/PopperPlacementStrings.cs @@ -0,0 +1,62 @@ +using System; + +namespace Skclusive.Material.Tooltip +{ + public static class PopperPlacementStrings + { + public const string Auto = "auto"; + public const string AutoStart = "auto-start"; + public const string AutoEnd = "auto-end"; + public const string Top = "top"; + public const string TopStart = "top-start"; + public const string TopEnd = "top-end"; + public const string Bottom = "bottom"; + public const string BottomStart = "bottom-start"; + public const string BottomEnd = "bottom-end"; + public const string Right = "right"; + public const string RightStart = "right-start"; + public const string RightEnd = "right-end"; + public const string Left = "left"; + public const string LeftStart = "left-start"; + public const string LeftEnd = "left-end"; + + public static string MapToString(this PopperPlacement popperPlacement) + { + switch (popperPlacement) + { + case PopperPlacement.Auto: + return Auto; + case PopperPlacement.AutoStart: + return AutoStart; + case PopperPlacement.AutoEnd: + return AutoEnd; + case PopperPlacement.Top: + return Top; + case PopperPlacement.TopStart: + return TopStart; + case PopperPlacement.TopEnd: + return TopEnd; + case PopperPlacement.Bottom: + return Bottom; + case PopperPlacement.BottomStart: + return BottomStart; + case PopperPlacement.BottomEnd: + return BottomEnd; + case PopperPlacement.Right: + return Right; + case PopperPlacement.RightStart: + return RightStart; + case PopperPlacement.RightEnd: + return RightEnd; + case PopperPlacement.Left: + return Left; + case PopperPlacement.LeftStart: + return LeftStart; + case PopperPlacement.LeftEnd: + return LeftEnd; + default: + throw new ArgumentOutOfRangeException(nameof(popperPlacement), popperPlacement, null); + } + } + } +} diff --git a/Tooltip/src/Popper/PopperState.cs b/Tooltip/src/Popper/PopperState.cs new file mode 100644 index 0000000..902ad5f --- /dev/null +++ b/Tooltip/src/Popper/PopperState.cs @@ -0,0 +1,15 @@ +using System.Collections.Generic; + +namespace Skclusive.Material.Tooltip +{ + public class PopperState + { + public string Placement { get; set; } + public IList OrderedModifiers { get; set; } + public PopperOptions Options { get; set; } + public object ModifiersData { get; set; } + public object Elements { get; set; } + public object Attributes { get; set; } + public object Styles { get; set; } + } +} diff --git a/Tooltip/src/Popper/PopperStrategy.cs b/Tooltip/src/Popper/PopperStrategy.cs new file mode 100644 index 0000000..9c63dfa --- /dev/null +++ b/Tooltip/src/Popper/PopperStrategy.cs @@ -0,0 +1,8 @@ +namespace Skclusive.Material.Tooltip +{ + public enum PopperStrategy + { + Absolute, + Fixed, + } +} diff --git a/Tooltip/src/Popper/PopperStrategyStrings.cs b/Tooltip/src/Popper/PopperStrategyStrings.cs new file mode 100644 index 0000000..60cba39 --- /dev/null +++ b/Tooltip/src/Popper/PopperStrategyStrings.cs @@ -0,0 +1,23 @@ +using System; + +namespace Skclusive.Material.Tooltip +{ + public static class PopperStrategyStrings + { + public const string Absolute = "absolute"; + public const string Fixed = "fixed"; + + public static string MapToString(this PopperStrategy popperStrategy) + { + switch (popperStrategy) + { + case PopperStrategy.Absolute: + return Absolute; + case PopperStrategy.Fixed: + return Fixed; + default: + throw new ArgumentOutOfRangeException(nameof(popperStrategy), popperStrategy, null); + } + } + } +} diff --git a/Tooltip/src/Popper/TooltipHelpersScript.cs b/Tooltip/src/Popper/TooltipHelpersScript.cs new file mode 100644 index 0000000..27af090 --- /dev/null +++ b/Tooltip/src/Popper/TooltipHelpersScript.cs @@ -0,0 +1,17 @@ +using Skclusive.Core.Component; + +namespace Skclusive.Material.Tooltip +{ + public class TooltipHelpersScript : Scripted + { + public TooltipHelpersScript() : base("TooltipHelpersScript") + { + } + + protected override string GetScript() + { + return + @"!function(){""use strict"";function e(e){var t=e.getBoundingClientRect();return{width:t.width,height:t.height,top:t.top,right:t.right,bottom:t.bottom,left:t.left,x:t.left,y:t.top}}function t(e){if(""[object Window]""!==e.toString()){var t=e.ownerDocument;return t?t.defaultView:window}return e}function n(e){var n=t(e);return{scrollLeft:n.pageXOffset,scrollTop:n.pageYOffset}}function r(e){return e instanceof t(e).Element||e instanceof Element}function o(e){return e instanceof t(e).HTMLElement||e instanceof HTMLElement}function i(e){return e?(e.nodeName||"""").toLowerCase():null}function a(e){return(r(e)?e.ownerDocument:e.document).documentElement}function s(t){return e(a(t)).left+n(t).scrollLeft}function f(e){return t(e).getComputedStyle(e)}function c(e){var t=f(e),n=t.overflow,r=t.overflowX,o=t.overflowY;return/auto|scroll|overlay|hidden/.test(n+o+r)}function p(r,f,p){void 0===p&&(p=!1);var u,d,l=a(f),m=e(r),h={scrollLeft:0,scrollTop:0},v={x:0,y:0};return p||((""body""!==i(f)||c(l))&&(h=(u=f)!==t(u)&&o(u)?{scrollLeft:(d=u).scrollLeft,scrollTop:d.scrollTop}:n(u)),o(f)?((v=e(f)).x+=f.clientLeft,v.y+=f.clientTop):l&&(v.x=s(l))),{x:m.left+h.scrollLeft-v.x,y:m.top+h.scrollTop-v.y,width:m.width,height:m.height}}function u(e){return{x:e.offsetLeft,y:e.offsetTop,width:e.offsetWidth,height:e.offsetHeight}}function d(e){return""html""===i(e)?e:e.assignedSlot||e.parentNode||e.host||a(e)}function l(e,n){void 0===n&&(n=[]);var r=function e(t){return[""html"",""body"",""#document""].indexOf(i(t))>=0?t.ownerDocument.body:o(t)&&c(t)?t:e(d(t))}(e),a=""body""===i(r),s=t(r),f=a?[s].concat(s.visualViewport||[],c(r)?r:[]):r,p=n.concat(f);return a?p:p.concat(l(d(f)))}function m(e){return[""table"",""td"",""th""].indexOf(i(e))>=0}function h(e){return o(e)&&""fixed""!==f(e).position?e.offsetParent:null}function v(e){for(var n=t(e),r=h(e);r&&m(r);)r=h(r);return r&&""body""===i(r)&&""static""===f(r).position?n:r||n}var g=""top"",y=""bottom"",b=""right"",w=""left"",x=[g,y,b,w],O=x.reduce((function(e,t){return e.concat([t+""-start"",t+""-end""])}),[]),M=[].concat(x,[""auto""]).reduce((function(e,t){return e.concat([t,t+""-start"",t+""-end""])}),[]),j=[""beforeRead"",""read"",""afterRead"",""beforeMain"",""main"",""afterMain"",""beforeWrite"",""write"",""afterWrite""];function E(e){var t=new Map,n=new Set,r=[];return e.forEach((function(e){t.set(e.name,e)})),e.forEach((function(e){n.has(e.name)||function e(o){n.add(o.name),[].concat(o.requires||[],o.requiresIfExists||[]).forEach((function(r){if(!n.has(r)){var o=t.get(r);o&&e(o)}})),r.push(o)}(e)})),r}function D(e){return e.split(""-"")[0]}var P={placement:""bottom"",modifiers:[],strategy:""absolute""};function k(){for(var e=arguments.length,t=new Array(e),n=0;n=0?""x"":""y""}function H(e){var t,n=e.reference,r=e.element,o=e.placement,i=o?D(o):null,a=o?W(o):null,s=n.x+n.width/2-r.width/2,f=n.y+n.height/2-r.height/2;switch(i){case g:t={x:s,y:n.y-r.height};break;case y:t={x:s,y:n.y+n.height};break;case b:t={x:n.x+n.width,y:f};break;case w:t={x:n.x-r.width,y:f};break;default:t={x:n.x,y:n.y}}var c=i?A(i):null;if(null!=c){var p=""y""===c?""height"":""width"";switch(a){case""start"":t[c]=Math.floor(t[c])-Math.floor(n[p]/2-r[p]/2);break;case""end"":t[c]=Math.floor(t[c])+Math.ceil(n[p]/2-r[p]/2)}}return t}var T={top:""auto"",right:""auto"",bottom:""auto"",left:""auto""};function R(e){var n,r=e.popper,o=e.popperRect,i=e.placement,s=e.offsets,f=e.position,c=e.gpuAcceleration,p=e.adaptive,u=function(e){var t=e.x,n=e.y,r=window.devicePixelRatio||1;return{x:Math.round(t*r)/r||0,y:Math.round(n*r)/r||0}}(s),d=u.x,l=u.y,m=s.hasOwnProperty(""x""),h=s.hasOwnProperty(""y""),x=w,O=g,M=window;if(p){var j=v(r);j===t(r)&&(j=a(r)),i===g&&(O=y,l-=j.clientHeight-o.height,l*=c?1:-1),i===w&&(x=b,d-=j.clientWidth-o.width,d*=c?1:-1)}var E,D=Object.assign({position:f},p&&T);return c?Object.assign({},D,((E={})[O]=h?""0"":"""",E[x]=m?""0"":"""",E.transform=(M.devicePixelRatio||1)<2?""translate(""+d+""px, ""+l+""px)"":""translate3d(""+d+""px, ""+l+""px, 0)"",E)):Object.assign({},D,((n={})[O]=h?l+""px"":"""",n[x]=m?d+""px"":"""",n.transform="""",n))}var S={left:""right"",right:""left"",bottom:""top"",top:""bottom""};function q(e){return e.replace(/left|right|bottom|top/g,(function(e){return S[e]}))}var I={start:""end"",end:""start""};function C(e){return e.replace(/start|end/g,(function(e){return I[e]}))}function N(e){return parseFloat(e)||0}function U(e){var n=t(e),r=function(e){var t=o(e)?f(e):{};return{top:N(t.borderTopWidth),right:N(t.borderRightWidth),bottom:N(t.borderBottomWidth),left:N(t.borderLeftWidth)}}(e),a=""html""===i(e),c=s(e),p=e.clientWidth+r.right,u=e.clientHeight+r.bottom;return a&&n.innerHeight-e.clientHeight>50&&(u=n.innerHeight-r.bottom),{top:a?0:e.clientTop,right:e.clientLeft>r.left?r.right:a?n.innerWidth-p-c:e.offsetWidth-p,bottom:a?n.innerHeight-u:e.offsetHeight-u,left:a?c:e.clientLeft}}function V(e,t){var n=Boolean(t.getRootNode&&t.getRootNode().host);if(e.contains(t))return!0;if(n){var r=t;do{if(r&&e.isSameNode(r))return!0;r=r.parentNode||r.host}while(r)}return!1}function z(e){return Object.assign({},e,{left:e.x,top:e.y,right:e.x+e.width,bottom:e.y+e.height})}function F(r,i){return""viewport""===i?z(function(e){var n=t(e),r=n.visualViewport,o=n.innerWidth,i=n.innerHeight;return r&&/iPhone|iPod|iPad/.test(navigator.platform)&&(o=r.width,i=r.height),{width:o,height:i,x:0,y:0}}(r)):o(i)?e(i):z(function(e){var r=t(e),o=n(e),i=p(a(e),r);return i.height=Math.max(i.height,r.innerHeight),i.width=Math.max(i.width,r.innerWidth),i.x=-o.scrollLeft,i.y=-o.scrollTop,i}(a(r)))}function _(e,t,n){var i=""clippingParents""===t?function(e){var t=l(e),n=[""absolute"",""fixed""].indexOf(f(e).position)>=0&&o(e)?v(e):e;return r(n)?t.filter((function(e){return r(e)&&V(e,n)})):[]}(e):[].concat(t),s=[].concat(i,[n]),c=s[0],p=s.reduce((function(t,n){var r=F(e,n),i=U(o(n)?n:a(e));return t.top=Math.max(r.top+i.top,t.top),t.right=Math.min(r.right-i.right,t.right),t.bottom=Math.min(r.bottom-i.bottom,t.bottom),t.left=Math.max(r.left+i.left,t.left),t}),F(e,c));return p.width=p.right-p.left,p.height=p.bottom-p.top,p.x=p.left,p.y=p.top,p}function X(e){return Object.assign({},{top:0,right:0,bottom:0,left:0},{},e)}function Y(e,t){return t.reduce((function(t,n){return t[n]=e,t}),{})}function G(t,n){void 0===n&&(n={});var o=n,i=o.placement,s=void 0===i?t.placement:i,f=o.boundary,c=void 0===f?""clippingParents"":f,p=o.rootBoundary,u=void 0===p?""viewport"":p,d=o.elementContext,l=void 0===d?""popper"":d,m=o.altBoundary,h=void 0!==m&&m,v=o.padding,w=void 0===v?0:v,O=X(""number""!=typeof w?w:Y(w,x)),M=""popper""===l?""reference"":""popper"",j=t.elements.reference,E=t.rects.popper,D=t.elements[h?M:l],P=_(r(D)?D:D.contextElement||a(t.elements.popper),c,u),k=e(j),L=H({reference:k,element:E,strategy:""absolute"",placement:s}),B=z(Object.assign({},E,{},L)),W=""popper""===l?B:k,A={top:P.top-W.top+O.top,bottom:W.bottom-P.bottom+O.bottom,left:P.left-W.left+O.left,right:W.right-P.right+O.right},T=t.modifiersData.offset;if(""popper""===l&&T){var R=T[s];Object.keys(A).forEach((function(e){var t=[b,y].indexOf(e)>=0?1:-1,n=[g,y].indexOf(e)>=0?""y"":""x"";A[e]+=R[n]*t}))}return A}function J(e,t){void 0===t&&(t={});var n=t,r=n.placement,o=n.boundary,i=n.rootBoundary,a=n.padding,s=n.flipVariations,f=n.allowedAutoPlacements,c=void 0===f?M:f,p=W(r),u=(p?s?O:O.filter((function(e){return W(e)===p})):x).filter((function(e){return c.indexOf(e)>=0})).reduce((function(t,n){return t[n]=G(e,{placement:n,boundary:o,rootBoundary:i,padding:a})[D(n)],t}),{});return Object.keys(u).sort((function(e,t){return u[e]-u[t]}))}function K(e,t,n){return Math.max(e,Math.min(t,n))}function Q(e,t,n){return void 0===n&&(n={x:0,y:0}),{top:e.top-t.height-n.y,right:e.right-t.width+n.x,bottom:e.bottom-t.height+n.y,left:e.left-t.width-n.x}}function Z(e){return[g,b,y,w].some((function(t){return e[t]>=0}))}var $=L({defaultModifiers:[{name:""eventListeners"",enabled:!0,phase:""write"",fn:function(){},effect:function(e){var n=e.state,r=e.instance,o=e.options,i=o.scroll,a=void 0===i||i,s=o.resize,f=void 0===s||s,c=t(n.elements.popper),p=[].concat(n.scrollParents.reference,n.scrollParents.popper);return a&&p.forEach((function(e){e.addEventListener(""scroll"",r.update,B)})),f&&c.addEventListener(""resize"",r.update,B),function(){a&&p.forEach((function(e){e.removeEventListener(""scroll"",r.update,B)})),f&&c.removeEventListener(""resize"",r.update,B)}},data:{}},{name:""popperOffsets"",enabled:!0,phase:""read"",fn:function(e){var t=e.state,n=e.name;t.modifiersData[n]=H({reference:t.rects.reference,element:t.rects.popper,strategy:""absolute"",placement:t.placement})},data:{}},{name:""computeStyles"",enabled:!0,phase:""beforeWrite"",fn:function(e){var t=e.state,n=e.options,r=n.gpuAcceleration,o=void 0===r||r,i=n.adaptive,a=void 0===i||i,s={placement:D(t.placement),popper:t.elements.popper,popperRect:t.rects.popper,gpuAcceleration:o};null!=t.modifiersData.popperOffsets&&(t.styles.popper=Object.assign({},t.styles.popper,{},R(Object.assign({},s,{offsets:t.modifiersData.popperOffsets,position:t.options.strategy,adaptive:a})))),null!=t.modifiersData.arrow&&(t.styles.arrow=Object.assign({},t.styles.arrow,{},R(Object.assign({},s,{offsets:t.modifiersData.arrow,position:""absolute"",adaptive:!1})))),t.attributes.popper=Object.assign({},t.attributes.popper,{""data-popper-placement"":t.placement})},data:{}},{name:""applyStyles"",enabled:!0,phase:""write"",fn:function(e){var t=e.state;Object.keys(t.elements).forEach((function(e){var n=t.styles[e]||{},r=t.attributes[e]||{},a=t.elements[e];o(a)&&i(a)&&(Object.assign(a.style,n),Object.keys(r).forEach((function(e){var t=r[e];!1===t?a.removeAttribute(e):a.setAttribute(e,!0===t?"""":t)})))}))},effect:function(e){var t=e.state,n={popper:{position:t.options.strategy,left:""0"",top:""0"",margin:""0""},arrow:{position:""absolute""},reference:{}};return Object.assign(t.elements.popper.style,n.popper),t.elements.arrow&&Object.assign(t.elements.arrow.style,n.arrow),function(){Object.keys(t.elements).forEach((function(e){var r=t.elements[e],a=t.attributes[e]||{},s=Object.keys(t.styles.hasOwnProperty(e)?t.styles[e]:n[e]).reduce((function(e,t){return e[t]="""",e}),{});o(r)&&i(r)&&(Object.assign(r.style,s),Object.keys(a).forEach((function(e){r.removeAttribute(e)})))}))}},requires:[""computeStyles""]},{name:""offset"",enabled:!0,phase:""main"",requires:[""popperOffsets""],fn:function(e){var t=e.state,n=e.options,r=e.name,o=n.offset,i=void 0===o?[0,0]:o,a=M.reduce((function(e,n){return e[n]=function(e,t,n){var r=D(e),o=[w,g].indexOf(r)>=0?-1:1,i=""function""==typeof n?n(Object.assign({},t,{placement:e})):n,a=i[0],s=i[1];return a=a||0,s=(s||0)*o,[w,b].indexOf(r)>=0?{x:s,y:a}:{x:a,y:s}}(n,t.rects,i),e}),{}),s=a[t.placement],f=s.x,c=s.y;null!=t.modifiersData.popperOffsets&&(t.modifiersData.popperOffsets.x+=f,t.modifiersData.popperOffsets.y+=c),t.modifiersData[r]=a}},{name:""flip"",enabled:!0,phase:""main"",fn:function(e){var t=e.state,n=e.options,r=e.name;if(!t.modifiersData[r]._skip){for(var o=n.mainAxis,i=void 0===o||o,a=n.altAxis,s=void 0===a||a,f=n.fallbackPlacements,c=n.padding,p=n.boundary,u=n.rootBoundary,d=n.altBoundary,l=n.flipVariations,m=void 0===l||l,h=n.allowedAutoPlacements,v=t.options.placement,x=D(v),O=f||(x===v||!m?[q(v)]:function(e){if(""auto""===D(e))return[];var t=q(e);return[C(e),t,C(t)]}(v)),M=[v].concat(O).reduce((function(e,n){return e.concat(""auto""===D(n)?J(t,{placement:n,boundary:p,rootBoundary:u,padding:c,flipVariations:m,allowedAutoPlacements:h}):n)}),[]),j=t.rects.reference,E=t.rects.popper,P=new Map,k=!0,L=M[0],B=0;B=0,S=R?""width"":""height"",I=G(t,{placement:A,boundary:p,rootBoundary:u,altBoundary:d,padding:c}),N=R?T?b:w:T?y:g;j[S]>E[S]&&(N=q(N));var U=q(N),V=[];if(i&&V.push(I[H]<=0),s&&V.push(I[N]<=0,I[U]<=0),V.every((function(e){return e}))){L=A,k=!1;break}P.set(A,V)}if(k)for(var z=function(e){var t=M.find((function(t){var n=P.get(t);if(n)return n.slice(0,e).every((function(e){return e}))}));if(t)return L=t,""break""},F=m?3:1;F>0;F--){if(""break""===z(F))break}t.placement!==L&&(t.modifiersData[r]._skip=!0,t.placement=L,t.reset=!0)}},requiresIfExists:[""offset""],data:{_skip:!1}},{name:""preventOverflow"",enabled:!0,phase:""main"",fn:function(e){var t=e.state,n=e.options,r=e.name,o=n.mainAxis,i=void 0===o||o,a=n.altAxis,s=void 0!==a&&a,f=n.boundary,c=n.rootBoundary,p=n.altBoundary,d=n.padding,l=n.tether,m=void 0===l||l,h=n.tetherOffset,x=void 0===h?0:h,O=G(t,{boundary:f,rootBoundary:c,padding:d,altBoundary:p}),M=D(t.placement),j=W(t.placement),E=!j,P=A(M),k=""x""===P?""y"":""x"",L=t.modifiersData.popperOffsets,B=t.rects.reference,H=t.rects.popper,T=""function""==typeof x?x(Object.assign({},t.rects,{placement:t.placement})):x,R={x:0,y:0};if(L){if(i){var S=""y""===P?g:w,q=""y""===P?y:b,I=""y""===P?""height"":""width"",C=L[P],N=L[P]+O[S],U=L[P]-O[q],V=m?-H[I]/2:0,z=""start""===j?B[I]:H[I],F=""start""===j?-H[I]:-B[I],_=t.elements.arrow,X=m&&_?u(_):{width:0,height:0},Y=t.modifiersData[""arrow#persistent""]?t.modifiersData[""arrow#persistent""].padding:{top:0,right:0,bottom:0,left:0},J=Y[S],Q=Y[q],Z=K(0,B[I],X[I]),$=E?B[I]/2-V-Z-J-T:z-Z-J-T,ee=E?-B[I]/2+V+Z+Q+T:F+Z+Q+T,te=t.elements.arrow&&v(t.elements.arrow),ne=te?""y""===P?te.clientTop||0:te.clientLeft||0:0,re=t.modifiersData.offset?t.modifiersData.offset[t.placement][P]:0,oe=L[P]+$-re-ne,ie=L[P]+ee-re,ae=K(m?Math.min(N,oe):N,C,m?Math.max(U,ie):U);L[P]=ae,R[P]=ae-C}if(s){var se=""x""===P?g:w,fe=""x""===P?y:b,ce=L[k],pe=K(ce+O[se],ce,ce-O[fe]);L[k]=pe,R[k]=pe-ce}t.modifiersData[r]=R}},requiresIfExists:[""offset""]},{name:""arrow"",enabled:!0,phase:""main"",fn:function(e){var t,n=e.state,r=e.name,o=n.elements.arrow,i=n.modifiersData.popperOffsets,a=D(n.placement),s=A(a),f=[w,b].indexOf(a)>=0?""height"":""width"";if(o&&i){var c=n.modifiersData[r+""#persistent""].padding,p=u(o),d=""y""===s?g:w,l=""y""===s?y:b,m=n.rects.reference[f]+n.rects.reference[s]-i[s]-n.rects.popper[f],h=i[s]-n.rects.reference[s],x=v(o),O=x?""y""===s?x.clientHeight||0:x.clientWidth||0:0,M=m/2-h/2,j=c[d],E=O-p[f]-c[l],P=O/2-p[f]/2+M,k=K(j,P,E),L=s;n.modifiersData[r]=((t={})[L]=k,t.centerOffset=k-P,t)}},effect:function(e){var t=e.state,n=e.options,r=e.name,o=n.element,i=void 0===o?""[data-popper-arrow]"":o,a=n.padding,s=void 0===a?0:a;null!=i&&(""string""!=typeof i||(i=t.elements.popper.querySelector(i)))&&V(t.elements.popper,i)&&(t.elements.arrow=i,t.modifiersData[r+""#persistent""]={padding:X(""number""!=typeof s?s:Y(s,x))})},requires:[""popperOffsets""],requiresIfExists:[""preventOverflow""]},{name:""hide"",enabled:!0,phase:""main"",requiresIfExists:[""preventOverflow""],fn:function(e){var t=e.state,n=e.name,r=t.rects.reference,o=t.rects.popper,i=t.modifiersData.preventOverflow,a=G(t,{elementContext:""reference""}),s=G(t,{altBoundary:!0}),f=Q(a,r),c=Q(s,o,i),p=Z(f),u=Z(c);t.modifiersData[n]={referenceClippingOffsets:f,popperEscapeOffsets:c,isReferenceHidden:p,hasPopperEscaped:u},t.attributes.popper=Object.assign({},t.attributes.popper,{""data-popper-reference-hidden"":p,""data-popper-escaped"":u})}}]});window.Skclusive={...window.Skclusive,Material:{...(window.Skclusive||{}).Material,Tooltip:new class{constructor(){this.lastId=0,this.instanceMap=new Map}generateId(){return this.lastId++}destroyPopper(e){let t=this.instanceMap.get(e);t&&(this.instanceMap.delete(e),t.destroy())}updatePopper(e){let t=this.instanceMap.get(e);t&&t.update()}createBlazorPopper(e,t,n){const r=$(e,t,n);let o=this.generateId();return this.instanceMap.set(o,r),{id:o,state:{placement:r.state.placement,orderedModifiers:r.state.orderedModifiers,options:r.state.options,modifiersData:r.state.modifiersData,attributes:r.state.attributes,styles:r.state.styles},setOptions:r.setOptions,forceUpdate:r.forceUpdate,update:r.update,destroy:r.destroy}}}}}}();"; + } + } +} diff --git a/Tooltip/src/Popper/popper-interop.js b/Tooltip/src/Popper/popper-interop.js new file mode 100644 index 0000000..ef52590 --- /dev/null +++ b/Tooltip/src/Popper/popper-interop.js @@ -0,0 +1,64 @@ +import { createPopper } from "../node_modules/@popperjs/core/dist/esm/popper.js"; + +class Tooltip +{ + constructor() { + this.lastId = 0; + this.instanceMap = new Map(); + } + + generateId() { + return this.lastId++; + } + + destroyPopper(id) { + let popper = this.instanceMap.get(id); + if (popper) { + this.instanceMap.delete(id); + popper.destroy(); + } + } + + updatePopper(id) { + let popper = this.instanceMap.get(id); + if (popper) { + popper.update(); + } + } + + createBlazorPopper(reference, popper, options) { + const instance = createPopper(reference, popper, options); + + let id = this.generateId(); + + this.instanceMap.set(id, instance); + + let blazorInstance = { + id: id, + state: { + placement: instance.state.placement, + orderedModifiers: instance.state.orderedModifiers, + options: instance.state.options, + modifiersData: instance.state.modifiersData, + //elements: instance.state.elements, // TypeError: Converting circular structure to JSON + attributes: instance.state.attributes, + styles: instance.state.styles, + //scrollParents: instance.state.scrollParents, // TypeError: Converting circular structure to JSON + }, + setOptions: instance.setOptions, + forceUpdate: instance.forceUpdate, + update: instance.update, + destroy: instance.destroy + }; + + return blazorInstance; + } +} + +window.Skclusive = { + ...window.Skclusive, + Material: { + ...(window.Skclusive || {}).Material, + Tooltip: new Tooltip() + } +}; diff --git a/Tooltip/src/Tooltip.csproj b/Tooltip/src/Tooltip.csproj new file mode 100644 index 0000000..759822d --- /dev/null +++ b/Tooltip/src/Tooltip.csproj @@ -0,0 +1,34 @@ + + + + 2.0.0 + $(VersionSuffix) + netstandard2.1 + 3.0 + Skclusive.Material.Tooltip + Skclusive.Material.Tooltip + Skclusive.Material.Tooltip + Andrej Kmetík + + + blazor material ui tooltip popper + https://github.com/skclusive/Skclusive.Material.Tooltip + https://github.com/skclusive/Skclusive.Material.Tooltip + + + + + + + + + + + + + + + + + + diff --git a/Tooltip/src/Tooltip/Tooltip.razor b/Tooltip/src/Tooltip/Tooltip.razor new file mode 100644 index 0000000..ddddad5 --- /dev/null +++ b/Tooltip/src/Tooltip/Tooltip.razor @@ -0,0 +1,60 @@ +@using Skclusive.Material.Transition +@using Skclusive.Material.Typography +@namespace Skclusive.Material.Tooltip +@inherits MaterialComponent + + + + @ChildContent + + + + + + @if (TitleComponent == null) + { + @Title + } + else + { + @TitleComponent + } + @if (Arrow) + { + + } + + + diff --git a/Tooltip/src/Tooltip/Tooltip.razor.cs b/Tooltip/src/Tooltip/Tooltip.razor.cs new file mode 100644 index 0000000..b3f0b14 --- /dev/null +++ b/Tooltip/src/Tooltip/Tooltip.razor.cs @@ -0,0 +1,240 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Components; +using Microsoft.AspNetCore.Components.Web; +using Skclusive.Core.Component; +using Skclusive.Transition.Component; + +namespace Skclusive.Material.Tooltip +{ + public partial class Tooltip + { + [Parameter] + public bool Arrow { get; set; } = false; + + [Parameter] + public PopperPlacement Placement { get; set; } = PopperPlacement.Bottom; + + [Parameter] + public PopperOptions PopperOptions { get; set; } = null; + + [Parameter] + public bool Open { get; set; } + + [Parameter] + public EventCallback OnOpenChanged { get; set; } + + [Parameter] + public RenderFragment TitleComponent { get; set; } = null; + + [Parameter] + public bool DisableTouchListener { get; set; } = true; + + [Parameter] + public bool DisableHoverListener { get; set; } = false; + + [Parameter] + public bool DisableFocusListener { get; set; } = true; + + [Parameter] + public string Title { get; set; } = ""; + + [Parameter] + public string ContainerTag { get; set; } = null; + + [Parameter] + public string ContainerClass { get; set; } = null; + + [Parameter] + public string ContainerStyle { get; set; } = null; + + [Parameter] + public int? TransitionDuration { set; get; } + + [Parameter] + public int? AppearTimeout { set; get; } + + [Parameter] + public int? EnterTimeout { set; get; } + + [Parameter] + public int? ExitTimeout { set; get; } + + [Parameter] + public bool MountOnEnter { set; get; } + + [Parameter] + public bool UnmountOnExit { set; get; } + + [Parameter] + public Action OnEnter { set; get; } + + [Parameter] + public Action OnEntering { set; get; } + + [Parameter] + public Action OnEntered { set; get; } + + [Parameter] + public Action OnExit { set; get; } + + [Parameter] + public Action OnExiting { set; get; } + + [Parameter] + public Action OnExited { set; get; } + + public ITransitionContext TransitionContext { get; set; } + + private IReference _popperAnchor = new Reference(); + + protected override IEnumerable Classes + { + get + { + foreach (var item in base.Classes) + yield return item; + + yield return "Tooltip"; + + yield return $"Tooltip-Placement-{Placement.MapToString().Split('-')[0]}"; + + if (Arrow) + { + yield return "Tooltip-Arrow"; + } + } + } + + public Tooltip() : base("Tooltip") + { + } + + private string PopperClasses() + { + return $"Tooltip-Popper{(Arrow ? " Tooltip-Popper-Arrow" : "")}{(_Class != null ? $" {_Class}" : "")}"; + } + + private string ArrowClasses() + { + // TODO + if (Placement == PopperPlacement.Bottom || Placement == PopperPlacement.BottomStart || Placement == PopperPlacement.BottomEnd) + { + return "Tooltip-Arrow Tooltip-Popper-Arrow-bottom"; + } + + return $"Tooltip-Arrow"; + } + + protected override Task OnAfterMountAsync() + { + return base.OnAfterMountAsync(); + } + + private async Task HandleOpenChanged(bool open) + { + Open = open; + + if (OnOpenChanged.HasDelegate) + { + await OnOpenChanged.InvokeAsync(Open); + } + + StateHasChanged(); + } + + private async Task HandleTouchStartInternal(TouchEventArgs args) + { + if (DisableTouchListener) + { + return; + } + } + + private async Task HandleTouchEndInternal(TouchEventArgs args) + { + if (DisableTouchListener) + { + return; + } + } + + private async Task HandleMouseEnterInternal(EventArgs args) + { + if (DisableHoverListener) + { + return; + } + + await HandleOpenChanged(true); + } + + private async Task HandleMouseLeaveInternal(EventArgs args) + { + if (DisableHoverListener) + { + return; + } + + await HandleOpenChanged(false); + } + + private async Task HandleFocusInternal(FocusEventArgs args) + { + if (DisableFocusListener) + { + return; + } + } + + private async Task HandleBlurInternal(FocusEventArgs args) + { + if (DisableFocusListener) + { + return; + } + } + + public Action CreateOnEnter(Action onEnter) + { + return (IReference reference, bool appearing) => + { + //_ = SetPositioningStylesAsync(reference.Current); + onEnter?.Invoke(reference, appearing); + OnEnter?.Invoke(reference, appearing); + }; + } + + public Action CreateOnExited(Action onExited) + { + return (IReference reference) => + { + onExited?.Invoke(reference); + OnExited?.Invoke(reference); + }; + } + + protected void HandleEntering(IReference refback, bool appearing) + { + OnEntering?.Invoke(refback, appearing); + + // _ = SetPositioningStylesAsync(refback.Current); + } + + protected void HandleEntered(IReference refback, bool appeared) + { + OnEntered?.Invoke(refback, appeared); + } + + protected void HandleExit(IReference refback) + { + OnExit?.Invoke(refback); + } + + protected void HandleExiting(IReference refback) + { + OnExiting?.Invoke(refback); + } + } +} diff --git a/Tooltip/src/Tooltip/TooltipStyle.razor b/Tooltip/src/Tooltip/TooltipStyle.razor new file mode 100644 index 0000000..b138a48 --- /dev/null +++ b/Tooltip/src/Tooltip/TooltipStyle.razor @@ -0,0 +1,118 @@ +@namespace Skclusive.Material.Tooltip +@inherits StyleComponentBase + + + .Tooltip-Popper { + z-index: var(--theme-zindex-tooltip, 1500); + pointer-events: none; + } + + .Tooltip-PopperInteractive { + pointer-events: auto; + } + + .Tooltip-Tooltip { + background-color: #717171; /*fade(theme.palette.grey[700], 0.9)*/ + border-radius: calc(var(--theme-shape-border-radius, 4) * 1px); + color: var(--theme-palette-common-white, #fff); + font-family: var(--theme-typography-font-family, "Roboto", "Helvetica", "Arial", sans-serif); + padding: 4px 8px; + font-size: 0.625rem; /*theme.typography.pxToRem(10)*/ + line-height: 1em; + max-width: 300px; + word-wrap: break-word; + font-weight: var(--theme-typography-font-weight-medium, 500); + opacity: 0.9; + } + + .Tooltip-Tooltip-Arrow { + position: relative; + margin: 0; + } + + .Tooltip-Arrow { + overflow: hidden; + position: absolute; + width: 1em; + height: 0.71em; /* = width / sqrt(2) = (length of the hypotenuse) */ + box-sizing: border-box; + color: #717171; /*fade(theme.palette.grey[700], 0.9)*/ + } + + .Tooltip-Arrow::before { + content: ""; + margin: auto; + display: block; + width: 100%; + height: 100%; + background: currentColor; + transform: rotate(45deg); + } + + .Tooltip-Popper-Arrow-bottom { + top: 0; + left: 0; + margin-top: -0.71em; + margin-left: 4px; + margin-right: 4px; + } + + .Tooltip-Popper-Arrow-bottom::before { + transform-origin: 0 100%; + } + + .Tooltip-Touch { + padding: 8px 16px; + fontSize: 0.875rem; /*theme.typography.pxToRem(14)*/ + lineHeight: 1em; + fontWeight: var(--theme-typography-font-weight-regular, 500); + } + + .Tooltip-Tooltip-Placement-left { + transform-origin: right center; + margin: 0 14px; + } + + @media (min-width: 600px): { + .Tooltip-Tooltip-Placement-left { + transform-origin: right center; + margin: 0 24px; + } + } + + .Tooltip-Tooltip-Placement-right { + transform-origin: left center; + margin: 0 14px; + } + + @media (min-width: 600px): { + .Tooltip-Tooltip-Placement-right { + transform-origin: left center; + margin: 0 24px; + } + } + + .Tooltip-Tooltip-Placement-top { + transform-origin: center bottom; + margin: 0 14px; + } + + @media (min-width: 600px): { + .Tooltip-Tooltip-Placement-top { + transform-origin: center bottom; + margin: 0 24px; + } + } + + .Tooltip-Tooltip-Placement-bottom { + transform-origin: center top; + margin: 0 14px; + } + + @media (min-width: 600px): { + .Tooltip-Tooltip-Placement-bottom { + transform-origin: center top; + margin: 0 24px; + } + } + diff --git a/Tooltip/src/_Imports.razor b/Tooltip/src/_Imports.razor new file mode 100644 index 0000000..af37308 --- /dev/null +++ b/Tooltip/src/_Imports.razor @@ -0,0 +1,4 @@ +@using Microsoft.AspNetCore.Components.Web +@using Skclusive.Core.Component +@using Skclusive.Material.Core +@using Skclusive.Transition.Component \ No newline at end of file diff --git a/Tooltip/src/package-lock.json b/Tooltip/src/package-lock.json new file mode 100644 index 0000000..0d25f3a --- /dev/null +++ b/Tooltip/src/package-lock.json @@ -0,0 +1,279 @@ +{ + "name": "material-component-tooltip", + "version": "1.0.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@babel/code-frame": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.8.3.tgz", + "integrity": "sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0jhss4cPP93EW7s+uC5bikET2twEF3KV+7rDblJcmNvTR7VJejqd2C2g==", + "dev": true, + "requires": { + "@babel/highlight": "^7.8.3" + } + }, + "@babel/helper-validator-identifier": { + "version": "7.9.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.9.5.tgz", + "integrity": "sha512-/8arLKUFq882w4tWGj9JYzRpAlZgiWUJ+dtteNTDqrRBz9Iguck9Rn3ykuBDoUwh2TO4tSAJlrxDUOXWklJe4g==", + "dev": true + }, + "@babel/highlight": { + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.9.0.tgz", + "integrity": "sha512-lJZPilxX7Op3Nv/2cvFdnlepPXDxi29wxteT57Q965oc5R9v86ztx0jfxVrTcBk8C2kcPkkDa2Z4T3ZsPPVWsQ==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.9.0", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + } + }, + "@popperjs/core": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.4.0.tgz", + "integrity": "sha512-NMrDy6EWh9TPdSRiHmHH2ye1v5U0gBD7pRYwSwJvomx7Bm4GG04vu63dYiVzebLOx2obPpJugew06xVP0Nk7hA==" + }, + "@types/estree": { + "version": "0.0.44", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.44.tgz", + "integrity": "sha512-iaIVzr+w2ZJ5HkidlZ3EJM8VTZb2MJLCjw3V+505yVts0gRC4UMvjw0d1HPtGqI/HQC/KdsYtayfzl+AXY2R8g==", + "dev": true + }, + "@types/node": { + "version": "14.0.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.0.5.tgz", + "integrity": "sha512-90hiq6/VqtQgX8Sp0EzeIsv3r+ellbGj4URKj5j30tLlZvRUpnAe9YbYnjl3pJM93GyXU0tghHhvXHq+5rnCKA==", + "dev": true + }, + "@types/resolve": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-0.0.8.tgz", + "integrity": "sha512-auApPaJf3NPfe18hSoJkp8EbZzer2ISk7o8mCC3M9he/a04+gbMF97NkpD2S8riMGvm4BMRI59/SZQSaLTKpsQ==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "acorn": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.2.0.tgz", + "integrity": "sha512-apwXVmYVpQ34m/i71vrApRrRKCWQnZZF1+npOD0WV5xZFfwWOmKGQ2RWlfdy9vWITsenisM8M0Qeq8agcFHNiQ==", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", + "dev": true + }, + "builtin-modules": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.1.0.tgz", + "integrity": "sha512-k0KL0aWZuBt2lrxrcASWDfwOLMnodeQjodT/1SxEQAXsHANgo6ZC/VEaSEHCXt7aSTZ4/4H5LKa+tBXmW7Vtvw==", + "dev": true + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "estree-walker": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.6.1.tgz", + "integrity": "sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==", + "dev": true + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "is-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz", + "integrity": "sha1-Mlj7afeMFNW4FdZkM2tM/7ZEFZE=", + "dev": true + }, + "jest-worker": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-24.9.0.tgz", + "integrity": "sha512-51PE4haMSXcHohnSMdM42anbvZANYTqMrr52tVKPqqsPJMzoP6FYYDVqahX/HrAoKEKz3uUPzSvKs9A3qR4iVw==", + "dev": true, + "requires": { + "merge-stream": "^2.0.0", + "supports-color": "^6.1.0" + }, + "dependencies": { + "supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, + "path-parse": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", + "dev": true + }, + "resolve": { + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", + "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==", + "dev": true, + "requires": { + "path-parse": "^1.0.6" + } + }, + "rollup": { + "version": "1.32.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-1.32.1.tgz", + "integrity": "sha512-/2HA0Ec70TvQnXdzynFffkjA6XN+1e2pEv/uKS5Ulca40g2L7KuOE3riasHoNVHOsFD5KKZgDsMk1CP3Tw9s+A==", + "dev": true, + "requires": { + "@types/estree": "*", + "@types/node": "*", + "acorn": "^7.1.0" + } + }, + "rollup-plugin-node-resolve": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/rollup-plugin-node-resolve/-/rollup-plugin-node-resolve-5.2.0.tgz", + "integrity": "sha512-jUlyaDXts7TW2CqQ4GaO5VJ4PwwaV8VUGA7+km3n6k6xtOEacf61u0VXwN80phY/evMcaS+9eIeJ9MOyDxt5Zw==", + "dev": true, + "requires": { + "@types/resolve": "0.0.8", + "builtin-modules": "^3.1.0", + "is-module": "^1.0.0", + "resolve": "^1.11.1", + "rollup-pluginutils": "^2.8.1" + } + }, + "rollup-plugin-terser": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/rollup-plugin-terser/-/rollup-plugin-terser-5.1.3.tgz", + "integrity": "sha512-FuFuXE5QUJ7snyxHLPp/0LFXJhdomKlIx/aK7Tg88Yubsx/UU/lmInoJafXJ4jwVVNcORJ1wRUC5T9cy5yk0wA==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "jest-worker": "^24.6.0", + "rollup-pluginutils": "^2.8.1", + "serialize-javascript": "^2.1.2", + "terser": "^4.1.0" + } + }, + "rollup-pluginutils": { + "version": "2.8.2", + "resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.8.2.tgz", + "integrity": "sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==", + "dev": true, + "requires": { + "estree-walker": "^0.6.1" + } + }, + "serialize-javascript": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-2.1.2.tgz", + "integrity": "sha512-rs9OggEUF0V4jUSecXazOYsLfu7OGK2qIn3c7IPBiffz32XniEp/TX9Xmc9LQfK2nQ2QKHvZ2oygKUGU0lG4jQ==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "source-map-support": { + "version": "0.5.19", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", + "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "terser": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-4.7.0.tgz", + "integrity": "sha512-Lfb0RiZcjRDXCC3OSHJpEkxJ9Qeqs6mp2v4jf2MHfy8vGERmVDuvjXdd/EnP5Deme5F2yBRBymKmKHCBg2echw==", + "dev": true, + "requires": { + "commander": "^2.20.0", + "source-map": "~0.6.1", + "source-map-support": "~0.5.12" + } + } + } +} diff --git a/Tooltip/src/package.json b/Tooltip/src/package.json new file mode 100644 index 0000000..d97521c --- /dev/null +++ b/Tooltip/src/package.json @@ -0,0 +1,20 @@ +{ + "name": "material-component-tooltip", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1", + "build": "rollup -c rollup.config.js" + }, + "author": "", + "license": "ISC", + "dependencies": { + "@popperjs/core": "^2.4.0" + }, + "devDependencies": { + "rollup": "^1.26.3", + "rollup-plugin-node-resolve": "^5.2.0", + "rollup-plugin-terser": "5.1.3" + } +} diff --git a/Tooltip/src/rollup.config.js b/Tooltip/src/rollup.config.js new file mode 100644 index 0000000..7fa7302 --- /dev/null +++ b/Tooltip/src/rollup.config.js @@ -0,0 +1,12 @@ +import resolve from "rollup-plugin-node-resolve"; +import { terser } from "rollup-plugin-terser"; + +process.env.INCLUDE_DEPS === "true"; +module.exports = { + input: "Popper/popper-interop.js", + output: { + file: "artifacts/popper-interop.js", + format: "iife" + }, + plugins: [resolve(), terser()] +};