wuira 0.2.8 → 0.3.0
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 +13 -0
- package/README.md +6 -2
- package/docs/icons.md +1 -1
- package/docs/nameplates.md +1 -1
- package/lib/index.d.ts +0 -15
- package/lib/index.lua +0 -26
- package/lib/platform/index.d.ts +5 -0
- package/lib/platform/index.lua +11 -0
- package/lib/ui/UnitPortrait.d.ts +3 -0
- package/lib/ui/UnitPortrait.lua +233 -0
- package/lib/ui/index.d.ts +1 -0
- package/lib/ui/index.lua +4 -0
- package/package.json +8 -1
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,19 @@ with the release date and highlight breaking changes explicitly.
|
|
|
7
7
|
|
|
8
8
|
## Unreleased
|
|
9
9
|
|
|
10
|
+
## 0.3.0 — 2026-10-17
|
|
11
|
+
|
|
12
|
+
### Breaking
|
|
13
|
+
|
|
14
|
+
- The package root exports only the addon shell: `Wuira`, `wuira`, `WuiraApp`, `AddonSettings`, `Encoding`, `Store`, and `StoreRegistry`.
|
|
15
|
+
- Import widgets, including `UI`, `HoverTracker`, and `unitPortrait`, from `wuira/ui`.
|
|
16
|
+
- Import `BlizzardUI` and `ActionBars` from `wuira/platform`.
|
|
17
|
+
- Import `Nameplates` and `MicroBar` from `wuira/skins`. Spell and icon enums stay on `wuira/spells` and `wuira/icons`.
|
|
18
|
+
|
|
19
|
+
### Added
|
|
20
|
+
|
|
21
|
+
- `unitPortrait` mounts a unit portrait and a protected target/menu button without coupling resource widgets to that button.
|
|
22
|
+
|
|
10
23
|
## 0.2.8 — 2026-10-17
|
|
11
24
|
|
|
12
25
|
### Fixed
|
package/README.md
CHANGED
|
@@ -7,7 +7,8 @@ Build WoW Forever interfaces with TypeScript and JSX.
|
|
|
7
7
|
wuira is a UI framework and addon toolchain for developers who want to describe interfaces in code, compose reusable components, and keep game data separate from presentation. Write TypeScript, arrange native widgets with JSX, and compile your addon to Lua.
|
|
8
8
|
|
|
9
9
|
```tsx
|
|
10
|
-
import {
|
|
10
|
+
import { wuira } from "wuira";
|
|
11
|
+
import { UI } from "wuira/ui";
|
|
11
12
|
|
|
12
13
|
function ResourceBar({ current }: { current: number }) {
|
|
13
14
|
return <progress width="inherit" height={24} min={0} max={100} current={current} />;
|
|
@@ -79,7 +80,8 @@ Supported action types: `spell`, `item`, `macro`, `action`, and `target`. Action
|
|
|
79
80
|
## Nameplates
|
|
80
81
|
|
|
81
82
|
```tsx
|
|
82
|
-
import {
|
|
83
|
+
import { UI } from "wuira/ui";
|
|
84
|
+
import { Nameplates } from "wuira/skins";
|
|
83
85
|
import { HP } from "wuira/datasources";
|
|
84
86
|
|
|
85
87
|
const plates = Nameplates
|
|
@@ -141,6 +143,8 @@ For global installation, use `npm install -g wuira`. To test unpublished changes
|
|
|
141
143
|
|
|
142
144
|
wuira is an early framework. It is not a complete UI replacement, an in-game visual editor, or a WeakAuras replacement. JSX describes widgets; there is no React runtime or automatic reactive rendering layer. Combat restrictions and secret-value rules still apply and cannot be bypassed by the framework.
|
|
143
145
|
|
|
146
|
+
Import widgets from `wuira/ui` (including `unitPortrait`), native adapters from `wuira/skins`, and `BlizzardUI` / `ActionBars` from `wuira/platform`. The package root is the addon shell.
|
|
147
|
+
|
|
144
148
|
Current core includes Cells, layouts, progress bars, decorations, unit sources, native nameplate adapters, and project tooling. Not yet implemented: a complete WoW API surface, nameplate click-cast abstractions, and preset management. Nameplate lifecycle tests use a mock Lua runtime; real-client validation is still required.
|
|
145
149
|
|
|
146
150
|
The target client is WoW Forever. Compatibility with Retail or other Classic clients is not promised without verification.
|
package/docs/icons.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
`Icons` contains native texture **FileDataIDs** from the same verified Forever build as the spell enums. Icon identity is independent of spell or item actions.
|
|
4
4
|
|
|
5
5
|
```ts
|
|
6
|
-
import { UI } from "wuira";
|
|
6
|
+
import { UI } from "wuira/ui";
|
|
7
7
|
import { Icons } from "wuira/icons";
|
|
8
8
|
import { Icon } from "wuira/ui";
|
|
9
9
|
|
package/docs/nameplates.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Nameplates
|
|
2
2
|
|
|
3
|
-
Import `Nameplates` from `wuira
|
|
3
|
+
Import `Nameplates` from `wuira/skins`. Wuira owns native access,
|
|
4
4
|
events, unit bindings and visual cleanup. Preset selection, NPC rules, editor
|
|
5
5
|
data and component collections belong to the consuming addon (for example LumaUI).
|
|
6
6
|
No class or mob presets are built into Wuira.
|
package/lib/index.d.ts
CHANGED
|
@@ -5,20 +5,5 @@ export { WuiraApp } from "./WuiraApp";
|
|
|
5
5
|
export type { CommandCallback } from "./platform/SlashCommands";
|
|
6
6
|
export { AddonSettings } from "./platform/AddonSettings";
|
|
7
7
|
export { Encoding } from "./platform/Encoding";
|
|
8
|
-
export { DruidSpells, GeneralSpells, HunterSpells, MageSpells, PaladinSpells, PetSpells, PriestSpells, ProfessionSpells, RacialSpells, RogueSpells, ShamanSpells, WarlockSpells, WarriorSpells, WorldSpells, BindingActions, } from "./spells/index";
|
|
9
|
-
export { Icons } from "./icons/index";
|
|
10
|
-
export { BlizzardUI } from "./platform/BlizzardUI";
|
|
11
|
-
export { ActionBars } from "./platform/ActionBars";
|
|
12
|
-
export type { ActionSlot, EmptyActionBarsOptions } from "./platform/ActionBars";
|
|
13
|
-
export type { BlizzardUIOptions } from "./platform/BlizzardUI";
|
|
14
|
-
export type { MicroMenuSkinOptions } from "./platform/MicroMenu";
|
|
15
|
-
export { UI } from "./ui/primitives/jsx";
|
|
16
|
-
export { HoverTracker } from "./ui/HoverTracker";
|
|
17
|
-
export type { HoverTrackerOptions, HoverFrame } from "./ui/HoverTracker";
|
|
18
|
-
export { MicroBar } from "./skins/MicroBar";
|
|
19
|
-
export { Nameplates, NameplateRules, NameplateContext } from "./skins/Nameplates";
|
|
20
|
-
export type { NameplateInfo, NameplateSelector, NameplateCustomize, NameplateRender, NativeNameplate, NativeNameplateVisual } from "./skins/Nameplates";
|
|
21
|
-
export type { Element, Component } from "./ui/primitives/jsx";
|
|
22
|
-
export type { Cell } from "./ui/Cell";
|
|
23
8
|
export { Store, StoreRegistry } from "./store/index";
|
|
24
9
|
export type { StoreClass, ReadonlyData, SavedStoreOptions } from "./store/index";
|
package/lib/index.lua
CHANGED
|
@@ -18,32 +18,6 @@ do
|
|
|
18
18
|
local ____Encoding = require("platform.Encoding")
|
|
19
19
|
____exports.Encoding = ____Encoding.Encoding
|
|
20
20
|
end
|
|
21
|
-
do
|
|
22
|
-
local ____BlizzardUI = require("platform.BlizzardUI")
|
|
23
|
-
____exports.BlizzardUI = ____BlizzardUI.BlizzardUI
|
|
24
|
-
end
|
|
25
|
-
do
|
|
26
|
-
local ____ActionBars = require("platform.ActionBars")
|
|
27
|
-
____exports.ActionBars = ____ActionBars.ActionBars
|
|
28
|
-
end
|
|
29
|
-
do
|
|
30
|
-
local ____jsx = require("ui.primitives.jsx")
|
|
31
|
-
____exports.UI = ____jsx.UI
|
|
32
|
-
end
|
|
33
|
-
do
|
|
34
|
-
local ____HoverTracker = require("ui.HoverTracker")
|
|
35
|
-
____exports.HoverTracker = ____HoverTracker.HoverTracker
|
|
36
|
-
end
|
|
37
|
-
do
|
|
38
|
-
local ____MicroBar = require("skins.MicroBar")
|
|
39
|
-
____exports.MicroBar = ____MicroBar.MicroBar
|
|
40
|
-
end
|
|
41
|
-
do
|
|
42
|
-
local ____Nameplates = require("skins.Nameplates")
|
|
43
|
-
____exports.Nameplates = ____Nameplates.Nameplates
|
|
44
|
-
____exports.NameplateRules = ____Nameplates.NameplateRules
|
|
45
|
-
____exports.NameplateContext = ____Nameplates.NameplateContext
|
|
46
|
-
end
|
|
47
21
|
do
|
|
48
22
|
local ____index = require("store.index")
|
|
49
23
|
____exports.Store = ____index.Store
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { BlizzardUI } from "./BlizzardUI";
|
|
2
|
+
export type { BlizzardUIOptions } from "./BlizzardUI";
|
|
3
|
+
export { ActionBars } from "./ActionBars";
|
|
4
|
+
export type { ActionSlot, EmptyActionBarsOptions } from "./ActionBars";
|
|
5
|
+
export type { MicroMenuSkinOptions } from "./MicroMenu";
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
--[[ Generated with https://github.com/TypeScriptToLua/TypeScriptToLua ]]
|
|
2
|
+
local ____exports = {}
|
|
3
|
+
do
|
|
4
|
+
local ____BlizzardUI = require("platform.BlizzardUI")
|
|
5
|
+
____exports.BlizzardUI = ____BlizzardUI.BlizzardUI
|
|
6
|
+
end
|
|
7
|
+
do
|
|
8
|
+
local ____ActionBars = require("platform.ActionBars")
|
|
9
|
+
____exports.ActionBars = ____ActionBars.ActionBars
|
|
10
|
+
end
|
|
11
|
+
return ____exports
|
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
--[[ Generated with https://github.com/TypeScriptToLua/TypeScriptToLua ]]
|
|
2
|
+
-- Lua Library inline imports
|
|
3
|
+
local function __TS__StringTrim(self)
|
|
4
|
+
local result = string.gsub(self, "^[%s ]*(.-)[%s ]*$", "%1")
|
|
5
|
+
return result
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
local function __TS__StringIncludes(self, searchString, position)
|
|
9
|
+
if not position then
|
|
10
|
+
position = 1
|
|
11
|
+
else
|
|
12
|
+
position = position + 1
|
|
13
|
+
end
|
|
14
|
+
local index = string.find(self, searchString, position, true)
|
|
15
|
+
return index ~= nil
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
local function __TS__ObjectAssign(target, ...)
|
|
19
|
+
local sources = {...}
|
|
20
|
+
for i = 1, #sources do
|
|
21
|
+
local source = sources[i]
|
|
22
|
+
if type(source) == "table" then
|
|
23
|
+
for key in pairs(source) do
|
|
24
|
+
target[key] = source[key]
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
return target
|
|
29
|
+
end
|
|
30
|
+
-- End of Lua Library inline imports
|
|
31
|
+
local ____exports = {}
|
|
32
|
+
local ____UnitSource = require("datasources.UnitSource")
|
|
33
|
+
local resolveUnit = ____UnitSource.resolveUnit
|
|
34
|
+
local ____jsx = require("ui.primitives.jsx")
|
|
35
|
+
local UI = ____jsx.UI
|
|
36
|
+
function ____exports.unitPortrait(self, props, input, crop, preview)
|
|
37
|
+
if preview == nil then
|
|
38
|
+
preview = false
|
|
39
|
+
end
|
|
40
|
+
if issecretvalue(input) or type(input) == "string" and __TS__StringTrim(input) == "" then
|
|
41
|
+
error("Unit portrait requires a public unit token", 0)
|
|
42
|
+
end
|
|
43
|
+
local target = resolveUnit(nil, input)
|
|
44
|
+
return UI:createElement(
|
|
45
|
+
"cell",
|
|
46
|
+
__TS__ObjectAssign(
|
|
47
|
+
{},
|
|
48
|
+
props,
|
|
49
|
+
{
|
|
50
|
+
clickThrough = true,
|
|
51
|
+
onMount = function(____, frame)
|
|
52
|
+
local host = frame
|
|
53
|
+
local ____preview_0
|
|
54
|
+
if preview then
|
|
55
|
+
____preview_0 = nil
|
|
56
|
+
else
|
|
57
|
+
____preview_0 = CreateFrame("Button", nil, UIParent, "SecureActionButtonTemplate")
|
|
58
|
+
end
|
|
59
|
+
local button = ____preview_0
|
|
60
|
+
local owner = button or host
|
|
61
|
+
local texture = owner:CreateTexture(nil, "OVERLAY")
|
|
62
|
+
texture:SetAllPoints(owner)
|
|
63
|
+
local buttonUnit = target.Token
|
|
64
|
+
local stopUnit
|
|
65
|
+
local stopped = false
|
|
66
|
+
local stopping = false
|
|
67
|
+
local elapsed = 0
|
|
68
|
+
local lastX
|
|
69
|
+
local lastY
|
|
70
|
+
local lastWidth
|
|
71
|
+
local lastHeight
|
|
72
|
+
local lastStrata
|
|
73
|
+
local lastLevel
|
|
74
|
+
local lastAlpha
|
|
75
|
+
local function draw()
|
|
76
|
+
if stopped or stopping then
|
|
77
|
+
return
|
|
78
|
+
end
|
|
79
|
+
SetPortraitTexture(texture, target.Token, true)
|
|
80
|
+
local uv = crop or ({0, 1, 0, 1})
|
|
81
|
+
texture:SetTexCoord(uv[1], uv[2], uv[3], uv[4])
|
|
82
|
+
end
|
|
83
|
+
local function cleanup()
|
|
84
|
+
if stopped then
|
|
85
|
+
return
|
|
86
|
+
end
|
|
87
|
+
stopped = true
|
|
88
|
+
if stopUnit ~= nil then
|
|
89
|
+
stopUnit(nil)
|
|
90
|
+
end
|
|
91
|
+
stopUnit = nil
|
|
92
|
+
host:SetScript("OnUpdate", nil)
|
|
93
|
+
owner:UnregisterAllEvents()
|
|
94
|
+
owner:SetScript("OnEvent", nil)
|
|
95
|
+
if button ~= nil then
|
|
96
|
+
button:SetAttribute("type1", nil)
|
|
97
|
+
button:SetAttribute("type2", nil)
|
|
98
|
+
button:EnableMouse(false)
|
|
99
|
+
button:Hide()
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
local function sync()
|
|
103
|
+
if button == nil or stopped or stopping or InCombatLockdown() then
|
|
104
|
+
return
|
|
105
|
+
end
|
|
106
|
+
if buttonUnit ~= target.Token then
|
|
107
|
+
button:SetAttribute("unit", target.Token)
|
|
108
|
+
buttonUnit = target.Token
|
|
109
|
+
end
|
|
110
|
+
if not host:IsVisible() then
|
|
111
|
+
if button:IsShown() then
|
|
112
|
+
button:Hide()
|
|
113
|
+
end
|
|
114
|
+
return
|
|
115
|
+
end
|
|
116
|
+
local x, y = host:GetCenter()
|
|
117
|
+
if x == nil or y == nil then
|
|
118
|
+
return
|
|
119
|
+
end
|
|
120
|
+
local scale = host:GetEffectiveScale() / UIParent:GetEffectiveScale()
|
|
121
|
+
local width = host:GetWidth() * scale
|
|
122
|
+
local height = host:GetHeight() * scale
|
|
123
|
+
local cx = x * scale
|
|
124
|
+
local cy = y * scale
|
|
125
|
+
if cx ~= lastX or cy ~= lastY or width ~= lastWidth or height ~= lastHeight then
|
|
126
|
+
button:ClearAllPoints()
|
|
127
|
+
button:SetPoint(
|
|
128
|
+
"CENTER",
|
|
129
|
+
UIParent,
|
|
130
|
+
"BOTTOMLEFT",
|
|
131
|
+
cx,
|
|
132
|
+
cy
|
|
133
|
+
)
|
|
134
|
+
button:SetSize(width, height)
|
|
135
|
+
lastX = cx
|
|
136
|
+
lastY = cy
|
|
137
|
+
lastWidth = width
|
|
138
|
+
lastHeight = height
|
|
139
|
+
end
|
|
140
|
+
local strata = host:GetFrameStrata()
|
|
141
|
+
local level = host:GetFrameLevel() + 2
|
|
142
|
+
local alpha = host:GetEffectiveAlpha()
|
|
143
|
+
if strata ~= lastStrata then
|
|
144
|
+
button:SetFrameStrata(strata)
|
|
145
|
+
lastStrata = strata
|
|
146
|
+
end
|
|
147
|
+
if level ~= lastLevel then
|
|
148
|
+
button:SetFrameLevel(level)
|
|
149
|
+
lastLevel = level
|
|
150
|
+
end
|
|
151
|
+
if alpha ~= lastAlpha then
|
|
152
|
+
button:SetAlpha(alpha)
|
|
153
|
+
lastAlpha = alpha
|
|
154
|
+
end
|
|
155
|
+
if not button:IsShown() then
|
|
156
|
+
button:Show()
|
|
157
|
+
end
|
|
158
|
+
end
|
|
159
|
+
do
|
|
160
|
+
local function ____catch(failure)
|
|
161
|
+
cleanup(nil)
|
|
162
|
+
error(failure, 0)
|
|
163
|
+
end
|
|
164
|
+
local ____try, ____hasReturned = pcall(function()
|
|
165
|
+
if button ~= nil then
|
|
166
|
+
button:RegisterForClicks("LeftButtonUp", "RightButtonUp")
|
|
167
|
+
button:SetID(0)
|
|
168
|
+
button:SetAttribute("useOnKeyDown", false)
|
|
169
|
+
button:SetAttribute("unit", target.Token)
|
|
170
|
+
button:SetAttribute("type1", "target")
|
|
171
|
+
button:SetAttribute("type2", "togglemenu")
|
|
172
|
+
button:EnableMouse(true)
|
|
173
|
+
host:SetScript(
|
|
174
|
+
"OnUpdate",
|
|
175
|
+
function(_frame, delta)
|
|
176
|
+
elapsed = elapsed + delta
|
|
177
|
+
if elapsed >= 0.05 then
|
|
178
|
+
elapsed = 0
|
|
179
|
+
sync(nil)
|
|
180
|
+
end
|
|
181
|
+
end
|
|
182
|
+
)
|
|
183
|
+
host:HookScript("OnShow", sync)
|
|
184
|
+
host:HookScript("OnHide", sync)
|
|
185
|
+
owner:RegisterEvent("PLAYER_REGEN_ENABLED")
|
|
186
|
+
end
|
|
187
|
+
for ____, event in ipairs({"UNIT_PORTRAIT_UPDATE", "UNIT_MODEL_CHANGED", "PORTRAITS_UPDATED", "PLAYER_ENTERING_WORLD"}) do
|
|
188
|
+
owner:RegisterEvent(event)
|
|
189
|
+
end
|
|
190
|
+
if __TS__StringIncludes(target.Token, "target") then
|
|
191
|
+
owner:RegisterEvent("PLAYER_TARGET_CHANGED")
|
|
192
|
+
end
|
|
193
|
+
if __TS__StringIncludes(target.Token, "focus") then
|
|
194
|
+
owner:RegisterEvent("PLAYER_FOCUS_CHANGED")
|
|
195
|
+
end
|
|
196
|
+
owner:SetScript(
|
|
197
|
+
"OnEvent",
|
|
198
|
+
function(_frame, event, eventUnit)
|
|
199
|
+
if event == "PLAYER_REGEN_ENABLED" then
|
|
200
|
+
if stopping then
|
|
201
|
+
cleanup(nil)
|
|
202
|
+
else
|
|
203
|
+
sync(nil)
|
|
204
|
+
end
|
|
205
|
+
elseif event ~= "UNIT_PORTRAIT_UPDATE" and event ~= "UNIT_MODEL_CHANGED" or eventUnit == target.Token then
|
|
206
|
+
draw(nil)
|
|
207
|
+
end
|
|
208
|
+
end
|
|
209
|
+
)
|
|
210
|
+
stopUnit = target:onTokenChange(function()
|
|
211
|
+
draw(nil)
|
|
212
|
+
sync(nil)
|
|
213
|
+
end)
|
|
214
|
+
draw(nil)
|
|
215
|
+
sync(nil)
|
|
216
|
+
end)
|
|
217
|
+
if not ____try then
|
|
218
|
+
____catch(____hasReturned)
|
|
219
|
+
end
|
|
220
|
+
end
|
|
221
|
+
return function()
|
|
222
|
+
stopping = true
|
|
223
|
+
if button ~= nil and InCombatLockdown() then
|
|
224
|
+
return
|
|
225
|
+
end
|
|
226
|
+
cleanup(nil)
|
|
227
|
+
end
|
|
228
|
+
end
|
|
229
|
+
}
|
|
230
|
+
)
|
|
231
|
+
)
|
|
232
|
+
end
|
|
233
|
+
return ____exports
|
package/lib/ui/index.d.ts
CHANGED
package/lib/ui/index.lua
CHANGED
package/package.json
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"type": "git",
|
|
5
5
|
"url": "git+https://github.com/KerimCETINBAS/wuira.git"
|
|
6
6
|
},
|
|
7
|
-
"version": "0.
|
|
7
|
+
"version": "0.3.0",
|
|
8
8
|
"author": {
|
|
9
9
|
"name": "Kerim Cetinbas",
|
|
10
10
|
"email": "a.cetinbas@icloud.com"
|
|
@@ -32,6 +32,10 @@
|
|
|
32
32
|
"types": "./lib/skins/index.d.ts",
|
|
33
33
|
"default": "./lib/skins/index.lua"
|
|
34
34
|
},
|
|
35
|
+
"./platform": {
|
|
36
|
+
"types": "./lib/platform/index.d.ts",
|
|
37
|
+
"default": "./lib/platform/index.lua"
|
|
38
|
+
},
|
|
35
39
|
"./spells": {
|
|
36
40
|
"types": "./lib/spells/index.d.ts",
|
|
37
41
|
"default": "./lib/spells/index.lua"
|
|
@@ -66,6 +70,9 @@
|
|
|
66
70
|
"skins": [
|
|
67
71
|
"lib/skins/index.d.ts"
|
|
68
72
|
],
|
|
73
|
+
"platform": [
|
|
74
|
+
"lib/platform/index.d.ts"
|
|
75
|
+
],
|
|
69
76
|
"spells": [
|
|
70
77
|
"lib/spells/index.d.ts"
|
|
71
78
|
],
|