wuira 0.2.2 → 0.2.4
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 +28 -0
- package/README.md +69 -6
- package/lib/datasources/GroupMembers.d.ts +6 -0
- package/lib/datasources/GroupMembers.lua +332 -0
- package/lib/datasources/GroupRoster.d.ts +28 -0
- package/lib/datasources/GroupRoster.lua +611 -0
- package/lib/datasources/Resources.d.ts +3 -2
- package/lib/datasources/Resources.lua +57 -48
- package/lib/datasources/UnitSource.d.ts +8 -3
- package/lib/datasources/UnitSource.lua +318 -5
- package/lib/datasources/index.d.ts +3 -1
- package/lib/datasources/index.lua +6 -0
- package/lib/platform/forever.d.ts +2 -0
- package/lib/rendering/decorations.lua +1 -0
- package/lib/ui/Cell.d.ts +2 -0
- package/lib/ui/ForEach.d.ts +18 -4
- package/lib/ui/ForEach.lua +763 -13
- package/lib/ui/decorations/Decorations.d.ts +2 -0
- package/lib/ui/decorations/Tooltip.d.ts +50 -0
- package/lib/ui/decorations/Tooltip.lua +218 -0
- package/lib/ui/index.d.ts +3 -1
- package/lib/ui/index.lua +4 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,34 @@ with the release date and highlight breaking changes explicitly.
|
|
|
7
7
|
|
|
8
8
|
## Unreleased
|
|
9
9
|
|
|
10
|
+
## 0.2.4 — 2026-10-15
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- Observable keyed ForEach rendering. Stable keys retain native widgets and their
|
|
15
|
+
subscriptions across joins, leaves, reorder and metadata updates; only added or
|
|
16
|
+
removed records mount or dispose. Supports grouped layout and wrapping.
|
|
17
|
+
- Native GroupRoster metadata with GUID identity, full-name/realm fallback, pet
|
|
18
|
+
ownership and raid subgroup membership. Retains the last readable roster if
|
|
19
|
+
native membership data becomes restricted.
|
|
20
|
+
- Cell keys, event-driven GroupMembers subscriptions and shared UnitSource
|
|
21
|
+
retargeting. HP/Mana readers and event filters follow the existing unit reference.
|
|
22
|
+
|
|
23
|
+
### Changed
|
|
24
|
+
|
|
25
|
+
- Defer keyed structural updates and unit retargeting until combat ends, keeping
|
|
26
|
+
protected click targets aligned with displayed data.
|
|
27
|
+
|
|
28
|
+
## 0.2.3 — 2026-10-15
|
|
29
|
+
|
|
30
|
+
### Added
|
|
31
|
+
|
|
32
|
+
- Tooltip attachment in Cell decorations, inherited by all visual components.
|
|
33
|
+
Route hover to native GameTooltip or another native tooltip with custom text,
|
|
34
|
+
extra lines or a callback using native spell, item, unit, hyperlink and action APIs.
|
|
35
|
+
- Motion-only hover input preserves click-through behavior and existing scripts;
|
|
36
|
+
owned tooltips close on leave, hide and disposal without changing secure actions.
|
|
37
|
+
|
|
10
38
|
## 0.2.2 — 2026-10-15
|
|
11
39
|
|
|
12
40
|
### Added
|
package/README.md
CHANGED
|
@@ -270,9 +270,10 @@ function SealButtons() {
|
|
|
270
270
|
|
|
271
271
|
The render function receives the item and its zero-based index. Use `ForEach`
|
|
272
272
|
inside a layout for multiple siblings; Cell still accepts at most one expanded
|
|
273
|
-
child. Nested loops are flattened in order.
|
|
273
|
+
child. Nested loops are flattened in order. Array inputs create no subscriptions:
|
|
274
274
|
recreate the view from `known.onChange` when needed, outside combat for protected
|
|
275
|
-
trees. Each filtered rank remains a separate entry.
|
|
275
|
+
trees. Each filtered rank remains a separate entry. Observable list sources also
|
|
276
|
+
support keyed updates, as shown below under Group members.
|
|
276
277
|
|
|
277
278
|
All visual cells accept `condition={boolean}` or `condition={() => boolean}`.
|
|
278
279
|
This controls visibility and retains the layout slot. It combines with datasource
|
|
@@ -542,10 +543,45 @@ const raid = new RaidMembers();
|
|
|
542
543
|
`GroupMembers` returns `["player"]` while solo, `player` plus `partyN` tokens
|
|
543
544
|
in a party, and `raidN` tokens in a raid. `PartyMembers` is empty outside a
|
|
544
545
|
party; `RaidMembers` is empty outside a raid. The player is included once.
|
|
545
|
-
Offline members are retained. Each `.Value` access reads the current roster
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
roster changes and should not be used as persistent identities.
|
|
546
|
+
Offline members are retained. Each `.Value` access reads the current roster.
|
|
547
|
+
`onChange` subscribes to roster, pet, connection and name events without polling;
|
|
548
|
+
unsubscribe or call `Dispose()` when done. Tokens may refer to different members
|
|
549
|
+
after roster changes and should not be used as persistent identities.
|
|
550
|
+
|
|
551
|
+
`GroupRoster` adds GUID-based keys, full-name/realm fallback, pet ownership and
|
|
552
|
+
raid subgroup metadata. Pass it directly to `ForEach` to retain mounted cells and
|
|
553
|
+
their resource subscriptions while the roster changes:
|
|
554
|
+
|
|
555
|
+
```tsx
|
|
556
|
+
import { UI, Wuira } from "wuira";
|
|
557
|
+
import { ForEach, ProgressBar, type Element } from "wuira/ui";
|
|
558
|
+
import { GroupRoster, HP, UnitSource } from "wuira/datasources";
|
|
559
|
+
|
|
560
|
+
const roster = new GroupRoster("party", { pets: true, includeSelfWhenSolo: true });
|
|
561
|
+
const units = new Map<Element, UnitSource>();
|
|
562
|
+
const view = (
|
|
563
|
+
<ForEach items={roster} key={member => member.key}
|
|
564
|
+
direction="vertical" wrapAfter={5} gap={4} lineGap={8}
|
|
565
|
+
onUpdate={(view, member) => units.get(view)!.Retarget(member.unit)}
|
|
566
|
+
onDispose={view => { units.delete(view); }}>
|
|
567
|
+
{member => {
|
|
568
|
+
const unit = new UnitSource(member.unit);
|
|
569
|
+
const view = <ProgressBar width={160} height={24} source={new HP(unit)} />;
|
|
570
|
+
units.set(view, unit);
|
|
571
|
+
return view;
|
|
572
|
+
}}
|
|
573
|
+
</ForEach>
|
|
574
|
+
);
|
|
575
|
+
const frame = Wuira.Mount(view)!;
|
|
576
|
+
// On teardown: Wuira.Unmount(frame); roster.Dispose();
|
|
577
|
+
```
|
|
578
|
+
|
|
579
|
+
Observable inputs expose `Value` and `onChange`, and require unique, public keys.
|
|
580
|
+
Only new keys call the child factory; removed keys unmount and call `onDispose`.
|
|
581
|
+
Use `onUpdate` to update retained views when their unit token or metadata changes.
|
|
582
|
+
Structural changes wait until combat ends. The observable `ForEach` owns its
|
|
583
|
+
layout and sizes its native host; mount it as a root or reserve an explicit slot
|
|
584
|
+
in its parent layout. `groupBy` can arrange raid subgroups in separate columns.
|
|
549
585
|
|
|
550
586
|
### Player class and specialization
|
|
551
587
|
|
|
@@ -567,6 +603,9 @@ specs.RequestInspect();
|
|
|
567
603
|
These sources accept real players only; NPCs produce no data or inspect request.
|
|
568
604
|
The same `UnitSource` can be passed to `Buffs`, `Debuffs`, `HP`, and `Mana`.
|
|
569
605
|
Its `Value` contains the current token and GUID, rather than a cached identity.
|
|
606
|
+
`Retarget(token)` changes a shared reference outside combat; bound HP/Mana widgets
|
|
607
|
+
refresh without replacing their sources. `onChange` observes these explicit token
|
|
608
|
+
changes, not every change to the native unit's identity.
|
|
570
609
|
`Is.PC` and `Is.Self` return `undefined` when their native result is secret.
|
|
571
610
|
String unit tokens are still supported as a convenience shorthand.
|
|
572
611
|
Own specialization data is read directly. Other players require an explicit,
|
|
@@ -610,6 +649,30 @@ not install event listeners or poll automatically. The current adapter requires
|
|
|
610
649
|
in-game verification. Unit tokens refer to snapshot time and are not persistent
|
|
611
650
|
caster identities. No Paladin-specific spell catalog or filtering is built in.
|
|
612
651
|
|
|
652
|
+
### Native tooltips
|
|
653
|
+
|
|
654
|
+
`Tooltip` attaches to any Cell through decorations. It forwards hover to the
|
|
655
|
+
game's native tooltip API and creates no visual regions or update loop.
|
|
656
|
+
|
|
657
|
+
```tsx
|
|
658
|
+
import { Cell, Tooltip } from "wuira/ui";
|
|
659
|
+
|
|
660
|
+
<Cell width={40} height={40} decorations={{
|
|
661
|
+
tooltip: new Tooltip({ text: "My tooltip", lines: [{ text: "Extra details" }] }),
|
|
662
|
+
}} />;
|
|
663
|
+
|
|
664
|
+
<Cell width={40} height={40} decorations={{
|
|
665
|
+
tooltip: new Tooltip({ show: tooltip => tooltip.SetSpellByID(635) }),
|
|
666
|
+
}} />;
|
|
667
|
+
```
|
|
668
|
+
|
|
669
|
+
The same attachment works on SecureButton. Call SetItemByID, SetUnit, SetHyperlink
|
|
670
|
+
or SetAction inside `show` for other native content. `text` may be a function
|
|
671
|
+
evaluated on hover; `show` may return false to suppress display. Optional `target`
|
|
672
|
+
selects another native tooltip, and `anchor` defaults to ANCHOR_RIGHT.
|
|
673
|
+
Hover preserves click-through and existing scripts. Leave, hide and unmount close
|
|
674
|
+
only a tooltip still owned by that Cell. Use one decoration instance per Cell.
|
|
675
|
+
|
|
613
676
|
### Visual styling
|
|
614
677
|
|
|
615
678
|
<!-- Screenshot: a dark Cell with a thin colored border. -->
|
|
@@ -4,7 +4,13 @@ export type GroupScope = "auto" | "party" | "raid";
|
|
|
4
4
|
export declare class GroupMembers extends DataSource<readonly string[]> {
|
|
5
5
|
readonly scope: GroupScope;
|
|
6
6
|
private restricted;
|
|
7
|
+
private readonly listeners;
|
|
8
|
+
private frame?;
|
|
7
9
|
constructor(scope?: GroupScope);
|
|
10
|
+
/** Roster/connection events, with one listener frame while observed. No polling. */
|
|
11
|
+
onChange(listener: (units: readonly string[]) => void): () => void;
|
|
12
|
+
private StopListening;
|
|
13
|
+
Dispose(): void;
|
|
8
14
|
protected HasSecretFields(): boolean;
|
|
9
15
|
protected GetValue(): readonly string[];
|
|
10
16
|
}
|
|
@@ -32,6 +32,284 @@ local function __TS__ClassExtends(target, base)
|
|
|
32
32
|
end
|
|
33
33
|
end
|
|
34
34
|
|
|
35
|
+
local __TS__Symbol, Symbol
|
|
36
|
+
do
|
|
37
|
+
local symbolMetatable = {__tostring = function(self)
|
|
38
|
+
return ("Symbol(" .. (self.description or "")) .. ")"
|
|
39
|
+
end}
|
|
40
|
+
function __TS__Symbol(description)
|
|
41
|
+
return setmetatable({description = description}, symbolMetatable)
|
|
42
|
+
end
|
|
43
|
+
Symbol = {
|
|
44
|
+
asyncDispose = __TS__Symbol("Symbol.asyncDispose"),
|
|
45
|
+
dispose = __TS__Symbol("Symbol.dispose"),
|
|
46
|
+
iterator = __TS__Symbol("Symbol.iterator"),
|
|
47
|
+
hasInstance = __TS__Symbol("Symbol.hasInstance"),
|
|
48
|
+
species = __TS__Symbol("Symbol.species"),
|
|
49
|
+
toStringTag = __TS__Symbol("Symbol.toStringTag")
|
|
50
|
+
}
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
local __TS__Iterator
|
|
54
|
+
do
|
|
55
|
+
local function iteratorGeneratorStep(self)
|
|
56
|
+
local co = self.____coroutine
|
|
57
|
+
local status, value = coroutine.resume(co)
|
|
58
|
+
if not status then
|
|
59
|
+
error(value, 0)
|
|
60
|
+
end
|
|
61
|
+
if coroutine.status(co) == "dead" then
|
|
62
|
+
return
|
|
63
|
+
end
|
|
64
|
+
return true, value
|
|
65
|
+
end
|
|
66
|
+
local function iteratorIteratorStep(self)
|
|
67
|
+
local result = self:next()
|
|
68
|
+
if result.done then
|
|
69
|
+
return
|
|
70
|
+
end
|
|
71
|
+
return true, result.value
|
|
72
|
+
end
|
|
73
|
+
local function iteratorStringStep(self, index)
|
|
74
|
+
index = index + 1
|
|
75
|
+
if index > #self then
|
|
76
|
+
return
|
|
77
|
+
end
|
|
78
|
+
return index, string.sub(self, index, index)
|
|
79
|
+
end
|
|
80
|
+
function __TS__Iterator(iterable)
|
|
81
|
+
if type(iterable) == "string" then
|
|
82
|
+
return iteratorStringStep, iterable, 0
|
|
83
|
+
elseif iterable.____coroutine ~= nil then
|
|
84
|
+
return iteratorGeneratorStep, iterable
|
|
85
|
+
elseif iterable[Symbol.iterator] then
|
|
86
|
+
local iterator = iterable[Symbol.iterator](iterable)
|
|
87
|
+
return iteratorIteratorStep, iterator
|
|
88
|
+
else
|
|
89
|
+
return ipairs(iterable)
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
local function __TS__New(target, ...)
|
|
95
|
+
local instance = setmetatable({}, target.prototype)
|
|
96
|
+
instance:____constructor(...)
|
|
97
|
+
return instance
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
local Set
|
|
101
|
+
do
|
|
102
|
+
Set = __TS__Class()
|
|
103
|
+
Set.name = "Set"
|
|
104
|
+
function Set.prototype.____constructor(self, values)
|
|
105
|
+
self[Symbol.toStringTag] = "Set"
|
|
106
|
+
self.size = 0
|
|
107
|
+
self.nextKey = {}
|
|
108
|
+
self.previousKey = {}
|
|
109
|
+
if values == nil then
|
|
110
|
+
return
|
|
111
|
+
end
|
|
112
|
+
local iterable = values
|
|
113
|
+
if iterable[Symbol.iterator] then
|
|
114
|
+
local iterator = iterable[Symbol.iterator](iterable)
|
|
115
|
+
while true do
|
|
116
|
+
local result = iterator:next()
|
|
117
|
+
if result.done then
|
|
118
|
+
break
|
|
119
|
+
end
|
|
120
|
+
self:add(result.value)
|
|
121
|
+
end
|
|
122
|
+
else
|
|
123
|
+
local array = values
|
|
124
|
+
for ____, value in ipairs(array) do
|
|
125
|
+
self:add(value)
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
function Set.prototype.add(self, value)
|
|
130
|
+
local isNewValue = not self:has(value)
|
|
131
|
+
if isNewValue then
|
|
132
|
+
self.size = self.size + 1
|
|
133
|
+
end
|
|
134
|
+
if self.firstKey == nil then
|
|
135
|
+
self.firstKey = value
|
|
136
|
+
self.lastKey = value
|
|
137
|
+
elseif isNewValue then
|
|
138
|
+
self.nextKey[self.lastKey] = value
|
|
139
|
+
self.previousKey[value] = self.lastKey
|
|
140
|
+
self.lastKey = value
|
|
141
|
+
end
|
|
142
|
+
return self
|
|
143
|
+
end
|
|
144
|
+
function Set.prototype.clear(self)
|
|
145
|
+
self.nextKey = {}
|
|
146
|
+
self.previousKey = {}
|
|
147
|
+
self.firstKey = nil
|
|
148
|
+
self.lastKey = nil
|
|
149
|
+
self.size = 0
|
|
150
|
+
end
|
|
151
|
+
function Set.prototype.delete(self, value)
|
|
152
|
+
local contains = self:has(value)
|
|
153
|
+
if contains then
|
|
154
|
+
self.size = self.size - 1
|
|
155
|
+
local next = self.nextKey[value]
|
|
156
|
+
local previous = self.previousKey[value]
|
|
157
|
+
if next ~= nil and previous ~= nil then
|
|
158
|
+
self.nextKey[previous] = next
|
|
159
|
+
self.previousKey[next] = previous
|
|
160
|
+
elseif next ~= nil then
|
|
161
|
+
self.firstKey = next
|
|
162
|
+
self.previousKey[next] = nil
|
|
163
|
+
elseif previous ~= nil then
|
|
164
|
+
self.lastKey = previous
|
|
165
|
+
self.nextKey[previous] = nil
|
|
166
|
+
else
|
|
167
|
+
self.firstKey = nil
|
|
168
|
+
self.lastKey = nil
|
|
169
|
+
end
|
|
170
|
+
self.nextKey[value] = nil
|
|
171
|
+
self.previousKey[value] = nil
|
|
172
|
+
end
|
|
173
|
+
return contains
|
|
174
|
+
end
|
|
175
|
+
function Set.prototype.forEach(self, callback)
|
|
176
|
+
for ____, key in __TS__Iterator(self:keys()) do
|
|
177
|
+
callback(nil, key, key, self)
|
|
178
|
+
end
|
|
179
|
+
end
|
|
180
|
+
function Set.prototype.has(self, value)
|
|
181
|
+
return self.nextKey[value] ~= nil or self.lastKey == value
|
|
182
|
+
end
|
|
183
|
+
Set.prototype[Symbol.iterator] = function(self)
|
|
184
|
+
return self:values()
|
|
185
|
+
end
|
|
186
|
+
function Set.prototype.entries(self)
|
|
187
|
+
local function getFirstKey()
|
|
188
|
+
return self.firstKey
|
|
189
|
+
end
|
|
190
|
+
local nextKey = self.nextKey
|
|
191
|
+
local key
|
|
192
|
+
local started = false
|
|
193
|
+
return {
|
|
194
|
+
[Symbol.iterator] = function(self)
|
|
195
|
+
return self
|
|
196
|
+
end,
|
|
197
|
+
next = function(self)
|
|
198
|
+
if not started then
|
|
199
|
+
started = true
|
|
200
|
+
key = getFirstKey(nil)
|
|
201
|
+
else
|
|
202
|
+
key = nextKey[key]
|
|
203
|
+
end
|
|
204
|
+
return {done = not key, value = {key, key}}
|
|
205
|
+
end
|
|
206
|
+
}
|
|
207
|
+
end
|
|
208
|
+
function Set.prototype.keys(self)
|
|
209
|
+
local function getFirstKey()
|
|
210
|
+
return self.firstKey
|
|
211
|
+
end
|
|
212
|
+
local nextKey = self.nextKey
|
|
213
|
+
local key
|
|
214
|
+
local started = false
|
|
215
|
+
return {
|
|
216
|
+
[Symbol.iterator] = function(self)
|
|
217
|
+
return self
|
|
218
|
+
end,
|
|
219
|
+
next = function(self)
|
|
220
|
+
if not started then
|
|
221
|
+
started = true
|
|
222
|
+
key = getFirstKey(nil)
|
|
223
|
+
else
|
|
224
|
+
key = nextKey[key]
|
|
225
|
+
end
|
|
226
|
+
return {done = not key, value = key}
|
|
227
|
+
end
|
|
228
|
+
}
|
|
229
|
+
end
|
|
230
|
+
function Set.prototype.values(self)
|
|
231
|
+
local function getFirstKey()
|
|
232
|
+
return self.firstKey
|
|
233
|
+
end
|
|
234
|
+
local nextKey = self.nextKey
|
|
235
|
+
local key
|
|
236
|
+
local started = false
|
|
237
|
+
return {
|
|
238
|
+
[Symbol.iterator] = function(self)
|
|
239
|
+
return self
|
|
240
|
+
end,
|
|
241
|
+
next = function(self)
|
|
242
|
+
if not started then
|
|
243
|
+
started = true
|
|
244
|
+
key = getFirstKey(nil)
|
|
245
|
+
else
|
|
246
|
+
key = nextKey[key]
|
|
247
|
+
end
|
|
248
|
+
return {done = not key, value = key}
|
|
249
|
+
end
|
|
250
|
+
}
|
|
251
|
+
end
|
|
252
|
+
function Set.prototype.union(self, other)
|
|
253
|
+
local result = __TS__New(Set, self)
|
|
254
|
+
for ____, item in __TS__Iterator(other) do
|
|
255
|
+
result:add(item)
|
|
256
|
+
end
|
|
257
|
+
return result
|
|
258
|
+
end
|
|
259
|
+
function Set.prototype.intersection(self, other)
|
|
260
|
+
local result = __TS__New(Set)
|
|
261
|
+
for ____, item in __TS__Iterator(self) do
|
|
262
|
+
if other:has(item) then
|
|
263
|
+
result:add(item)
|
|
264
|
+
end
|
|
265
|
+
end
|
|
266
|
+
return result
|
|
267
|
+
end
|
|
268
|
+
function Set.prototype.difference(self, other)
|
|
269
|
+
local result = __TS__New(Set, self)
|
|
270
|
+
for ____, item in __TS__Iterator(other) do
|
|
271
|
+
result:delete(item)
|
|
272
|
+
end
|
|
273
|
+
return result
|
|
274
|
+
end
|
|
275
|
+
function Set.prototype.symmetricDifference(self, other)
|
|
276
|
+
local result = __TS__New(Set, self)
|
|
277
|
+
for ____, item in __TS__Iterator(other) do
|
|
278
|
+
if self:has(item) then
|
|
279
|
+
result:delete(item)
|
|
280
|
+
else
|
|
281
|
+
result:add(item)
|
|
282
|
+
end
|
|
283
|
+
end
|
|
284
|
+
return result
|
|
285
|
+
end
|
|
286
|
+
function Set.prototype.isSubsetOf(self, other)
|
|
287
|
+
for ____, item in __TS__Iterator(self) do
|
|
288
|
+
if not other:has(item) then
|
|
289
|
+
return false
|
|
290
|
+
end
|
|
291
|
+
end
|
|
292
|
+
return true
|
|
293
|
+
end
|
|
294
|
+
function Set.prototype.isSupersetOf(self, other)
|
|
295
|
+
for ____, item in __TS__Iterator(other) do
|
|
296
|
+
if not self:has(item) then
|
|
297
|
+
return false
|
|
298
|
+
end
|
|
299
|
+
end
|
|
300
|
+
return true
|
|
301
|
+
end
|
|
302
|
+
function Set.prototype.isDisjointFrom(self, other)
|
|
303
|
+
for ____, item in __TS__Iterator(self) do
|
|
304
|
+
if other:has(item) then
|
|
305
|
+
return false
|
|
306
|
+
end
|
|
307
|
+
end
|
|
308
|
+
return true
|
|
309
|
+
end
|
|
310
|
+
Set[Symbol.species] = Set
|
|
311
|
+
end
|
|
312
|
+
|
|
35
313
|
local function __TS__NumberIsFinite(value)
|
|
36
314
|
return type(value) == "number" and value == value and value ~= math.huge and value ~= -math.huge
|
|
37
315
|
end
|
|
@@ -55,6 +333,60 @@ function GroupMembers.prototype.____constructor(self, scope)
|
|
|
55
333
|
DataSource.prototype.____constructor(self, {})
|
|
56
334
|
self.scope = scope
|
|
57
335
|
self.restricted = false
|
|
336
|
+
self.listeners = __TS__New(Set)
|
|
337
|
+
end
|
|
338
|
+
function GroupMembers.prototype.onChange(self, listener)
|
|
339
|
+
self.listeners:add(listener)
|
|
340
|
+
if self.listeners.size == 1 then
|
|
341
|
+
if self.frame == nil then
|
|
342
|
+
self.frame = CreateFrame("Frame", nil, UIParent)
|
|
343
|
+
end
|
|
344
|
+
for ____, event in ipairs({
|
|
345
|
+
"GROUP_ROSTER_UPDATE",
|
|
346
|
+
"UNIT_PET",
|
|
347
|
+
"UNIT_CONNECTION",
|
|
348
|
+
"UNIT_NAME_UPDATE",
|
|
349
|
+
"PLAYER_ENTERING_WORLD"
|
|
350
|
+
}) do
|
|
351
|
+
self.frame:RegisterEvent(event)
|
|
352
|
+
end
|
|
353
|
+
self.frame:SetScript(
|
|
354
|
+
"OnEvent",
|
|
355
|
+
function()
|
|
356
|
+
local units = self:GetValue()
|
|
357
|
+
if self.restricted then
|
|
358
|
+
return
|
|
359
|
+
end
|
|
360
|
+
for ____, callback in __TS__Iterator(self.listeners) do
|
|
361
|
+
callback(nil, units)
|
|
362
|
+
end
|
|
363
|
+
end
|
|
364
|
+
)
|
|
365
|
+
end
|
|
366
|
+
return function()
|
|
367
|
+
self.listeners:delete(listener)
|
|
368
|
+
if self.listeners.size == 0 then
|
|
369
|
+
self:StopListening()
|
|
370
|
+
end
|
|
371
|
+
end
|
|
372
|
+
end
|
|
373
|
+
function GroupMembers.prototype.StopListening(self)
|
|
374
|
+
local ____opt_0 = self.frame
|
|
375
|
+
if ____opt_0 ~= nil then
|
|
376
|
+
____opt_0:UnregisterAllEvents()
|
|
377
|
+
end
|
|
378
|
+
local ____opt_2 = self.frame
|
|
379
|
+
if ____opt_2 ~= nil then
|
|
380
|
+
____opt_2:SetScript("OnEvent", nil)
|
|
381
|
+
end
|
|
382
|
+
local ____opt_4 = self.frame
|
|
383
|
+
if ____opt_4 ~= nil then
|
|
384
|
+
____opt_4:Hide()
|
|
385
|
+
end
|
|
386
|
+
end
|
|
387
|
+
function GroupMembers.prototype.Dispose(self)
|
|
388
|
+
self.listeners:clear()
|
|
389
|
+
self:StopListening()
|
|
58
390
|
end
|
|
59
391
|
function GroupMembers.prototype.HasSecretFields(self)
|
|
60
392
|
return self.restricted
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { DataSource } from "./DataSource";
|
|
2
|
+
import type { GroupScope } from "./GroupMembers";
|
|
3
|
+
export interface GroupRosterMember {
|
|
4
|
+
readonly key: string;
|
|
5
|
+
readonly guid?: string;
|
|
6
|
+
readonly unit: string;
|
|
7
|
+
readonly pet: boolean;
|
|
8
|
+
readonly group: string;
|
|
9
|
+
}
|
|
10
|
+
export declare function getPetUnitToken(unit: string): string;
|
|
11
|
+
/** Small snapshots describe identity/order only; keyed rendering owns widgets and unit sources. */
|
|
12
|
+
export declare class GroupRoster extends DataSource<readonly GroupRosterMember[]> {
|
|
13
|
+
private readonly scope;
|
|
14
|
+
private readonly options;
|
|
15
|
+
private readonly roster;
|
|
16
|
+
private readonly knownNames;
|
|
17
|
+
private snapshot;
|
|
18
|
+
private restricted;
|
|
19
|
+
get Status(): "ready" | "restricted";
|
|
20
|
+
constructor(scope?: GroupScope, options?: {
|
|
21
|
+
pets?: boolean;
|
|
22
|
+
includeSelfWhenSolo?: boolean;
|
|
23
|
+
});
|
|
24
|
+
protected GetValue(): readonly GroupRosterMember[];
|
|
25
|
+
private Read;
|
|
26
|
+
onChange(listener: (members: readonly GroupRosterMember[]) => void): () => void;
|
|
27
|
+
Dispose(): void;
|
|
28
|
+
}
|