wuira 0.2.5 → 0.2.7
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 +29 -0
- package/README.md +25 -2
- package/docs/nameplates.md +89 -0
- package/docs/source-converters.md +9 -16
- package/lib/WuiraApp.lua +42 -6
- package/lib/datasources/SourceConverter.d.ts +0 -9
- package/lib/datasources/SourceConverter.lua +0 -93
- package/lib/datasources/index.d.ts +2 -3
- package/lib/datasources/index.lua +0 -5
- package/lib/index.d.ts +2 -0
- package/lib/index.lua +6 -0
- package/lib/platform/forever.d.ts +3 -0
- package/lib/skins/Nameplates.d.ts +56 -0
- package/lib/skins/Nameplates.lua +1119 -0
- package/lib/skins/index.d.ts +2 -0
- package/lib/skins/index.lua +6 -0
- package/package.json +3 -2
- package/lib/datasources/MathConverter.d.ts +0 -6
- package/lib/datasources/MathConverter.lua +0 -61
- package/lib/datasources/MathExpression.d.ts +0 -16
- package/lib/datasources/MathExpression.lua +0 -281
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,35 @@ with the release date and highlight breaking changes explicitly.
|
|
|
7
7
|
|
|
8
8
|
## Unreleased
|
|
9
9
|
|
|
10
|
+
## 0.2.7 — 2026-10-16
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- Generic `Nameplates.Apply` / `Replace` registration groups, with global first-match
|
|
15
|
+
precedence, fresh per-unit JSX factories, reversible native visual helpers,
|
|
16
|
+
event-driven pooled-frame lifecycle, explicit refresh, and independent disposal.
|
|
17
|
+
Forbidden/protected frames and secret identities are skipped; secure JSX is rejected.
|
|
18
|
+
- Lua integration coverage for nameplate reuse, rule conflicts, rollback, native
|
|
19
|
+
restoration and HP subscription cleanup. These are mock tests, not in-game validation.
|
|
20
|
+
|
|
21
|
+
### Fixed
|
|
22
|
+
|
|
23
|
+
- Continue unmount cleanup after a binding or decoration disposer throws, so remaining
|
|
24
|
+
subscriptions and frames are released before the first error is reported.
|
|
25
|
+
|
|
26
|
+
## 0.2.6 — 2026-10-16
|
|
27
|
+
|
|
28
|
+
### Changed
|
|
29
|
+
|
|
30
|
+
- Keep wuira source conversion callback-based. Case mappings and arithmetic
|
|
31
|
+
formula factories now belong to LumaUI's builder layer.
|
|
32
|
+
|
|
33
|
+
### Removed
|
|
34
|
+
|
|
35
|
+
- **Breaking:** Remove the `CaseConverter` and `MathConverter` APIs introduced in
|
|
36
|
+
0.2.5, including the expression parser. Use `new SourceConverter(source,
|
|
37
|
+
value => ...)` in wuira code; LumaUI owns its editable case/math definitions.
|
|
38
|
+
|
|
10
39
|
## 0.2.5 — 2026-10-16
|
|
11
40
|
|
|
12
41
|
### Added
|
package/README.md
CHANGED
|
@@ -30,7 +30,7 @@ wuira.Mount(App);
|
|
|
30
30
|
- **Native widgets** — Cells mount to WoW frames; progress bars use the native StatusBar widget.
|
|
31
31
|
- **Layout primitives** — Arrange children with `flow` and `grid`.
|
|
32
32
|
- **Data sources** — HP, Mana, auras, cooldowns, casts, swings, group members, class/spec, spellbook.
|
|
33
|
-
- **Source converters** —
|
|
33
|
+
- **Source converters** — Transform checked values with typed callbacks. See [source converters](docs/source-converters.md).
|
|
34
34
|
- **Slash commands** — Register commands with quoting and escaping support.
|
|
35
35
|
- **Windows and settings** — `Window`, `AddonSettings`, `FrameMover`, `KeybindCapture`.
|
|
36
36
|
- **Secure buttons** — Spell, item, macro, action, and target actions with `SecureButton`.
|
|
@@ -76,6 +76,29 @@ Other sources include `AuraTimer`, `GlobalCooldown`, `CastTimer`, `SpellCooldown
|
|
|
76
76
|
|
|
77
77
|
Supported action types: `spell`, `item`, `macro`, `action`, and `target`. Actions and units are static mount-time attributes. Protected trees cannot be mounted during combat.
|
|
78
78
|
|
|
79
|
+
## Nameplates
|
|
80
|
+
|
|
81
|
+
```tsx
|
|
82
|
+
import { Nameplates, UI } from "wuira";
|
|
83
|
+
import { HP } from "wuira/datasources";
|
|
84
|
+
|
|
85
|
+
const plates = Nameplates
|
|
86
|
+
.Apply(p => p.GUID === configuredGUID, p => {
|
|
87
|
+
if (p.Native.healthBar) p.Size(p.Native.healthBar, 140, 12);
|
|
88
|
+
})
|
|
89
|
+
.Replace(() => true, p => (
|
|
90
|
+
<progress width={140} height={12} source={new HP(p.Unit)} />
|
|
91
|
+
));
|
|
92
|
+
|
|
93
|
+
// plates.Dispose();
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
The first matching rule wins across Apply and Replace; they do not stack.
|
|
97
|
+
Each factory creates fresh JSX for its unit. Use `Nameplates.Create()` with
|
|
98
|
+
`collection.forEach(...)` to register presets, and `Refresh()` after preset changes.
|
|
99
|
+
See [nameplate lifecycle and cleanup](docs/nameplates.md). Secure nameplate controls
|
|
100
|
+
require a separate lifecycle and are not supported by this visual API.
|
|
101
|
+
|
|
79
102
|
## Stores
|
|
80
103
|
|
|
81
104
|
```ts
|
|
@@ -118,7 +141,7 @@ For global installation, use `npm install -g wuira`. To test unpublished changes
|
|
|
118
141
|
|
|
119
142
|
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.
|
|
120
143
|
|
|
121
|
-
Current core includes Cells,
|
|
144
|
+
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.
|
|
122
145
|
|
|
123
146
|
The target client is WoW Forever. Compatibility with Retail or other Classic clients is not promised without verification.
|
|
124
147
|
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# Nameplates
|
|
2
|
+
|
|
3
|
+
Import `Nameplates` from `wuira` or `wuira/skins`. Wuira owns native access,
|
|
4
|
+
events, unit bindings and visual cleanup. Preset selection, NPC rules, editor
|
|
5
|
+
data and component collections belong to the consuming addon (for example LumaUI).
|
|
6
|
+
No class or mob presets are built into Wuira.
|
|
7
|
+
|
|
8
|
+
`NativeSkin` remains the adapter for fixed named frames. Nameplates use a separate
|
|
9
|
+
event-driven manager because both carriers and unit visuals are dynamically pooled.
|
|
10
|
+
|
|
11
|
+
## Rules and ownership
|
|
12
|
+
|
|
13
|
+
`Nameplates.Apply(selector, customize)` and `Nameplates.Replace(selector, render)`
|
|
14
|
+
start independent groups. Chained calls append to that same group. `Nameplates.Create()`
|
|
15
|
+
starts an empty group, useful for collections:
|
|
16
|
+
|
|
17
|
+
```tsx
|
|
18
|
+
const plates = Nameplates.Create();
|
|
19
|
+
collection.forEach(component => {
|
|
20
|
+
plates.Replace(p => component.matches(p.Unit, p.GUID), p => component.render(p));
|
|
21
|
+
});
|
|
22
|
+
// When preset data changes:
|
|
23
|
+
plates.Refresh();
|
|
24
|
+
// On addon feature shutdown:
|
|
25
|
+
plates.Dispose();
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Rules are ordered by registration time across all groups. **The first matching
|
|
29
|
+
rule wins, regardless of whether it is Apply or Replace.** Apply rules do not
|
|
30
|
+
accumulate before/after a replacement. Put specific rules before fallbacks.
|
|
31
|
+
Disposing a losing group leaves the winning binding intact. Disposing a winning
|
|
32
|
+
group restores its changes and then activates the next matching rule, if any.
|
|
33
|
+
Dispose is idempotent; adding rules to a disposed group is an error.
|
|
34
|
+
|
|
35
|
+
Selectors receive `Unit`, public `GUID`, engine-owned `Frame`, and native visual
|
|
36
|
+
`Native` (with optional `healthBar` / `castBar`). Restricted identities/frames
|
|
37
|
+
never reach selectors. A selector error or secret result leaves the plate native;
|
|
38
|
+
it does not activate a less specific fallback. Callback errors go to WoW's error
|
|
39
|
+
handler. A failing winner is retried on refresh or the next relevant native event.
|
|
40
|
+
Callbacks must not add/dispose/refresh groups while reconciliation is running.
|
|
41
|
+
|
|
42
|
+
## Apply
|
|
43
|
+
|
|
44
|
+
Apply reuses Blizzard's visuals and bars. The context exposes reversible
|
|
45
|
+
`Alpha(frame, value)`, `Scale(frame, value)`, `Size(frame, width, height)`, and
|
|
46
|
+
`BarColor(bar, r, g, b, a?)`. These accept the native visual or its accessible,
|
|
47
|
+
unprotected descendants; the engine-owned carrier is excluded.
|
|
48
|
+
|
|
49
|
+
Cleanup restores a property only if it still equals the value this binding wrote,
|
|
50
|
+
so a later external write is preserved. Blizzard or another addon can overwrite
|
|
51
|
+
Apply styling; it is reapplied on relevant identity/faction/target/world events or
|
|
52
|
+
explicit refresh, rather than continuously polled. Direct native writes through
|
|
53
|
+
`Frame`/`Native` are outside rollback ownership and should be avoided.
|
|
54
|
+
|
|
55
|
+
Register each owned subscription immediately with `p.OnDispose(stop)` before
|
|
56
|
+
doing more work that could throw. Disposers run in reverse order, and a failing
|
|
57
|
+
disposer cannot prevent the remaining cleanup operations.
|
|
58
|
+
|
|
59
|
+
## Replace
|
|
60
|
+
|
|
61
|
+
Replace mounts the factory's fresh visual JSX under the native carrier, centered
|
|
62
|
+
on it, and suppresses native UnitFrame alpha only after mounting succeeds. It
|
|
63
|
+
keeps native scripts and events registered. A dormant hook per pooled UnitFrame
|
|
64
|
+
maintains suppression and remembers subsequent public native alpha writes for
|
|
65
|
+
restoration. This does not arbitrate competing nameplate addons that also hide,
|
|
66
|
+
reparent or replace native visuals.
|
|
67
|
+
|
|
68
|
+
Factories run per unit binding. Do not return one cached JSX instance for several
|
|
69
|
+
plates: mounting rejects simultaneous reuse. Bind sources inside the factory,
|
|
70
|
+
for example `new HP(p.Unit)`; mounting owns their widget subscriptions. Register
|
|
71
|
+
additional manual subscriptions through `OnDispose`.
|
|
72
|
+
|
|
73
|
+
Nameplate add/remove events, GUID changes and reuse of either carrier or UnitFrame
|
|
74
|
+
dispose the previous binding before a fresh factory runs. Already visible plates
|
|
75
|
+
are discovered on registration and world entry. Name/faction/target events and
|
|
76
|
+
`Refresh()` reevaluate selection and visuals. Health events are handled by data
|
|
77
|
+
sources, without polling selectors. Refresh also rebuilds matching views so edited
|
|
78
|
+
preset values take effect. Protected/forbidden frames and secret GUIDs are skipped.
|
|
79
|
+
|
|
80
|
+
Native positioning, movement, click bounds and ordinary targeting stay with the
|
|
81
|
+
engine. This API does not resize the carrier or alter native click areas. Ordinary
|
|
82
|
+
unprotected visuals can mount/unmount during combat. Secure JSX is rejected,
|
|
83
|
+
including outside combat: secure nameplate buttons need a separate design for
|
|
84
|
+
combat-time creation, positioning and correct targeting. Fixed arena secure cells
|
|
85
|
+
do not establish that dynamic nameplate buttons are safe.
|
|
86
|
+
|
|
87
|
+
The Lua integration tests exercise the compiled framework with mock WoW APIs,
|
|
88
|
+
including actual HP source subscription cleanup and mounting failures. They do
|
|
89
|
+
not establish real-client behavior or compatibility with other nameplate addons.
|
|
@@ -1,34 +1,27 @@
|
|
|
1
1
|
# Source converters
|
|
2
2
|
|
|
3
|
-
`SourceConverter` transforms a readable source
|
|
3
|
+
`SourceConverter` transforms a readable source with a typed callback. It consumes change notifications, shares one upstream subscription across observers, and does not create a timer or dispose the shared input. Sources without notifications remain available as checked one-time reads.
|
|
4
4
|
|
|
5
5
|
```ts
|
|
6
|
-
import {
|
|
6
|
+
import { SourceConverter, HP, ClassSource, Unit } from "wuira/datasources";
|
|
7
7
|
|
|
8
|
+
const hp = new HP(Unit.Player);
|
|
9
|
+
const doubled = new SourceConverter(hp, value => value * 2);
|
|
8
10
|
const characterClass = new ClassSource(Unit.Player);
|
|
9
11
|
const token = new SourceConverter(characterClass, info => info?.token);
|
|
10
|
-
const color = new CaseConverter(token, [
|
|
11
|
-
{ equals: "PALADIN", value: { r: 1, g: 0.5, b: 0.7, a: 1 } },
|
|
12
|
-
{ equals: "MAGE", value: { r: 0.4, g: 0.8, b: 1, a: 1 } },
|
|
13
|
-
], { r: 0.35, g: 0.4, b: 0.45, a: 1 });
|
|
14
|
-
|
|
15
|
-
const hp = new HP(Unit.Player);
|
|
16
|
-
const doubled = new MathConverter(hp, "2 * input");
|
|
17
12
|
const stop = doubled.BindTo(value => console.log(value));
|
|
13
|
+
|
|
18
14
|
// On removal:
|
|
19
15
|
stop();
|
|
20
16
|
doubled.Dispose();
|
|
21
|
-
color.Dispose();
|
|
22
17
|
token.Dispose();
|
|
23
18
|
characterClass.Dispose();
|
|
24
19
|
```
|
|
25
20
|
|
|
26
|
-
`Value` and `Compute()` are checked reads. `TryCompute()` performs one checked read and returns `{ readable: false }` for restricted data
|
|
27
|
-
|
|
28
|
-
Cases compare strings, finite numbers and booleans with strict equality; `1` and `"1"` are different keys. Duplicate keys are rejected. Unmatched values return the supplied default, or `undefined` when none was provided. Case outputs can be colors, texture IDs, text or other data.
|
|
21
|
+
`Value` and `Compute()` are checked reads. `TryCompute()` performs one checked read and returns `{ readable: false }` for restricted data without invoking the callback. Converter chains use it to read their leaf once, including when the data is restricted.
|
|
29
22
|
|
|
30
|
-
|
|
23
|
+
`onChange()` observes future readable output changes; `BindTo()` also applies the current readable value immediately. Identical scalar outputs do not emit again. `When()` filters emissions without changing the checked getter. `Dispose()` releases observers while leaving the input available to other consumers.
|
|
31
24
|
|
|
32
|
-
Restricted values, including nested secret fields, never reach a conversion callback. Restrictions are checked when
|
|
25
|
+
Restricted values, including nested secret fields, never reach a conversion callback. Restrictions are checked when consumed; combat alone does not mark a value secret. ClassSource subscriptions follow unit identity changes and native events, releasing listeners when the last consumer unsubscribes.
|
|
33
26
|
|
|
34
|
-
|
|
27
|
+
The SDK accepts TypeScript callbacks. Editable case rules and math formulas are LumaUI builder factories, implemented using this generic source. Converters produce data; protected button actions remain subject to native combat restrictions.
|
package/lib/WuiraApp.lua
CHANGED
|
@@ -372,22 +372,58 @@ function WuiraApp.prototype.Unmount(self, frame)
|
|
|
372
372
|
tree.pendingUnmount = true
|
|
373
373
|
return
|
|
374
374
|
end
|
|
375
|
+
local failed = false
|
|
376
|
+
local failure
|
|
377
|
+
local function attempt(____, action)
|
|
378
|
+
do
|
|
379
|
+
local function ____catch(caught)
|
|
380
|
+
if not failed then
|
|
381
|
+
failed = true
|
|
382
|
+
failure = caught
|
|
383
|
+
end
|
|
384
|
+
end
|
|
385
|
+
local ____try, ____hasReturned = pcall(function()
|
|
386
|
+
action(nil)
|
|
387
|
+
end)
|
|
388
|
+
if not ____try then
|
|
389
|
+
____catch(____hasReturned)
|
|
390
|
+
end
|
|
391
|
+
end
|
|
392
|
+
end
|
|
375
393
|
for ____, dispose in ipairs(tree.bindings) do
|
|
376
|
-
|
|
394
|
+
attempt(nil, dispose)
|
|
377
395
|
end
|
|
378
396
|
for ____, decoration in ipairs(tree.decorations) do
|
|
379
|
-
|
|
397
|
+
attempt(
|
|
398
|
+
nil,
|
|
399
|
+
function() return decoration:dispose() end
|
|
400
|
+
)
|
|
380
401
|
end
|
|
381
402
|
for ____, child in ipairs(tree.frames) do
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
403
|
+
attempt(
|
|
404
|
+
nil,
|
|
405
|
+
function() return child:UnregisterAllEvents() end
|
|
406
|
+
)
|
|
407
|
+
attempt(
|
|
408
|
+
nil,
|
|
409
|
+
function() return child:SetScript("OnEvent", nil) end
|
|
410
|
+
)
|
|
411
|
+
attempt(
|
|
412
|
+
nil,
|
|
413
|
+
function() return child:SetScript("OnUpdate", nil) end
|
|
414
|
+
)
|
|
415
|
+
attempt(
|
|
416
|
+
nil,
|
|
417
|
+
function() return child:Hide() end
|
|
418
|
+
)
|
|
386
419
|
end
|
|
387
420
|
for ____, cell in ipairs(tree.cells) do
|
|
388
421
|
self.mountedFrames:delete(cell.props)
|
|
389
422
|
end
|
|
390
423
|
self.mountedTrees:delete(frame)
|
|
424
|
+
if failed then
|
|
425
|
+
error(failure, 0)
|
|
426
|
+
end
|
|
391
427
|
end
|
|
392
428
|
function WuiraApp.prototype.Protect(self, root, tree)
|
|
393
429
|
local ____temp_8 = not tree.protected
|
|
@@ -28,12 +28,3 @@ export declare class SourceConverter<TInput, TOutput> extends DataSource<TOutput
|
|
|
28
28
|
BindTo(apply: (value: TOutput) => void): () => void;
|
|
29
29
|
Dispose(): void;
|
|
30
30
|
}
|
|
31
|
-
export type CaseKey = string | number | boolean;
|
|
32
|
-
export interface SourceCase<T> {
|
|
33
|
-
readonly equals: CaseKey;
|
|
34
|
-
readonly value: T;
|
|
35
|
-
}
|
|
36
|
-
/** Strict equality, first matching case, then the optional default value. */
|
|
37
|
-
export declare class CaseConverter<TInput, TOutput> extends SourceConverter<TInput, TOutput | undefined> {
|
|
38
|
-
constructor(input: ValueSource<TInput>, cases: readonly SourceCase<TOutput>[], fallback?: TOutput);
|
|
39
|
-
}
|
|
@@ -319,62 +319,6 @@ local function __TS__ClassExtends(target, base)
|
|
|
319
319
|
target.prototype.__tostring = base.prototype.__tostring
|
|
320
320
|
end
|
|
321
321
|
end
|
|
322
|
-
|
|
323
|
-
local function __TS__ObjectAssign(target, ...)
|
|
324
|
-
local sources = {...}
|
|
325
|
-
for i = 1, #sources do
|
|
326
|
-
local source = sources[i]
|
|
327
|
-
if type(source) == "table" then
|
|
328
|
-
for key in pairs(source) do
|
|
329
|
-
target[key] = source[key]
|
|
330
|
-
end
|
|
331
|
-
end
|
|
332
|
-
end
|
|
333
|
-
return target
|
|
334
|
-
end
|
|
335
|
-
|
|
336
|
-
local function __TS__ArrayMap(self, callbackfn, thisArg)
|
|
337
|
-
local result = {}
|
|
338
|
-
for i = 1, #self do
|
|
339
|
-
result[i] = callbackfn(thisArg, self[i], i - 1, self)
|
|
340
|
-
end
|
|
341
|
-
return result
|
|
342
|
-
end
|
|
343
|
-
|
|
344
|
-
local function __TS__TypeOf(value)
|
|
345
|
-
local luaType = type(value)
|
|
346
|
-
if luaType == "table" then
|
|
347
|
-
return "object"
|
|
348
|
-
elseif luaType == "nil" then
|
|
349
|
-
return "undefined"
|
|
350
|
-
else
|
|
351
|
-
return luaType
|
|
352
|
-
end
|
|
353
|
-
end
|
|
354
|
-
|
|
355
|
-
local function __TS__ArrayIncludes(self, searchElement, fromIndex)
|
|
356
|
-
if fromIndex == nil then
|
|
357
|
-
fromIndex = 0
|
|
358
|
-
end
|
|
359
|
-
local len = #self
|
|
360
|
-
local k = fromIndex
|
|
361
|
-
if fromIndex < 0 then
|
|
362
|
-
k = len + fromIndex
|
|
363
|
-
end
|
|
364
|
-
if k < 0 then
|
|
365
|
-
k = 0
|
|
366
|
-
end
|
|
367
|
-
for i = k + 1, len do
|
|
368
|
-
if self[i] == searchElement then
|
|
369
|
-
return true
|
|
370
|
-
end
|
|
371
|
-
end
|
|
372
|
-
return false
|
|
373
|
-
end
|
|
374
|
-
|
|
375
|
-
local function __TS__NumberIsFinite(value)
|
|
376
|
-
return type(value) == "number" and value == value and value ~= math.huge and value ~= -math.huge
|
|
377
|
-
end
|
|
378
322
|
-- End of Lua Library inline imports
|
|
379
323
|
local ____exports = {}
|
|
380
324
|
local ____DataSource = require("datasources.DataSource")
|
|
@@ -528,41 +472,4 @@ function SourceConverter.prototype.Dispose(self)
|
|
|
528
472
|
self.stop = nil
|
|
529
473
|
self.listeners:clear()
|
|
530
474
|
end
|
|
531
|
-
--- Strict equality, first matching case, then the optional default value.
|
|
532
|
-
____exports.CaseConverter = __TS__Class()
|
|
533
|
-
local CaseConverter = ____exports.CaseConverter
|
|
534
|
-
CaseConverter.name = "CaseConverter"
|
|
535
|
-
__TS__ClassExtends(CaseConverter, ____exports.SourceConverter)
|
|
536
|
-
function CaseConverter.prototype.____constructor(self, input, cases, fallback)
|
|
537
|
-
local entries = __TS__ArrayMap(
|
|
538
|
-
cases,
|
|
539
|
-
function(____, entry) return __TS__ObjectAssign({}, entry) end
|
|
540
|
-
)
|
|
541
|
-
local seen = __TS__New(Set)
|
|
542
|
-
for ____, entry in ipairs(entries) do
|
|
543
|
-
local key = entry.equals
|
|
544
|
-
if issecretvalue(key) or not __TS__ArrayIncludes(
|
|
545
|
-
{"string", "number", "boolean"},
|
|
546
|
-
__TS__TypeOf(key)
|
|
547
|
-
) or type(key) == "number" and not __TS__NumberIsFinite(key) then
|
|
548
|
-
error("CaseConverter: invalid match value")
|
|
549
|
-
end
|
|
550
|
-
if seen:has(key) then
|
|
551
|
-
error("CaseConverter: duplicate match value")
|
|
552
|
-
end
|
|
553
|
-
seen:add(key)
|
|
554
|
-
end
|
|
555
|
-
CaseConverter.____super.prototype.____constructor(
|
|
556
|
-
self,
|
|
557
|
-
input,
|
|
558
|
-
function(____, value)
|
|
559
|
-
for ____, entry in ipairs(entries) do
|
|
560
|
-
if value == entry.equals then
|
|
561
|
-
return entry.value
|
|
562
|
-
end
|
|
563
|
-
end
|
|
564
|
-
return fallback
|
|
565
|
-
end
|
|
566
|
-
)
|
|
567
|
-
end
|
|
568
475
|
return ____exports
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
/// <reference path="../platform/forever.d.ts" />
|
|
2
2
|
export { DataSource } from "./DataSource";
|
|
3
3
|
export type { ReadResult } from "./DataSource";
|
|
4
|
-
export { SourceConverter
|
|
5
|
-
export type { ValueSource
|
|
6
|
-
export { MathConverter } from "./MathConverter";
|
|
4
|
+
export { SourceConverter } from "./SourceConverter";
|
|
5
|
+
export type { ValueSource } from "./SourceConverter";
|
|
7
6
|
export { EditModeLayouts } from "./EditModeLayouts";
|
|
8
7
|
export type { EditModeLayout, EditModeLayoutSnapshot, EditModeLayoutsStatus } from "./EditModeLayouts";
|
|
9
8
|
export { ProgressSource } from "./ProgressSource";
|
|
@@ -7,11 +7,6 @@ end
|
|
|
7
7
|
do
|
|
8
8
|
local ____SourceConverter = require("datasources.SourceConverter")
|
|
9
9
|
____exports.SourceConverter = ____SourceConverter.SourceConverter
|
|
10
|
-
____exports.CaseConverter = ____SourceConverter.CaseConverter
|
|
11
|
-
end
|
|
12
|
-
do
|
|
13
|
-
local ____MathConverter = require("datasources.MathConverter")
|
|
14
|
-
____exports.MathConverter = ____MathConverter.MathConverter
|
|
15
10
|
end
|
|
16
11
|
do
|
|
17
12
|
local ____EditModeLayouts = require("datasources.EditModeLayouts")
|
package/lib/index.d.ts
CHANGED
|
@@ -16,6 +16,8 @@ export { UI } from "./ui/primitives/jsx";
|
|
|
16
16
|
export { HoverTracker } from "./ui/HoverTracker";
|
|
17
17
|
export type { HoverTrackerOptions, HoverFrame } from "./ui/HoverTracker";
|
|
18
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";
|
|
19
21
|
export type { Element, Component } from "./ui/primitives/jsx";
|
|
20
22
|
export type { Cell } from "./ui/Cell";
|
|
21
23
|
export { Store, StoreRegistry } from "./store/index";
|
package/lib/index.lua
CHANGED
|
@@ -38,6 +38,12 @@ do
|
|
|
38
38
|
local ____MicroBar = require("skins.MicroBar")
|
|
39
39
|
____exports.MicroBar = ____MicroBar.MicroBar
|
|
40
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
|
|
41
47
|
do
|
|
42
48
|
local ____index = require("store.index")
|
|
43
49
|
____exports.Store = ____index.Store
|
|
@@ -35,6 +35,8 @@ interface wuiraNativeFrame {
|
|
|
35
35
|
SetScript(script: "OnMouseWheel", handler: ((this: void, frame: wuiraNativeFrame, delta: number) => void) | undefined): void;
|
|
36
36
|
GetName(): string | undefined;
|
|
37
37
|
IsProtected?(): boolean;
|
|
38
|
+
IsForbidden?(): boolean;
|
|
39
|
+
GetAlpha(): number;
|
|
38
40
|
GetParent(): wuiraNativeFrame;
|
|
39
41
|
GetNumPoints(): number;
|
|
40
42
|
GetPoint(index: number): wuiraNativeReturns<[wuiraAnchor, wuiraNativeFrame, wuiraAnchor, number, number]>;
|
|
@@ -95,6 +97,7 @@ declare const UIParent: wuiraNativeFrame;
|
|
|
95
97
|
declare const _G: Record<string, unknown>;
|
|
96
98
|
declare const SlashCmdList: Record<string, (this: void, message: string) => void>;
|
|
97
99
|
interface wuiraNativeStatusBar extends wuiraNativeFrame {
|
|
100
|
+
GetStatusBarColor(): wuiraNativeReturns<[number, number, number, number]>;
|
|
98
101
|
GetStatusBarTexture(): wuiraNativeTexture;
|
|
99
102
|
SetMinMaxValues(min: number, max: number): void;
|
|
100
103
|
SetValue(value: number): void;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import type { Cell } from "../ui/Cell";
|
|
2
|
+
export interface NativeNameplate extends wuiraNativeFrame {
|
|
3
|
+
readonly UnitFrame?: NativeNameplateVisual;
|
|
4
|
+
readonly namePlateUnitToken?: string;
|
|
5
|
+
GetUnit?(): string | undefined;
|
|
6
|
+
}
|
|
7
|
+
export interface NativeNameplateVisual extends wuiraNativeFrame {
|
|
8
|
+
readonly healthBar?: wuiraNativeStatusBar;
|
|
9
|
+
readonly castBar?: wuiraNativeStatusBar;
|
|
10
|
+
}
|
|
11
|
+
export interface NameplateInfo {
|
|
12
|
+
readonly Unit: string;
|
|
13
|
+
readonly GUID: string;
|
|
14
|
+
/** Engine-owned carrier. Do not mutate it or attach secure controls through this API. */
|
|
15
|
+
readonly Frame: NativeNameplate;
|
|
16
|
+
readonly Native: NativeNameplateVisual;
|
|
17
|
+
}
|
|
18
|
+
export type NameplateSelector = (this: void, plate: NameplateInfo) => boolean;
|
|
19
|
+
export type NameplateCustomize = (this: void, plate: NameplateContext) => void;
|
|
20
|
+
export type NameplateRender = (this: void, plate: NameplateContext) => Cell;
|
|
21
|
+
/** One unit binding. Use the reversible methods; direct native writes are not tracked. */
|
|
22
|
+
export declare class NameplateContext implements NameplateInfo {
|
|
23
|
+
readonly Unit: string;
|
|
24
|
+
readonly GUID: string;
|
|
25
|
+
readonly Frame: NativeNameplate;
|
|
26
|
+
readonly Native: NativeNameplateVisual;
|
|
27
|
+
private active;
|
|
28
|
+
private readonly cleanup;
|
|
29
|
+
constructor(Unit: string, GUID: string, Frame: NativeNameplate, Native: NativeNameplateVisual);
|
|
30
|
+
/** Register owned subscriptions/sources immediately, before subsequent work can throw. */
|
|
31
|
+
OnDispose(cleanup: () => void): void;
|
|
32
|
+
private check;
|
|
33
|
+
Alpha(frame: wuiraNativeFrame, value: number): void;
|
|
34
|
+
Scale(frame: wuiraNativeFrame, value: number): void;
|
|
35
|
+
Size(frame: wuiraNativeFrame, width: number, height: number): void;
|
|
36
|
+
BarColor(bar: wuiraNativeStatusBar, r: number, g: number, b: number, a?: number): void;
|
|
37
|
+
/** Internal lifecycle endpoint; cleanup failures cannot prevent other restorations. */
|
|
38
|
+
Dispose(): void;
|
|
39
|
+
}
|
|
40
|
+
/** An independently disposable ordered registration group. First matching rule wins globally. */
|
|
41
|
+
export declare class NameplateRules {
|
|
42
|
+
private disposed;
|
|
43
|
+
private add;
|
|
44
|
+
Apply(selector: NameplateSelector, customize: NameplateCustomize): this;
|
|
45
|
+
Replace(selector: NameplateSelector, render: NameplateRender): this;
|
|
46
|
+
/** Re-evaluate after external preset/selector data changes; native events handle unit changes. */
|
|
47
|
+
Refresh(): void;
|
|
48
|
+
Dispose(): void;
|
|
49
|
+
}
|
|
50
|
+
/** Each entry call creates a new group; chained calls append to that group. */
|
|
51
|
+
export declare class Nameplates {
|
|
52
|
+
private constructor();
|
|
53
|
+
static Apply(selector: NameplateSelector, customize: NameplateCustomize): NameplateRules;
|
|
54
|
+
static Replace(selector: NameplateSelector, render: NameplateRender): NameplateRules;
|
|
55
|
+
static Create(): NameplateRules;
|
|
56
|
+
}
|