@lattice-ui/tooltip 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/out/Tooltip/TooltipContent.d.ts +3 -0
- package/out/Tooltip/TooltipContent.luau +111 -0
- package/out/Tooltip/TooltipPortal.d.ts +3 -0
- package/out/Tooltip/TooltipPortal.luau +33 -0
- package/out/Tooltip/TooltipProvider.d.ts +3 -0
- package/out/Tooltip/TooltipProvider.luau +50 -0
- package/out/Tooltip/TooltipRoot.d.ts +3 -0
- package/out/Tooltip/TooltipRoot.luau +78 -0
- package/out/Tooltip/TooltipTrigger.d.ts +3 -0
- package/out/Tooltip/TooltipTrigger.luau +61 -0
- package/out/Tooltip/context.d.ts +6 -0
- package/out/Tooltip/context.luau +32 -0
- package/out/Tooltip/types.d.ts +51 -0
- package/out/Tooltip/types.luau +2 -0
- package/out/index.d.ts +6 -0
- package/out/init.luau +9 -0
- package/package.json +25 -0
- package/src/Tooltip/TooltipContent.tsx +144 -0
- package/src/Tooltip/TooltipPortal.tsx +28 -0
- package/src/Tooltip/TooltipProvider.tsx +43 -0
- package/src/Tooltip/TooltipRoot.tsx +76 -0
- package/src/Tooltip/TooltipTrigger.tsx +75 -0
- package/src/Tooltip/context.ts +21 -0
- package/src/Tooltip/types.ts +59 -0
- package/src/index.ts +12 -0
- package/tsconfig.json +16 -0
- package/tsconfig.typecheck.json +25 -0
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
-- Compiled with roblox-ts v3.0.0
|
|
2
|
+
local TS = _G[script]
|
|
3
|
+
local _core = TS.import(script, TS.getModule(script, "@lattice-ui", "core").out)
|
|
4
|
+
local React = _core.React
|
|
5
|
+
local Slot = _core.Slot
|
|
6
|
+
local _layer = TS.import(script, TS.getModule(script, "@lattice-ui", "layer").out)
|
|
7
|
+
local DismissableLayer = _layer.DismissableLayer
|
|
8
|
+
local Presence = _layer.Presence
|
|
9
|
+
local usePopper = TS.import(script, TS.getModule(script, "@lattice-ui", "popper").out).usePopper
|
|
10
|
+
local useTooltipContext = TS.import(script, script.Parent, "context").useTooltipContext
|
|
11
|
+
local function toGuiObject(instance)
|
|
12
|
+
if not instance or not instance:IsA("GuiObject") then
|
|
13
|
+
return nil
|
|
14
|
+
end
|
|
15
|
+
return instance
|
|
16
|
+
end
|
|
17
|
+
local function TooltipContentImpl(props)
|
|
18
|
+
local tooltipContext = useTooltipContext()
|
|
19
|
+
local popper = usePopper({
|
|
20
|
+
anchorRef = tooltipContext.triggerRef,
|
|
21
|
+
contentRef = tooltipContext.contentRef,
|
|
22
|
+
placement = props.placement,
|
|
23
|
+
offset = props.offset,
|
|
24
|
+
padding = props.padding,
|
|
25
|
+
enabled = props.enabled,
|
|
26
|
+
})
|
|
27
|
+
local setContentRef = React.useCallback(function(instance)
|
|
28
|
+
tooltipContext.contentRef.current = toGuiObject(instance)
|
|
29
|
+
end, { tooltipContext.contentRef })
|
|
30
|
+
if props.asChild then
|
|
31
|
+
local child = props.children
|
|
32
|
+
if not React.isValidElement(child) then
|
|
33
|
+
error("[TooltipContent] `asChild` requires a child element.")
|
|
34
|
+
end
|
|
35
|
+
return React.createElement(DismissableLayer, {
|
|
36
|
+
enabled = props.enabled,
|
|
37
|
+
modal = false,
|
|
38
|
+
onDismiss = props.onDismiss,
|
|
39
|
+
onEscapeKeyDown = props.onEscapeKeyDown,
|
|
40
|
+
onInteractOutside = props.onInteractOutside,
|
|
41
|
+
onPointerDownOutside = props.onPointerDownOutside,
|
|
42
|
+
}, React.createElement(Slot, {
|
|
43
|
+
AnchorPoint = popper.anchorPoint,
|
|
44
|
+
Position = popper.position,
|
|
45
|
+
Visible = props.visible,
|
|
46
|
+
ref = setContentRef,
|
|
47
|
+
}, child))
|
|
48
|
+
end
|
|
49
|
+
return React.createElement(DismissableLayer, {
|
|
50
|
+
enabled = props.enabled,
|
|
51
|
+
modal = false,
|
|
52
|
+
onDismiss = props.onDismiss,
|
|
53
|
+
onEscapeKeyDown = props.onEscapeKeyDown,
|
|
54
|
+
onInteractOutside = props.onInteractOutside,
|
|
55
|
+
onPointerDownOutside = props.onPointerDownOutside,
|
|
56
|
+
}, React.createElement("frame", {
|
|
57
|
+
AnchorPoint = popper.anchorPoint,
|
|
58
|
+
BackgroundTransparency = 1,
|
|
59
|
+
BorderSizePixel = 0,
|
|
60
|
+
Position = popper.position,
|
|
61
|
+
Size = UDim2.fromOffset(0, 0),
|
|
62
|
+
Visible = props.visible,
|
|
63
|
+
ref = setContentRef,
|
|
64
|
+
}, props.children))
|
|
65
|
+
end
|
|
66
|
+
local function TooltipContent(props)
|
|
67
|
+
local tooltipContext = useTooltipContext()
|
|
68
|
+
local open = tooltipContext.open
|
|
69
|
+
local forceMount = props.forceMount == true
|
|
70
|
+
local handleDismiss = React.useCallback(function()
|
|
71
|
+
tooltipContext.close()
|
|
72
|
+
end, { tooltipContext })
|
|
73
|
+
if not open and not forceMount then
|
|
74
|
+
return nil
|
|
75
|
+
end
|
|
76
|
+
if forceMount then
|
|
77
|
+
return React.createElement(TooltipContentImpl, {
|
|
78
|
+
asChild = props.asChild,
|
|
79
|
+
enabled = open,
|
|
80
|
+
offset = props.offset,
|
|
81
|
+
onDismiss = handleDismiss,
|
|
82
|
+
onEscapeKeyDown = props.onEscapeKeyDown,
|
|
83
|
+
onInteractOutside = props.onInteractOutside,
|
|
84
|
+
onPointerDownOutside = props.onPointerDownOutside,
|
|
85
|
+
padding = props.padding,
|
|
86
|
+
placement = props.placement,
|
|
87
|
+
visible = open,
|
|
88
|
+
}, props.children)
|
|
89
|
+
end
|
|
90
|
+
return React.createElement(Presence, {
|
|
91
|
+
exitFallbackMs = 0,
|
|
92
|
+
present = open,
|
|
93
|
+
render = function(state)
|
|
94
|
+
return React.createElement(TooltipContentImpl, {
|
|
95
|
+
asChild = props.asChild,
|
|
96
|
+
enabled = state.isPresent,
|
|
97
|
+
offset = props.offset,
|
|
98
|
+
onDismiss = handleDismiss,
|
|
99
|
+
onEscapeKeyDown = props.onEscapeKeyDown,
|
|
100
|
+
onInteractOutside = props.onInteractOutside,
|
|
101
|
+
onPointerDownOutside = props.onPointerDownOutside,
|
|
102
|
+
padding = props.padding,
|
|
103
|
+
placement = props.placement,
|
|
104
|
+
visible = state.isPresent,
|
|
105
|
+
}, props.children)
|
|
106
|
+
end,
|
|
107
|
+
})
|
|
108
|
+
end
|
|
109
|
+
return {
|
|
110
|
+
TooltipContent = TooltipContent,
|
|
111
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
-- Compiled with roblox-ts v3.0.0
|
|
2
|
+
local TS = _G[script]
|
|
3
|
+
local React = TS.import(script, TS.getModule(script, "@lattice-ui", "core").out).React
|
|
4
|
+
local _layer = TS.import(script, TS.getModule(script, "@lattice-ui", "layer").out)
|
|
5
|
+
local Portal = _layer.Portal
|
|
6
|
+
local PortalProvider = _layer.PortalProvider
|
|
7
|
+
local usePortalContext = _layer.usePortalContext
|
|
8
|
+
local function TooltipPortalWithOverrides(props)
|
|
9
|
+
local portalContext = usePortalContext()
|
|
10
|
+
local container = props.container or portalContext.container
|
|
11
|
+
local _condition = props.displayOrderBase
|
|
12
|
+
if _condition == nil then
|
|
13
|
+
_condition = portalContext.displayOrderBase
|
|
14
|
+
end
|
|
15
|
+
local displayOrderBase = _condition
|
|
16
|
+
return React.createElement(PortalProvider, {
|
|
17
|
+
container = container,
|
|
18
|
+
displayOrderBase = displayOrderBase,
|
|
19
|
+
}, React.createElement(Portal, nil, props.children))
|
|
20
|
+
end
|
|
21
|
+
local function TooltipPortal(props)
|
|
22
|
+
local hasOverrides = props.container ~= nil or props.displayOrderBase ~= nil
|
|
23
|
+
if hasOverrides then
|
|
24
|
+
return React.createElement(TooltipPortalWithOverrides, {
|
|
25
|
+
container = props.container,
|
|
26
|
+
displayOrderBase = props.displayOrderBase,
|
|
27
|
+
}, props.children)
|
|
28
|
+
end
|
|
29
|
+
return React.createElement(Portal, nil, props.children)
|
|
30
|
+
end
|
|
31
|
+
return {
|
|
32
|
+
TooltipPortal = TooltipPortal,
|
|
33
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
-- Compiled with roblox-ts v3.0.0
|
|
2
|
+
local TS = _G[script]
|
|
3
|
+
local React = TS.import(script, TS.getModule(script, "@lattice-ui", "core").out).React
|
|
4
|
+
local TooltipProviderContext = TS.import(script, script.Parent, "context").TooltipProviderContext
|
|
5
|
+
local function TooltipProvider(props)
|
|
6
|
+
local _condition = props.delayDuration
|
|
7
|
+
if _condition == nil then
|
|
8
|
+
_condition = 700
|
|
9
|
+
end
|
|
10
|
+
local delayDuration = _condition
|
|
11
|
+
local _condition_1 = props.skipDelayDuration
|
|
12
|
+
if _condition_1 == nil then
|
|
13
|
+
_condition_1 = 300
|
|
14
|
+
end
|
|
15
|
+
local skipDelayDuration = _condition_1
|
|
16
|
+
local lastOpenTimestampRef = React.useRef()
|
|
17
|
+
local markOpen = React.useCallback(function()
|
|
18
|
+
lastOpenTimestampRef.current = os.clock()
|
|
19
|
+
end, {})
|
|
20
|
+
local resolveOpenDelay = React.useCallback(function(requestedDelay)
|
|
21
|
+
local _condition_2 = requestedDelay
|
|
22
|
+
if _condition_2 == nil then
|
|
23
|
+
_condition_2 = delayDuration
|
|
24
|
+
end
|
|
25
|
+
local baseDelay = _condition_2
|
|
26
|
+
local lastOpenTimestamp = lastOpenTimestampRef.current
|
|
27
|
+
if lastOpenTimestamp == nil then
|
|
28
|
+
return baseDelay
|
|
29
|
+
end
|
|
30
|
+
local elapsedMs = (os.clock() - lastOpenTimestamp) * 1000
|
|
31
|
+
if elapsedMs <= skipDelayDuration then
|
|
32
|
+
return math.min(baseDelay, skipDelayDuration)
|
|
33
|
+
end
|
|
34
|
+
return baseDelay
|
|
35
|
+
end, { delayDuration, skipDelayDuration })
|
|
36
|
+
local contextValue = React.useMemo(function()
|
|
37
|
+
return {
|
|
38
|
+
delayDuration = delayDuration,
|
|
39
|
+
skipDelayDuration = skipDelayDuration,
|
|
40
|
+
resolveOpenDelay = resolveOpenDelay,
|
|
41
|
+
markOpen = markOpen,
|
|
42
|
+
}
|
|
43
|
+
end, { delayDuration, markOpen, resolveOpenDelay, skipDelayDuration })
|
|
44
|
+
return React.createElement(TooltipProviderContext.Provider, {
|
|
45
|
+
value = contextValue,
|
|
46
|
+
}, props.children)
|
|
47
|
+
end
|
|
48
|
+
return {
|
|
49
|
+
TooltipProvider = TooltipProvider,
|
|
50
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
-- Compiled with roblox-ts v3.0.0
|
|
2
|
+
local TS = _G[script]
|
|
3
|
+
local _core = TS.import(script, TS.getModule(script, "@lattice-ui", "core").out)
|
|
4
|
+
local React = _core.React
|
|
5
|
+
local useControllableState = _core.useControllableState
|
|
6
|
+
local _context = TS.import(script, script.Parent, "context")
|
|
7
|
+
local TooltipContextProvider = _context.TooltipContextProvider
|
|
8
|
+
local useTooltipProviderContext = _context.useTooltipProviderContext
|
|
9
|
+
local function Tooltip(props)
|
|
10
|
+
local providerContext = useTooltipProviderContext()
|
|
11
|
+
local _object = {
|
|
12
|
+
value = props.open,
|
|
13
|
+
}
|
|
14
|
+
local _left = "defaultValue"
|
|
15
|
+
local _condition = props.defaultOpen
|
|
16
|
+
if _condition == nil then
|
|
17
|
+
_condition = false
|
|
18
|
+
end
|
|
19
|
+
_object[_left] = _condition
|
|
20
|
+
_object.onChange = props.onOpenChange
|
|
21
|
+
local _binding = useControllableState(_object)
|
|
22
|
+
local open = _binding[1]
|
|
23
|
+
local setOpenState = _binding[2]
|
|
24
|
+
local triggerRef = React.useRef()
|
|
25
|
+
local contentRef = React.useRef()
|
|
26
|
+
local openDelayTaskRef = React.useRef()
|
|
27
|
+
local cancelPendingOpen = React.useCallback(function()
|
|
28
|
+
local openDelayTask = openDelayTaskRef.current
|
|
29
|
+
if not openDelayTask then
|
|
30
|
+
return nil
|
|
31
|
+
end
|
|
32
|
+
task.cancel(openDelayTask)
|
|
33
|
+
openDelayTaskRef.current = nil
|
|
34
|
+
end, {})
|
|
35
|
+
local setOpen = React.useCallback(function(nextOpen)
|
|
36
|
+
setOpenState(nextOpen)
|
|
37
|
+
if nextOpen then
|
|
38
|
+
providerContext.markOpen()
|
|
39
|
+
end
|
|
40
|
+
end, { providerContext, setOpenState })
|
|
41
|
+
local openWithDelay = React.useCallback(function()
|
|
42
|
+
cancelPendingOpen()
|
|
43
|
+
local resolvedDelay = providerContext.resolveOpenDelay(props.delayDuration)
|
|
44
|
+
if resolvedDelay <= 0 then
|
|
45
|
+
setOpen(true)
|
|
46
|
+
return nil
|
|
47
|
+
end
|
|
48
|
+
openDelayTaskRef.current = task.delay(resolvedDelay / 1000, function()
|
|
49
|
+
openDelayTaskRef.current = nil
|
|
50
|
+
setOpen(true)
|
|
51
|
+
end)
|
|
52
|
+
end, { cancelPendingOpen, props.delayDuration, providerContext, setOpen })
|
|
53
|
+
local close = React.useCallback(function()
|
|
54
|
+
cancelPendingOpen()
|
|
55
|
+
setOpen(false)
|
|
56
|
+
end, { cancelPendingOpen, setOpen })
|
|
57
|
+
React.useEffect(function()
|
|
58
|
+
return function()
|
|
59
|
+
cancelPendingOpen()
|
|
60
|
+
end
|
|
61
|
+
end, { cancelPendingOpen })
|
|
62
|
+
local contextValue = React.useMemo(function()
|
|
63
|
+
return {
|
|
64
|
+
open = open,
|
|
65
|
+
setOpen = setOpen,
|
|
66
|
+
openWithDelay = openWithDelay,
|
|
67
|
+
close = close,
|
|
68
|
+
triggerRef = triggerRef,
|
|
69
|
+
contentRef = contentRef,
|
|
70
|
+
}
|
|
71
|
+
end, { close, open, openWithDelay, setOpen })
|
|
72
|
+
return React.createElement(TooltipContextProvider, {
|
|
73
|
+
value = contextValue,
|
|
74
|
+
}, props.children)
|
|
75
|
+
end
|
|
76
|
+
return {
|
|
77
|
+
Tooltip = Tooltip,
|
|
78
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
-- Compiled with roblox-ts v3.0.0
|
|
2
|
+
local TS = _G[script]
|
|
3
|
+
local _core = TS.import(script, TS.getModule(script, "@lattice-ui", "core").out)
|
|
4
|
+
local React = _core.React
|
|
5
|
+
local Slot = _core.Slot
|
|
6
|
+
local useTooltipContext = TS.import(script, script.Parent, "context").useTooltipContext
|
|
7
|
+
local function toGuiObject(instance)
|
|
8
|
+
if not instance or not instance:IsA("GuiObject") then
|
|
9
|
+
return nil
|
|
10
|
+
end
|
|
11
|
+
return instance
|
|
12
|
+
end
|
|
13
|
+
local function TooltipTrigger(props)
|
|
14
|
+
local tooltipContext = useTooltipContext()
|
|
15
|
+
local setTriggerRef = React.useCallback(function(instance)
|
|
16
|
+
tooltipContext.triggerRef.current = toGuiObject(instance)
|
|
17
|
+
end, { tooltipContext.triggerRef })
|
|
18
|
+
local handleOpen = React.useCallback(function()
|
|
19
|
+
if props.disabled then
|
|
20
|
+
return nil
|
|
21
|
+
end
|
|
22
|
+
tooltipContext.openWithDelay()
|
|
23
|
+
end, { props.disabled, tooltipContext })
|
|
24
|
+
local handleClose = React.useCallback(function()
|
|
25
|
+
tooltipContext.close()
|
|
26
|
+
end, { tooltipContext })
|
|
27
|
+
local eventHandlers = React.useMemo(function()
|
|
28
|
+
return {
|
|
29
|
+
MouseEnter = handleOpen,
|
|
30
|
+
MouseLeave = handleClose,
|
|
31
|
+
SelectionGained = handleOpen,
|
|
32
|
+
SelectionLost = handleClose,
|
|
33
|
+
}
|
|
34
|
+
end, { handleClose, handleOpen })
|
|
35
|
+
if props.asChild then
|
|
36
|
+
local child = props.children
|
|
37
|
+
if not child then
|
|
38
|
+
error("[TooltipTrigger] `asChild` requires a child element.")
|
|
39
|
+
end
|
|
40
|
+
return React.createElement(Slot, {
|
|
41
|
+
Event = eventHandlers,
|
|
42
|
+
ref = setTriggerRef,
|
|
43
|
+
}, child)
|
|
44
|
+
end
|
|
45
|
+
return React.createElement("textbutton", {
|
|
46
|
+
Active = props.disabled ~= true,
|
|
47
|
+
AutoButtonColor = false,
|
|
48
|
+
BackgroundTransparency = 1,
|
|
49
|
+
BorderSizePixel = 0,
|
|
50
|
+
Event = eventHandlers,
|
|
51
|
+
Selectable = props.disabled ~= true,
|
|
52
|
+
Size = UDim2.fromOffset(140, 36),
|
|
53
|
+
Text = "Tooltip Trigger",
|
|
54
|
+
TextColor3 = Color3.fromRGB(240, 244, 250),
|
|
55
|
+
TextSize = 15,
|
|
56
|
+
ref = setTriggerRef,
|
|
57
|
+
}, props.children)
|
|
58
|
+
end
|
|
59
|
+
return {
|
|
60
|
+
TooltipTrigger = TooltipTrigger,
|
|
61
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { React } from "@lattice-ui/core";
|
|
2
|
+
import type { TooltipContextValue, TooltipProviderContextValue } from "./types";
|
|
3
|
+
declare const TooltipContextProvider: React.Provider<TooltipContextValue | undefined>, useTooltipContext: () => TooltipContextValue;
|
|
4
|
+
declare const TooltipProviderContext: React.Context<TooltipProviderContextValue>;
|
|
5
|
+
declare function useTooltipProviderContext(): TooltipProviderContextValue;
|
|
6
|
+
export { TooltipContextProvider, TooltipProviderContext, useTooltipContext, useTooltipProviderContext };
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
-- Compiled with roblox-ts v3.0.0
|
|
2
|
+
local TS = _G[script]
|
|
3
|
+
local _core = TS.import(script, TS.getModule(script, "@lattice-ui", "core").out)
|
|
4
|
+
local createStrictContext = _core.createStrictContext
|
|
5
|
+
local React = _core.React
|
|
6
|
+
local _binding = createStrictContext("Tooltip")
|
|
7
|
+
local TooltipContextProvider = _binding[1]
|
|
8
|
+
local useTooltipContext = _binding[2]
|
|
9
|
+
local DEFAULT_TOOLTIP_PROVIDER_CONTEXT = {
|
|
10
|
+
delayDuration = 700,
|
|
11
|
+
skipDelayDuration = 300,
|
|
12
|
+
resolveOpenDelay = function(requestedDelay)
|
|
13
|
+
local _condition = requestedDelay
|
|
14
|
+
if _condition == nil then
|
|
15
|
+
_condition = 700
|
|
16
|
+
end
|
|
17
|
+
return _condition
|
|
18
|
+
end,
|
|
19
|
+
markOpen = function()
|
|
20
|
+
-- default no-op
|
|
21
|
+
end,
|
|
22
|
+
}
|
|
23
|
+
local TooltipProviderContext = React.createContext(DEFAULT_TOOLTIP_PROVIDER_CONTEXT)
|
|
24
|
+
local function useTooltipProviderContext()
|
|
25
|
+
return React.useContext(TooltipProviderContext)
|
|
26
|
+
end
|
|
27
|
+
return {
|
|
28
|
+
TooltipContextProvider = TooltipContextProvider,
|
|
29
|
+
TooltipProviderContext = TooltipProviderContext,
|
|
30
|
+
useTooltipContext = useTooltipContext,
|
|
31
|
+
useTooltipProviderContext = useTooltipProviderContext,
|
|
32
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import type { LayerInteractEvent } from "@lattice-ui/layer";
|
|
2
|
+
import type { PopperPlacement } from "@lattice-ui/popper";
|
|
3
|
+
import type React from "@rbxts/react";
|
|
4
|
+
export type TooltipSetOpen = (open: boolean) => void;
|
|
5
|
+
export type TooltipContextValue = {
|
|
6
|
+
open: boolean;
|
|
7
|
+
setOpen: TooltipSetOpen;
|
|
8
|
+
openWithDelay: () => void;
|
|
9
|
+
close: () => void;
|
|
10
|
+
triggerRef: React.MutableRefObject<GuiObject | undefined>;
|
|
11
|
+
contentRef: React.MutableRefObject<GuiObject | undefined>;
|
|
12
|
+
};
|
|
13
|
+
export type TooltipProviderContextValue = {
|
|
14
|
+
delayDuration: number;
|
|
15
|
+
skipDelayDuration: number;
|
|
16
|
+
resolveOpenDelay: (requestedDelay?: number) => number;
|
|
17
|
+
markOpen: () => void;
|
|
18
|
+
};
|
|
19
|
+
export type TooltipProviderProps = {
|
|
20
|
+
delayDuration?: number;
|
|
21
|
+
skipDelayDuration?: number;
|
|
22
|
+
children?: React.ReactNode;
|
|
23
|
+
};
|
|
24
|
+
export type TooltipProps = {
|
|
25
|
+
open?: boolean;
|
|
26
|
+
defaultOpen?: boolean;
|
|
27
|
+
delayDuration?: number;
|
|
28
|
+
onOpenChange?: (open: boolean) => void;
|
|
29
|
+
children?: React.ReactNode;
|
|
30
|
+
};
|
|
31
|
+
export type TooltipTriggerProps = {
|
|
32
|
+
asChild?: boolean;
|
|
33
|
+
disabled?: boolean;
|
|
34
|
+
children?: React.ReactElement;
|
|
35
|
+
};
|
|
36
|
+
export type TooltipPortalProps = {
|
|
37
|
+
container?: BasePlayerGui;
|
|
38
|
+
displayOrderBase?: number;
|
|
39
|
+
children?: React.ReactNode;
|
|
40
|
+
};
|
|
41
|
+
export type TooltipContentProps = {
|
|
42
|
+
asChild?: boolean;
|
|
43
|
+
forceMount?: boolean;
|
|
44
|
+
placement?: PopperPlacement;
|
|
45
|
+
offset?: Vector2;
|
|
46
|
+
padding?: number;
|
|
47
|
+
onEscapeKeyDown?: (event: LayerInteractEvent) => void;
|
|
48
|
+
onPointerDownOutside?: (event: LayerInteractEvent) => void;
|
|
49
|
+
onInteractOutside?: (event: LayerInteractEvent) => void;
|
|
50
|
+
children?: React.ReactNode;
|
|
51
|
+
};
|
package/out/index.d.ts
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { TooltipContent } from "./Tooltip/TooltipContent";
|
|
2
|
+
export { TooltipPortal } from "./Tooltip/TooltipPortal";
|
|
3
|
+
export { TooltipProvider } from "./Tooltip/TooltipProvider";
|
|
4
|
+
export { Tooltip } from "./Tooltip/TooltipRoot";
|
|
5
|
+
export { TooltipTrigger } from "./Tooltip/TooltipTrigger";
|
|
6
|
+
export type { TooltipContentProps, TooltipPortalProps, TooltipProps, TooltipProviderProps, TooltipTriggerProps, } from "./Tooltip/types";
|
package/out/init.luau
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
-- Compiled with roblox-ts v3.0.0
|
|
2
|
+
local TS = _G[script]
|
|
3
|
+
local exports = {}
|
|
4
|
+
exports.TooltipContent = TS.import(script, script, "Tooltip", "TooltipContent").TooltipContent
|
|
5
|
+
exports.TooltipPortal = TS.import(script, script, "Tooltip", "TooltipPortal").TooltipPortal
|
|
6
|
+
exports.TooltipProvider = TS.import(script, script, "Tooltip", "TooltipProvider").TooltipProvider
|
|
7
|
+
exports.Tooltip = TS.import(script, script, "Tooltip", "TooltipRoot").Tooltip
|
|
8
|
+
exports.TooltipTrigger = TS.import(script, script, "Tooltip", "TooltipTrigger").TooltipTrigger
|
|
9
|
+
return exports
|
package/package.json
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@lattice-ui/tooltip",
|
|
3
|
+
"version": "0.1.1",
|
|
4
|
+
"private": false,
|
|
5
|
+
"main": "out/init.luau",
|
|
6
|
+
"types": "out/index.d.ts",
|
|
7
|
+
"dependencies": {
|
|
8
|
+
"@lattice-ui/core": "0.1.1",
|
|
9
|
+
"@lattice-ui/layer": "0.1.1",
|
|
10
|
+
"@lattice-ui/popper": "0.1.1"
|
|
11
|
+
},
|
|
12
|
+
"devDependencies": {
|
|
13
|
+
"@rbxts/react": "17.3.7-ts.1",
|
|
14
|
+
"@rbxts/react-roblox": "17.3.7-ts.1"
|
|
15
|
+
},
|
|
16
|
+
"peerDependencies": {
|
|
17
|
+
"@rbxts/react": "^17",
|
|
18
|
+
"@rbxts/react-roblox": "^17"
|
|
19
|
+
},
|
|
20
|
+
"scripts": {
|
|
21
|
+
"build": "rbxtsc -p tsconfig.json",
|
|
22
|
+
"watch": "rbxtsc -p tsconfig.json -w",
|
|
23
|
+
"typecheck": "tsc -p tsconfig.typecheck.json"
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import { React, Slot } from "@lattice-ui/core";
|
|
2
|
+
import { DismissableLayer, Presence } from "@lattice-ui/layer";
|
|
3
|
+
import { usePopper } from "@lattice-ui/popper";
|
|
4
|
+
import { useTooltipContext } from "./context";
|
|
5
|
+
import type { TooltipContentProps } from "./types";
|
|
6
|
+
|
|
7
|
+
type TooltipContentImplProps = {
|
|
8
|
+
enabled: boolean;
|
|
9
|
+
visible: boolean;
|
|
10
|
+
onDismiss: () => void;
|
|
11
|
+
asChild?: boolean;
|
|
12
|
+
placement?: TooltipContentProps["placement"];
|
|
13
|
+
offset?: TooltipContentProps["offset"];
|
|
14
|
+
padding?: TooltipContentProps["padding"];
|
|
15
|
+
} & Pick<TooltipContentProps, "children" | "onEscapeKeyDown" | "onInteractOutside" | "onPointerDownOutside">;
|
|
16
|
+
|
|
17
|
+
function toGuiObject(instance: Instance | undefined) {
|
|
18
|
+
if (!instance || !instance.IsA("GuiObject")) {
|
|
19
|
+
return undefined;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
return instance;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function TooltipContentImpl(props: TooltipContentImplProps) {
|
|
26
|
+
const tooltipContext = useTooltipContext();
|
|
27
|
+
|
|
28
|
+
const popper = usePopper({
|
|
29
|
+
anchorRef: tooltipContext.triggerRef,
|
|
30
|
+
contentRef: tooltipContext.contentRef,
|
|
31
|
+
placement: props.placement,
|
|
32
|
+
offset: props.offset,
|
|
33
|
+
padding: props.padding,
|
|
34
|
+
enabled: props.enabled,
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
const setContentRef = React.useCallback(
|
|
38
|
+
(instance: Instance | undefined) => {
|
|
39
|
+
tooltipContext.contentRef.current = toGuiObject(instance);
|
|
40
|
+
},
|
|
41
|
+
[tooltipContext.contentRef],
|
|
42
|
+
);
|
|
43
|
+
|
|
44
|
+
if (props.asChild) {
|
|
45
|
+
const child = props.children;
|
|
46
|
+
if (!React.isValidElement(child)) {
|
|
47
|
+
error("[TooltipContent] `asChild` requires a child element.");
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return (
|
|
51
|
+
<DismissableLayer
|
|
52
|
+
enabled={props.enabled}
|
|
53
|
+
modal={false}
|
|
54
|
+
onDismiss={props.onDismiss}
|
|
55
|
+
onEscapeKeyDown={props.onEscapeKeyDown}
|
|
56
|
+
onInteractOutside={props.onInteractOutside}
|
|
57
|
+
onPointerDownOutside={props.onPointerDownOutside}
|
|
58
|
+
>
|
|
59
|
+
<Slot AnchorPoint={popper.anchorPoint} Position={popper.position} Visible={props.visible} ref={setContentRef}>
|
|
60
|
+
{child}
|
|
61
|
+
</Slot>
|
|
62
|
+
</DismissableLayer>
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
return (
|
|
67
|
+
<DismissableLayer
|
|
68
|
+
enabled={props.enabled}
|
|
69
|
+
modal={false}
|
|
70
|
+
onDismiss={props.onDismiss}
|
|
71
|
+
onEscapeKeyDown={props.onEscapeKeyDown}
|
|
72
|
+
onInteractOutside={props.onInteractOutside}
|
|
73
|
+
onPointerDownOutside={props.onPointerDownOutside}
|
|
74
|
+
>
|
|
75
|
+
<frame
|
|
76
|
+
AnchorPoint={popper.anchorPoint}
|
|
77
|
+
BackgroundTransparency={1}
|
|
78
|
+
BorderSizePixel={0}
|
|
79
|
+
Position={popper.position}
|
|
80
|
+
Size={UDim2.fromOffset(0, 0)}
|
|
81
|
+
Visible={props.visible}
|
|
82
|
+
ref={setContentRef}
|
|
83
|
+
>
|
|
84
|
+
{props.children}
|
|
85
|
+
</frame>
|
|
86
|
+
</DismissableLayer>
|
|
87
|
+
);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export function TooltipContent(props: TooltipContentProps) {
|
|
91
|
+
const tooltipContext = useTooltipContext();
|
|
92
|
+
const open = tooltipContext.open;
|
|
93
|
+
const forceMount = props.forceMount === true;
|
|
94
|
+
|
|
95
|
+
const handleDismiss = React.useCallback(() => {
|
|
96
|
+
tooltipContext.close();
|
|
97
|
+
}, [tooltipContext]);
|
|
98
|
+
|
|
99
|
+
if (!open && !forceMount) {
|
|
100
|
+
return undefined;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
if (forceMount) {
|
|
104
|
+
return (
|
|
105
|
+
<TooltipContentImpl
|
|
106
|
+
asChild={props.asChild}
|
|
107
|
+
enabled={open}
|
|
108
|
+
offset={props.offset}
|
|
109
|
+
onDismiss={handleDismiss}
|
|
110
|
+
onEscapeKeyDown={props.onEscapeKeyDown}
|
|
111
|
+
onInteractOutside={props.onInteractOutside}
|
|
112
|
+
onPointerDownOutside={props.onPointerDownOutside}
|
|
113
|
+
padding={props.padding}
|
|
114
|
+
placement={props.placement}
|
|
115
|
+
visible={open}
|
|
116
|
+
>
|
|
117
|
+
{props.children}
|
|
118
|
+
</TooltipContentImpl>
|
|
119
|
+
);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
return (
|
|
123
|
+
<Presence
|
|
124
|
+
exitFallbackMs={0}
|
|
125
|
+
present={open}
|
|
126
|
+
render={(state) => (
|
|
127
|
+
<TooltipContentImpl
|
|
128
|
+
asChild={props.asChild}
|
|
129
|
+
enabled={state.isPresent}
|
|
130
|
+
offset={props.offset}
|
|
131
|
+
onDismiss={handleDismiss}
|
|
132
|
+
onEscapeKeyDown={props.onEscapeKeyDown}
|
|
133
|
+
onInteractOutside={props.onInteractOutside}
|
|
134
|
+
onPointerDownOutside={props.onPointerDownOutside}
|
|
135
|
+
padding={props.padding}
|
|
136
|
+
placement={props.placement}
|
|
137
|
+
visible={state.isPresent}
|
|
138
|
+
>
|
|
139
|
+
{props.children}
|
|
140
|
+
</TooltipContentImpl>
|
|
141
|
+
)}
|
|
142
|
+
/>
|
|
143
|
+
);
|
|
144
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { React } from "@lattice-ui/core";
|
|
2
|
+
import { Portal, PortalProvider, usePortalContext } from "@lattice-ui/layer";
|
|
3
|
+
import type { TooltipPortalProps } from "./types";
|
|
4
|
+
|
|
5
|
+
function TooltipPortalWithOverrides(props: TooltipPortalProps) {
|
|
6
|
+
const portalContext = usePortalContext();
|
|
7
|
+
const container = props.container ?? portalContext.container;
|
|
8
|
+
const displayOrderBase = props.displayOrderBase ?? portalContext.displayOrderBase;
|
|
9
|
+
|
|
10
|
+
return (
|
|
11
|
+
<PortalProvider container={container} displayOrderBase={displayOrderBase}>
|
|
12
|
+
<Portal>{props.children}</Portal>
|
|
13
|
+
</PortalProvider>
|
|
14
|
+
);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function TooltipPortal(props: TooltipPortalProps) {
|
|
18
|
+
const hasOverrides = props.container !== undefined || props.displayOrderBase !== undefined;
|
|
19
|
+
if (hasOverrides) {
|
|
20
|
+
return (
|
|
21
|
+
<TooltipPortalWithOverrides container={props.container} displayOrderBase={props.displayOrderBase}>
|
|
22
|
+
{props.children}
|
|
23
|
+
</TooltipPortalWithOverrides>
|
|
24
|
+
);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
return <Portal>{props.children}</Portal>;
|
|
28
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { React } from "@lattice-ui/core";
|
|
2
|
+
import { TooltipProviderContext } from "./context";
|
|
3
|
+
import type { TooltipProviderContextValue, TooltipProviderProps } from "./types";
|
|
4
|
+
|
|
5
|
+
export function TooltipProvider(props: TooltipProviderProps) {
|
|
6
|
+
const delayDuration = props.delayDuration ?? 700;
|
|
7
|
+
const skipDelayDuration = props.skipDelayDuration ?? 300;
|
|
8
|
+
const lastOpenTimestampRef = React.useRef<number>();
|
|
9
|
+
|
|
10
|
+
const markOpen = React.useCallback(() => {
|
|
11
|
+
lastOpenTimestampRef.current = os.clock();
|
|
12
|
+
}, []);
|
|
13
|
+
|
|
14
|
+
const resolveOpenDelay = React.useCallback(
|
|
15
|
+
(requestedDelay?: number) => {
|
|
16
|
+
const baseDelay = requestedDelay ?? delayDuration;
|
|
17
|
+
const lastOpenTimestamp = lastOpenTimestampRef.current;
|
|
18
|
+
if (lastOpenTimestamp === undefined) {
|
|
19
|
+
return baseDelay;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const elapsedMs = (os.clock() - lastOpenTimestamp) * 1000;
|
|
23
|
+
if (elapsedMs <= skipDelayDuration) {
|
|
24
|
+
return math.min(baseDelay, skipDelayDuration);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
return baseDelay;
|
|
28
|
+
},
|
|
29
|
+
[delayDuration, skipDelayDuration],
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
const contextValue = React.useMemo<TooltipProviderContextValue>(
|
|
33
|
+
() => ({
|
|
34
|
+
delayDuration,
|
|
35
|
+
skipDelayDuration,
|
|
36
|
+
resolveOpenDelay,
|
|
37
|
+
markOpen,
|
|
38
|
+
}),
|
|
39
|
+
[delayDuration, markOpen, resolveOpenDelay, skipDelayDuration],
|
|
40
|
+
);
|
|
41
|
+
|
|
42
|
+
return <TooltipProviderContext.Provider value={contextValue}>{props.children}</TooltipProviderContext.Provider>;
|
|
43
|
+
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { React, useControllableState } from "@lattice-ui/core";
|
|
2
|
+
import { TooltipContextProvider, useTooltipProviderContext } from "./context";
|
|
3
|
+
import type { TooltipProps } from "./types";
|
|
4
|
+
|
|
5
|
+
export function Tooltip(props: TooltipProps) {
|
|
6
|
+
const providerContext = useTooltipProviderContext();
|
|
7
|
+
const [open, setOpenState] = useControllableState<boolean>({
|
|
8
|
+
value: props.open,
|
|
9
|
+
defaultValue: props.defaultOpen ?? false,
|
|
10
|
+
onChange: props.onOpenChange,
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
const triggerRef = React.useRef<GuiObject>();
|
|
14
|
+
const contentRef = React.useRef<GuiObject>();
|
|
15
|
+
const openDelayTaskRef = React.useRef<thread>();
|
|
16
|
+
|
|
17
|
+
const cancelPendingOpen = React.useCallback(() => {
|
|
18
|
+
const openDelayTask = openDelayTaskRef.current;
|
|
19
|
+
if (!openDelayTask) {
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
task.cancel(openDelayTask);
|
|
24
|
+
openDelayTaskRef.current = undefined;
|
|
25
|
+
}, []);
|
|
26
|
+
|
|
27
|
+
const setOpen = React.useCallback(
|
|
28
|
+
(nextOpen: boolean) => {
|
|
29
|
+
setOpenState(nextOpen);
|
|
30
|
+
if (nextOpen) {
|
|
31
|
+
providerContext.markOpen();
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
[providerContext, setOpenState],
|
|
35
|
+
);
|
|
36
|
+
|
|
37
|
+
const openWithDelay = React.useCallback(() => {
|
|
38
|
+
cancelPendingOpen();
|
|
39
|
+
|
|
40
|
+
const resolvedDelay = providerContext.resolveOpenDelay(props.delayDuration);
|
|
41
|
+
if (resolvedDelay <= 0) {
|
|
42
|
+
setOpen(true);
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
openDelayTaskRef.current = task.delay(resolvedDelay / 1000, () => {
|
|
47
|
+
openDelayTaskRef.current = undefined;
|
|
48
|
+
setOpen(true);
|
|
49
|
+
});
|
|
50
|
+
}, [cancelPendingOpen, props.delayDuration, providerContext, setOpen]);
|
|
51
|
+
|
|
52
|
+
const close = React.useCallback(() => {
|
|
53
|
+
cancelPendingOpen();
|
|
54
|
+
setOpen(false);
|
|
55
|
+
}, [cancelPendingOpen, setOpen]);
|
|
56
|
+
|
|
57
|
+
React.useEffect(() => {
|
|
58
|
+
return () => {
|
|
59
|
+
cancelPendingOpen();
|
|
60
|
+
};
|
|
61
|
+
}, [cancelPendingOpen]);
|
|
62
|
+
|
|
63
|
+
const contextValue = React.useMemo(
|
|
64
|
+
() => ({
|
|
65
|
+
open,
|
|
66
|
+
setOpen,
|
|
67
|
+
openWithDelay,
|
|
68
|
+
close,
|
|
69
|
+
triggerRef,
|
|
70
|
+
contentRef,
|
|
71
|
+
}),
|
|
72
|
+
[close, open, openWithDelay, setOpen],
|
|
73
|
+
);
|
|
74
|
+
|
|
75
|
+
return <TooltipContextProvider value={contextValue}>{props.children}</TooltipContextProvider>;
|
|
76
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { React, Slot } from "@lattice-ui/core";
|
|
2
|
+
import { useTooltipContext } from "./context";
|
|
3
|
+
import type { TooltipTriggerProps } from "./types";
|
|
4
|
+
|
|
5
|
+
function toGuiObject(instance: Instance | undefined) {
|
|
6
|
+
if (!instance || !instance.IsA("GuiObject")) {
|
|
7
|
+
return undefined;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
return instance;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function TooltipTrigger(props: TooltipTriggerProps) {
|
|
14
|
+
const tooltipContext = useTooltipContext();
|
|
15
|
+
|
|
16
|
+
const setTriggerRef = React.useCallback(
|
|
17
|
+
(instance: Instance | undefined) => {
|
|
18
|
+
tooltipContext.triggerRef.current = toGuiObject(instance);
|
|
19
|
+
},
|
|
20
|
+
[tooltipContext.triggerRef],
|
|
21
|
+
);
|
|
22
|
+
|
|
23
|
+
const handleOpen = React.useCallback(() => {
|
|
24
|
+
if (props.disabled) {
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
tooltipContext.openWithDelay();
|
|
29
|
+
}, [props.disabled, tooltipContext]);
|
|
30
|
+
|
|
31
|
+
const handleClose = React.useCallback(() => {
|
|
32
|
+
tooltipContext.close();
|
|
33
|
+
}, [tooltipContext]);
|
|
34
|
+
|
|
35
|
+
const eventHandlers = React.useMemo(
|
|
36
|
+
() => ({
|
|
37
|
+
MouseEnter: handleOpen,
|
|
38
|
+
MouseLeave: handleClose,
|
|
39
|
+
SelectionGained: handleOpen,
|
|
40
|
+
SelectionLost: handleClose,
|
|
41
|
+
}),
|
|
42
|
+
[handleClose, handleOpen],
|
|
43
|
+
);
|
|
44
|
+
|
|
45
|
+
if (props.asChild) {
|
|
46
|
+
const child = props.children;
|
|
47
|
+
if (!child) {
|
|
48
|
+
error("[TooltipTrigger] `asChild` requires a child element.");
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return (
|
|
52
|
+
<Slot Event={eventHandlers} ref={setTriggerRef}>
|
|
53
|
+
{child}
|
|
54
|
+
</Slot>
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
return (
|
|
59
|
+
<textbutton
|
|
60
|
+
Active={props.disabled !== true}
|
|
61
|
+
AutoButtonColor={false}
|
|
62
|
+
BackgroundTransparency={1}
|
|
63
|
+
BorderSizePixel={0}
|
|
64
|
+
Event={eventHandlers}
|
|
65
|
+
Selectable={props.disabled !== true}
|
|
66
|
+
Size={UDim2.fromOffset(140, 36)}
|
|
67
|
+
Text="Tooltip Trigger"
|
|
68
|
+
TextColor3={Color3.fromRGB(240, 244, 250)}
|
|
69
|
+
TextSize={15}
|
|
70
|
+
ref={setTriggerRef}
|
|
71
|
+
>
|
|
72
|
+
{props.children}
|
|
73
|
+
</textbutton>
|
|
74
|
+
);
|
|
75
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { createStrictContext, React } from "@lattice-ui/core";
|
|
2
|
+
import type { TooltipContextValue, TooltipProviderContextValue } from "./types";
|
|
3
|
+
|
|
4
|
+
const [TooltipContextProvider, useTooltipContext] = createStrictContext<TooltipContextValue>("Tooltip");
|
|
5
|
+
|
|
6
|
+
const DEFAULT_TOOLTIP_PROVIDER_CONTEXT: TooltipProviderContextValue = {
|
|
7
|
+
delayDuration: 700,
|
|
8
|
+
skipDelayDuration: 300,
|
|
9
|
+
resolveOpenDelay: (requestedDelay) => requestedDelay ?? 700,
|
|
10
|
+
markOpen: () => {
|
|
11
|
+
// default no-op
|
|
12
|
+
},
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
const TooltipProviderContext = React.createContext<TooltipProviderContextValue>(DEFAULT_TOOLTIP_PROVIDER_CONTEXT);
|
|
16
|
+
|
|
17
|
+
function useTooltipProviderContext() {
|
|
18
|
+
return React.useContext(TooltipProviderContext);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export { TooltipContextProvider, TooltipProviderContext, useTooltipContext, useTooltipProviderContext };
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import type { LayerInteractEvent } from "@lattice-ui/layer";
|
|
2
|
+
import type { PopperPlacement } from "@lattice-ui/popper";
|
|
3
|
+
import type React from "@rbxts/react";
|
|
4
|
+
|
|
5
|
+
export type TooltipSetOpen = (open: boolean) => void;
|
|
6
|
+
|
|
7
|
+
export type TooltipContextValue = {
|
|
8
|
+
open: boolean;
|
|
9
|
+
setOpen: TooltipSetOpen;
|
|
10
|
+
openWithDelay: () => void;
|
|
11
|
+
close: () => void;
|
|
12
|
+
triggerRef: React.MutableRefObject<GuiObject | undefined>;
|
|
13
|
+
contentRef: React.MutableRefObject<GuiObject | undefined>;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export type TooltipProviderContextValue = {
|
|
17
|
+
delayDuration: number;
|
|
18
|
+
skipDelayDuration: number;
|
|
19
|
+
resolveOpenDelay: (requestedDelay?: number) => number;
|
|
20
|
+
markOpen: () => void;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export type TooltipProviderProps = {
|
|
24
|
+
delayDuration?: number;
|
|
25
|
+
skipDelayDuration?: number;
|
|
26
|
+
children?: React.ReactNode;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
export type TooltipProps = {
|
|
30
|
+
open?: boolean;
|
|
31
|
+
defaultOpen?: boolean;
|
|
32
|
+
delayDuration?: number;
|
|
33
|
+
onOpenChange?: (open: boolean) => void;
|
|
34
|
+
children?: React.ReactNode;
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
export type TooltipTriggerProps = {
|
|
38
|
+
asChild?: boolean;
|
|
39
|
+
disabled?: boolean;
|
|
40
|
+
children?: React.ReactElement;
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
export type TooltipPortalProps = {
|
|
44
|
+
container?: BasePlayerGui;
|
|
45
|
+
displayOrderBase?: number;
|
|
46
|
+
children?: React.ReactNode;
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
export type TooltipContentProps = {
|
|
50
|
+
asChild?: boolean;
|
|
51
|
+
forceMount?: boolean;
|
|
52
|
+
placement?: PopperPlacement;
|
|
53
|
+
offset?: Vector2;
|
|
54
|
+
padding?: number;
|
|
55
|
+
onEscapeKeyDown?: (event: LayerInteractEvent) => void;
|
|
56
|
+
onPointerDownOutside?: (event: LayerInteractEvent) => void;
|
|
57
|
+
onInteractOutside?: (event: LayerInteractEvent) => void;
|
|
58
|
+
children?: React.ReactNode;
|
|
59
|
+
};
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export { TooltipContent } from "./Tooltip/TooltipContent";
|
|
2
|
+
export { TooltipPortal } from "./Tooltip/TooltipPortal";
|
|
3
|
+
export { TooltipProvider } from "./Tooltip/TooltipProvider";
|
|
4
|
+
export { Tooltip } from "./Tooltip/TooltipRoot";
|
|
5
|
+
export { TooltipTrigger } from "./Tooltip/TooltipTrigger";
|
|
6
|
+
export type {
|
|
7
|
+
TooltipContentProps,
|
|
8
|
+
TooltipPortalProps,
|
|
9
|
+
TooltipProps,
|
|
10
|
+
TooltipProviderProps,
|
|
11
|
+
TooltipTriggerProps,
|
|
12
|
+
} from "./Tooltip/types";
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"extends": "../../tsconfig.base.json",
|
|
3
|
+
"compilerOptions": {
|
|
4
|
+
"rootDir": "src",
|
|
5
|
+
"outDir": "out",
|
|
6
|
+
"declaration": true,
|
|
7
|
+
"typeRoots": [
|
|
8
|
+
"./node_modules/@rbxts",
|
|
9
|
+
"../../node_modules/@rbxts",
|
|
10
|
+
"./node_modules/@lattice-ui",
|
|
11
|
+
"../../node_modules/@lattice-ui"
|
|
12
|
+
],
|
|
13
|
+
"types": ["types", "compiler-types"]
|
|
14
|
+
},
|
|
15
|
+
"include": ["src"]
|
|
16
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"extends": "./tsconfig.json",
|
|
3
|
+
"compilerOptions": {
|
|
4
|
+
"noEmit": true,
|
|
5
|
+
"baseUrl": "..",
|
|
6
|
+
"rootDir": "..",
|
|
7
|
+
"paths": {
|
|
8
|
+
"@lattice-ui/checkbox": ["checkbox/src/index.ts"],
|
|
9
|
+
"@lattice-ui/core": ["core/src/index.ts"],
|
|
10
|
+
"@lattice-ui/dialog": ["dialog/src/index.ts"],
|
|
11
|
+
"@lattice-ui/focus": ["focus/src/index.ts"],
|
|
12
|
+
"@lattice-ui/layer": ["layer/src/index.ts"],
|
|
13
|
+
"@lattice-ui/menu": ["menu/src/index.ts"],
|
|
14
|
+
"@lattice-ui/popover": ["popover/src/index.ts"],
|
|
15
|
+
"@lattice-ui/popper": ["popper/src/index.ts"],
|
|
16
|
+
"@lattice-ui/radio-group": ["radio-group/src/index.ts"],
|
|
17
|
+
"@lattice-ui/style": ["style/src/index.ts"],
|
|
18
|
+
"@lattice-ui/switch": ["switch/src/index.ts"],
|
|
19
|
+
"@lattice-ui/system": ["system/src/index.ts"],
|
|
20
|
+
"@lattice-ui/tabs": ["tabs/src/index.ts"],
|
|
21
|
+
"@lattice-ui/toggle-group": ["toggle-group/src/index.ts"],
|
|
22
|
+
"@lattice-ui/tooltip": ["tooltip/src/index.ts"]
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|