wuira 0.2.2 → 0.2.3

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/CHANGELOG.md CHANGED
@@ -7,6 +7,16 @@ with the release date and highlight breaking changes explicitly.
7
7
 
8
8
  ## Unreleased
9
9
 
10
+ ## 0.2.3 — 2026-10-15
11
+
12
+ ### Added
13
+
14
+ - Tooltip attachment in Cell decorations, inherited by all visual components.
15
+ Route hover to native GameTooltip or another native tooltip with custom text,
16
+ extra lines or a callback using native spell, item, unit, hyperlink and action APIs.
17
+ - Motion-only hover input preserves click-through behavior and existing scripts;
18
+ owned tooltips close on leave, hide and disposal without changing secure actions.
19
+
10
20
  ## 0.2.2 — 2026-10-15
11
21
 
12
22
  ### Added
package/README.md CHANGED
@@ -610,6 +610,30 @@ not install event listeners or poll automatically. The current adapter requires
610
610
  in-game verification. Unit tokens refer to snapshot time and are not persistent
611
611
  caster identities. No Paladin-specific spell catalog or filtering is built in.
612
612
 
613
+ ### Native tooltips
614
+
615
+ `Tooltip` attaches to any Cell through decorations. It forwards hover to the
616
+ game's native tooltip API and creates no visual regions or update loop.
617
+
618
+ ```tsx
619
+ import { Cell, Tooltip } from "wuira/ui";
620
+
621
+ <Cell width={40} height={40} decorations={{
622
+ tooltip: new Tooltip({ text: "My tooltip", lines: [{ text: "Extra details" }] }),
623
+ }} />;
624
+
625
+ <Cell width={40} height={40} decorations={{
626
+ tooltip: new Tooltip({ show: tooltip => tooltip.SetSpellByID(635) }),
627
+ }} />;
628
+ ```
629
+
630
+ The same attachment works on SecureButton. Call SetItemByID, SetUnit, SetHyperlink
631
+ or SetAction inside `show` for other native content. `text` may be a function
632
+ evaluated on hover; `show` may return false to suppress display. Optional `target`
633
+ selects another native tooltip, and `anchor` defaults to ANCHOR_RIGHT.
634
+ Hover preserves click-through and existing scripts. Leave, hide and unmount close
635
+ only a tooltip still owned by that Cell. Use one decoration instance per Cell.
636
+
613
637
  ### Visual styling
614
638
 
615
639
  <!-- Screenshot: a dark Cell with a thin colored border. -->
@@ -50,6 +50,8 @@ interface wuiraNativeFrame {
50
50
  SetFrameLevel(level: number): void;
51
51
  CreateFontString(name: undefined, layer: "OVERLAY"): wuiraNativeFontString;
52
52
  EnableMouse(enabled: boolean): void;
53
+ EnableMouseMotion(enabled: boolean): void;
54
+ IsMouseMotionEnabled(): boolean;
53
55
  RegisterEvent(event: string): void;
54
56
  UnregisterAllEvents(): void;
55
57
  SetScript(script: "OnEvent", handler: ((this: void, frame: wuiraNativeFrame, event: string, unit?: string) => void) | undefined): void;
@@ -38,5 +38,6 @@ function ____exports.renderDecorations(self, item, tree)
38
38
  end
39
39
  ____attach_16(nil, ____temp_15)
40
40
  attach(nil, decorations and decorations.glow)
41
+ attach(nil, decorations and decorations.tooltip)
41
42
  end
42
43
  return ____exports
@@ -1,8 +1,10 @@
1
1
  import type { Background } from "./Background";
2
2
  import type { Border } from "./Border";
3
3
  import type { Glow } from "./Glow";
4
+ import type { Tooltip } from "./Tooltip";
4
5
  export interface Decorations {
5
6
  background?: Background;
6
7
  border?: Border;
7
8
  glow?: Glow;
9
+ tooltip?: Tooltip;
8
10
  }
@@ -0,0 +1,50 @@
1
+ import type { Color } from "../../types/Color";
2
+ import { Decoration } from "./Decoration";
3
+ export type TooltipAnchor = "ANCHOR_RIGHT" | "ANCHOR_LEFT" | "ANCHOR_TOP" | "ANCHOR_BOTTOM" | "ANCHOR_CURSOR" | "ANCHOR_NONE";
4
+ /** Native GameTooltip surface passed to callbacks; no custom tooltip renderer. */
5
+ export interface NativeTooltip {
6
+ SetOwner(owner: wuiraNativeFrame, anchor: TooltipAnchor): void;
7
+ IsOwned(owner: wuiraNativeFrame): boolean;
8
+ ClearLines(): void;
9
+ SetText(text: string, r?: number, g?: number, b?: number, alpha?: number, wrap?: boolean): void;
10
+ AddLine(text: string, r?: number, g?: number, b?: number, wrap?: boolean): void;
11
+ SetSpellByID(id: number): void;
12
+ SetItemByID(id: number): void;
13
+ SetUnit(unit: string): void;
14
+ SetHyperlink(link: string): void;
15
+ SetAction(slot: number): void;
16
+ Show(): void;
17
+ Hide(): void;
18
+ }
19
+ export interface TooltipLine {
20
+ text: string;
21
+ color?: Color;
22
+ wrap?: boolean;
23
+ }
24
+ interface TooltipOptions {
25
+ anchor?: TooltipAnchor;
26
+ /** Defaults to the game's shared GameTooltip; resolved on hover. */
27
+ target?: NativeTooltip | (() => NativeTooltip | undefined);
28
+ lines?: readonly TooltipLine[];
29
+ }
30
+ export type TooltipProps = TooltipOptions & ({
31
+ text: string | (() => string | undefined);
32
+ color?: Color;
33
+ wrap?: boolean;
34
+ show?: never;
35
+ } | {
36
+ show: (tooltip: NativeTooltip, owner: wuiraNativeFrame) => void | false;
37
+ text?: never;
38
+ });
39
+ /** Attaches hover routing to a Cell. Creates no frames, textures or update loop. */
40
+ export declare class Tooltip extends Decoration {
41
+ readonly props: TooltipProps;
42
+ private binding?;
43
+ private shown?;
44
+ constructor(props: TooltipProps);
45
+ protected draw(frame: wuiraNativeFrame): void;
46
+ private Show;
47
+ private Hide;
48
+ dispose(): void;
49
+ }
50
+ export {};
@@ -0,0 +1,218 @@
1
+ --[[ Generated with https://github.com/TypeScriptToLua/TypeScriptToLua ]]
2
+ -- Lua Library inline imports
3
+ local function __TS__Class(self)
4
+ local c = {prototype = {}}
5
+ c.prototype.__index = c.prototype
6
+ c.prototype.constructor = c
7
+ return c
8
+ end
9
+
10
+ local function __TS__ClassExtends(target, base)
11
+ target.____super = base
12
+ local staticMetatable = setmetatable({__index = base}, base)
13
+ setmetatable(target, staticMetatable)
14
+ local baseMetatable = getmetatable(base)
15
+ if baseMetatable then
16
+ if type(baseMetatable.__index) == "function" then
17
+ staticMetatable.__index = baseMetatable.__index
18
+ end
19
+ if type(baseMetatable.__newindex) == "function" then
20
+ staticMetatable.__newindex = baseMetatable.__newindex
21
+ end
22
+ end
23
+ setmetatable(target.prototype, base.prototype)
24
+ if type(base.prototype.__index) == "function" then
25
+ target.prototype.__index = base.prototype.__index
26
+ end
27
+ if type(base.prototype.__newindex) == "function" then
28
+ target.prototype.__newindex = base.prototype.__newindex
29
+ end
30
+ if type(base.prototype.__tostring) == "function" then
31
+ target.prototype.__tostring = base.prototype.__tostring
32
+ end
33
+ end
34
+
35
+ local function __TS__CountVarargs(...)
36
+ return select("#", ...)
37
+ end
38
+
39
+ local function __TS__SparseArrayNew(...)
40
+ local sparseArray = {...}
41
+ sparseArray.sparseLength = __TS__CountVarargs(...)
42
+ return sparseArray
43
+ end
44
+
45
+ local function __TS__SparseArrayPush(sparseArray, ...)
46
+ local args = {...}
47
+ local argsLen = __TS__CountVarargs(...)
48
+ local listLen = sparseArray.sparseLength
49
+ for i = 1, argsLen do
50
+ sparseArray[listLen + i] = args[i]
51
+ end
52
+ sparseArray.sparseLength = listLen + argsLen
53
+ end
54
+
55
+ local function __TS__SparseArraySpread(sparseArray)
56
+ local _unpack = unpack or table.unpack
57
+ return _unpack(sparseArray, 1, sparseArray.sparseLength)
58
+ end
59
+ -- End of Lua Library inline imports
60
+ local ____exports = {}
61
+ local ____Decoration = require("ui.decorations.Decoration")
62
+ local Decoration = ____Decoration.Decoration
63
+ --- Attaches hover routing to a Cell. Creates no frames, textures or update loop.
64
+ ____exports.Tooltip = __TS__Class()
65
+ local Tooltip = ____exports.Tooltip
66
+ Tooltip.name = "Tooltip"
67
+ __TS__ClassExtends(Tooltip, Decoration)
68
+ function Tooltip.prototype.____constructor(self, props)
69
+ Decoration.prototype.____constructor(self)
70
+ self.props = props
71
+ end
72
+ function Tooltip.prototype.draw(self, frame)
73
+ local binding = {
74
+ frame = frame,
75
+ motion = frame:IsMouseMotionEnabled()
76
+ }
77
+ self.binding = binding
78
+ binding.enter = function() return self:Show(frame) end
79
+ binding.leave = function() return self:Hide() end
80
+ frame:HookScript(
81
+ "OnEnter",
82
+ function()
83
+ local ____opt_0 = binding.enter
84
+ return ____opt_0 and ____opt_0(binding)
85
+ end
86
+ )
87
+ frame:HookScript(
88
+ "OnLeave",
89
+ function()
90
+ local ____opt_2 = binding.leave
91
+ return ____opt_2 and ____opt_2(binding)
92
+ end
93
+ )
94
+ frame:HookScript(
95
+ "OnHide",
96
+ function()
97
+ local ____opt_4 = binding.leave
98
+ return ____opt_4 and ____opt_4(binding)
99
+ end
100
+ )
101
+ if not binding.motion then
102
+ frame:EnableMouseMotion(true)
103
+ end
104
+ end
105
+ function Tooltip.prototype.Show(self, owner)
106
+ self:Hide()
107
+ local target = self.props.target
108
+ local ____temp_6
109
+ if type(target) == "function" then
110
+ ____temp_6 = target(nil)
111
+ else
112
+ ____temp_6 = target or GameTooltip
113
+ end
114
+ local tooltip = ____temp_6
115
+ if tooltip == nil then
116
+ return
117
+ end
118
+ tooltip:SetOwner(owner, self.props.anchor or "ANCHOR_RIGHT")
119
+ self.shown = {tooltip = tooltip, owner = owner}
120
+ do
121
+ local function ____catch(failure)
122
+ self:Hide()
123
+ error(failure, 0)
124
+ end
125
+ local ____try, ____hasReturned, ____returnValue = pcall(function()
126
+ tooltip:ClearLines()
127
+ if self.props.show ~= nil then
128
+ if self.props:show(tooltip, owner) == false then
129
+ self:Hide()
130
+ return true
131
+ end
132
+ else
133
+ local ____temp_7
134
+ if type(self.props.text) == "function" then
135
+ ____temp_7 = self.props:text()
136
+ else
137
+ ____temp_7 = self.props.text
138
+ end
139
+ local text = ____temp_7
140
+ if text == nil then
141
+ self:Hide()
142
+ return true
143
+ end
144
+ local color = self.props.color or ({r = 1, g = 1, b = 1})
145
+ local ____tooltip_SetText_10 = tooltip.SetText
146
+ local ____array_9 = __TS__SparseArrayNew(
147
+ text,
148
+ color.r,
149
+ color.g,
150
+ color.b,
151
+ color.a or 1
152
+ )
153
+ local ____self_props_wrap_8 = self.props.wrap
154
+ if ____self_props_wrap_8 == nil then
155
+ ____self_props_wrap_8 = true
156
+ end
157
+ __TS__SparseArrayPush(____array_9, ____self_props_wrap_8)
158
+ ____tooltip_SetText_10(
159
+ tooltip,
160
+ __TS__SparseArraySpread(____array_9)
161
+ )
162
+ end
163
+ for ____, line in ipairs(self.props.lines or ({})) do
164
+ local color = line.color or ({r = 1, g = 1, b = 1})
165
+ local ____tooltip_AddLine_13 = tooltip.AddLine
166
+ local ____array_12 = __TS__SparseArrayNew(line.text, color.r, color.g, color.b)
167
+ local ____line_wrap_11 = line.wrap
168
+ if ____line_wrap_11 == nil then
169
+ ____line_wrap_11 = true
170
+ end
171
+ __TS__SparseArrayPush(____array_12, ____line_wrap_11)
172
+ ____tooltip_AddLine_13(
173
+ tooltip,
174
+ __TS__SparseArraySpread(____array_12)
175
+ )
176
+ end
177
+ tooltip:Show()
178
+ end)
179
+ if not ____try then
180
+ ____hasReturned, ____returnValue = ____catch(____hasReturned)
181
+ end
182
+ if ____hasReturned then
183
+ return ____returnValue
184
+ end
185
+ end
186
+ end
187
+ function Tooltip.prototype.Hide(self)
188
+ local shown = self.shown
189
+ self.shown = nil
190
+ if shown ~= nil and shown.tooltip:IsOwned(shown.owner) then
191
+ shown.tooltip:Hide()
192
+ end
193
+ end
194
+ function Tooltip.prototype.dispose(self)
195
+ local binding = self.binding
196
+ self.binding = nil
197
+ if binding ~= nil then
198
+ binding.enter = nil
199
+ binding.leave = nil
200
+ local ____temp_17 = not binding.motion
201
+ if ____temp_17 then
202
+ local ____InCombatLockdown_result_16 = InCombatLockdown()
203
+ if ____InCombatLockdown_result_16 then
204
+ local ____this_15
205
+ ____this_15 = binding.frame
206
+ local ____opt_14 = ____this_15.IsProtected
207
+ ____InCombatLockdown_result_16 = (____opt_14 and ____opt_14(____this_15)) == true
208
+ end
209
+ ____temp_17 = not ____InCombatLockdown_result_16
210
+ end
211
+ if ____temp_17 then
212
+ binding.frame:EnableMouseMotion(false)
213
+ end
214
+ end
215
+ self:Hide()
216
+ Decoration.prototype.dispose(self)
217
+ end
218
+ return ____exports
package/lib/ui/index.d.ts CHANGED
@@ -24,6 +24,8 @@ export { ProgressBar } from "./ProgressBar";
24
24
  export { Background } from "./decorations/Background";
25
25
  export { Border } from "./decorations/Border";
26
26
  export { Glow } from "./decorations/Glow";
27
+ export { Tooltip } from "./decorations/Tooltip";
28
+ export type { TooltipProps, TooltipAnchor, TooltipLine, NativeTooltip } from "./decorations/Tooltip";
27
29
  export { Label } from "./Label";
28
30
  export type { LabelProps } from "./Label";
29
31
  export { Icon } from "./Icon";
package/lib/ui/index.lua CHANGED
@@ -68,6 +68,10 @@ do
68
68
  local ____Glow = require("ui.decorations.Glow")
69
69
  ____exports.Glow = ____Glow.Glow
70
70
  end
71
+ do
72
+ local ____Tooltip = require("ui.decorations.Tooltip")
73
+ ____exports.Tooltip = ____Tooltip.Tooltip
74
+ end
71
75
  do
72
76
  local ____Label = require("ui.Label")
73
77
  ____exports.Label = ____Label.Label
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wuira",
3
- "version": "0.2.2",
3
+ "version": "0.2.3",
4
4
  "author": {
5
5
  "name": "Kerim Cetinbas",
6
6
  "email": "a.cetinbas@icloud.com"