@quenty/observablecollection 12.20.0 → 12.20.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/CHANGELOG.md +11 -0
- package/package.json +15 -15
- package/src/Shared/ObservableCountingMap.lua +102 -81
- package/src/Shared/ObservableList.lua +91 -70
- package/src/Shared/ObservableMap.lua +100 -78
- package/src/Shared/ObservableMapList.lua +2 -2
- package/src/Shared/ObservableMapSet.lua +83 -41
- package/src/Shared/ObservableSet.lua +61 -34
- package/src/Shared/SortedList/ObservableSortedList.lua +128 -58
- package/src/Shared/SortedList/ObservableSortedList.story.lua +1 -1
- package/src/Shared/SortedList/SortFunctionUtils.lua +25 -8
- package/src/Shared/SortedList/SortedNode.lua +231 -116
- package/src/Shared/SortedList/SortedNodeValue.lua +17 -6
- package/src/Shared/Utils/ListIndexUtils.lua +9 -2
- package/test/scripts/Server/ServerMain.server.lua +1 -1
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
--!strict
|
|
1
2
|
--[=[
|
|
2
3
|
A list that can be observed for blend and other components
|
|
3
4
|
@class ObservableMap
|
|
@@ -13,17 +14,59 @@ local Signal = require("Signal")
|
|
|
13
14
|
local ValueObject = require("ValueObject")
|
|
14
15
|
local RxBrioUtils = require("RxBrioUtils")
|
|
15
16
|
local DuckTypeUtils = require("DuckTypeUtils")
|
|
17
|
+
local _SortFunctionUtils = require("SortFunctionUtils")
|
|
16
18
|
|
|
17
19
|
local ObservableMap = {}
|
|
18
20
|
ObservableMap.ClassName = "ObservableMap"
|
|
19
21
|
ObservableMap.__index = ObservableMap
|
|
20
22
|
|
|
23
|
+
export type ObservableMap<TKey, TValue> = typeof(setmetatable(
|
|
24
|
+
{} :: {
|
|
25
|
+
_maid: Maid.Maid,
|
|
26
|
+
_map: { [TKey]: TValue },
|
|
27
|
+
_keySubTable: any, -- ObservableSubscriptionTable.ObservableSubscriptionTable<TKey>,
|
|
28
|
+
_countValue: ValueObject.ValueObject<number>,
|
|
29
|
+
|
|
30
|
+
--[=[
|
|
31
|
+
Fires when a key is added
|
|
32
|
+
@readonly
|
|
33
|
+
@prop KeyAdded Signal<TKey, TValue?>
|
|
34
|
+
@within ObservableMap
|
|
35
|
+
]=]
|
|
36
|
+
KeyAdded: Signal.Signal<(TKey, TValue)>,
|
|
37
|
+
|
|
38
|
+
--[=[
|
|
39
|
+
Fires when a key is removed
|
|
40
|
+
@readonly
|
|
41
|
+
@prop KeyRemoved Signal<TKey>
|
|
42
|
+
@within ObservableMap
|
|
43
|
+
]=]
|
|
44
|
+
KeyRemoved: Signal.Signal<TKey>,
|
|
45
|
+
|
|
46
|
+
--[=[
|
|
47
|
+
Fires when a key value changes, including add and remove.
|
|
48
|
+
@readonly
|
|
49
|
+
@prop KeyValueChanged Signal<(TKey, TValue?, TValue?)>
|
|
50
|
+
@within ObservableMap
|
|
51
|
+
]=]
|
|
52
|
+
KeyValueChanged: Signal.Signal<(TKey, TValue?, TValue?)>,
|
|
53
|
+
|
|
54
|
+
--[=[
|
|
55
|
+
Fires when the count changes.
|
|
56
|
+
@prop CountChanged Signal.Signal<number>
|
|
57
|
+
@within ObservableMap
|
|
58
|
+
]=]
|
|
59
|
+
CountChanged: Signal.Signal<number>,
|
|
60
|
+
},
|
|
61
|
+
ObservableMap
|
|
62
|
+
))
|
|
63
|
+
|
|
21
64
|
--[=[
|
|
22
65
|
Constructs a new ObservableMap
|
|
23
66
|
@return ObservableMap<TKey, TValue>
|
|
24
67
|
]=]
|
|
25
|
-
function ObservableMap.new()
|
|
26
|
-
local self = setmetatable({}, ObservableMap)
|
|
68
|
+
function ObservableMap.new<TKey, TValue>(): ObservableMap<TKey, TValue>
|
|
69
|
+
local self: any = setmetatable({} :: any, ObservableMap)
|
|
27
70
|
|
|
28
71
|
self._maid = Maid.new()
|
|
29
72
|
self._map = {}
|
|
@@ -31,35 +74,9 @@ function ObservableMap.new()
|
|
|
31
74
|
self._keySubTable = self._maid:Add(ObservableSubscriptionTable.new())
|
|
32
75
|
self._countValue = self._maid:Add(ValueObject.new(0, "number"))
|
|
33
76
|
|
|
34
|
-
--[=[
|
|
35
|
-
Fires when a key is added
|
|
36
|
-
@readonly
|
|
37
|
-
@prop KeyAdded Signal<TKey>
|
|
38
|
-
@within ObservableMap
|
|
39
|
-
]=]
|
|
40
77
|
self.KeyAdded = self._maid:Add(Signal.new()) -- :Fire(key, value)
|
|
41
|
-
|
|
42
|
-
--[=[
|
|
43
|
-
Fires when a key is removed
|
|
44
|
-
@readonly
|
|
45
|
-
@prop KeyRemoved Signal<TKey>
|
|
46
|
-
@within ObservableMap
|
|
47
|
-
]=]
|
|
48
78
|
self.KeyRemoved = self._maid:Add(Signal.new()) -- :Fire(key)
|
|
49
|
-
|
|
50
|
-
--[=[
|
|
51
|
-
Fires when a key value changes, including add and remove.
|
|
52
|
-
@readonly
|
|
53
|
-
@prop KeyValueChanged Signal<(TKey, TValue, TValue)>
|
|
54
|
-
@within ObservableMap
|
|
55
|
-
]=]
|
|
56
79
|
self.KeyValueChanged = self._maid:Add(Signal.new()) -- :Fire(key, value, oldValue)
|
|
57
|
-
|
|
58
|
-
--[=[
|
|
59
|
-
Fires when the count changes.
|
|
60
|
-
@prop CountChanged RBXScriptSignal
|
|
61
|
-
@within ObservableMap
|
|
62
|
-
]=]
|
|
63
80
|
self.CountChanged = self._countValue.Changed
|
|
64
81
|
|
|
65
82
|
return self
|
|
@@ -70,7 +87,7 @@ end
|
|
|
70
87
|
@param value any
|
|
71
88
|
@return boolean
|
|
72
89
|
]=]
|
|
73
|
-
function ObservableMap.isObservableMap(value)
|
|
90
|
+
function ObservableMap.isObservableMap(value: any): boolean
|
|
74
91
|
return DuckTypeUtils.isImplementation(ObservableMap, value)
|
|
75
92
|
end
|
|
76
93
|
|
|
@@ -79,70 +96,74 @@ end
|
|
|
79
96
|
|
|
80
97
|
@return (T) -> ((T, nextIndex: any) -> ...any, T?)
|
|
81
98
|
]=]
|
|
82
|
-
function ObservableMap
|
|
99
|
+
function ObservableMap.__iter<TKey, TValue>(self: ObservableMap<TKey, TValue>): ...any
|
|
83
100
|
return pairs(self._map)
|
|
84
101
|
end
|
|
85
102
|
|
|
86
|
-
|
|
87
103
|
--[=[
|
|
88
104
|
Observes all keys in the map
|
|
89
105
|
@return Observable<Brio<TKey>>
|
|
90
106
|
]=]
|
|
91
|
-
function ObservableMap
|
|
92
|
-
return self:_observeKeyValueChanged(function(key, _value)
|
|
107
|
+
function ObservableMap.ObserveKeysBrio<TKey, TValue>(self: ObservableMap<TKey, TValue>): Observable.Observable<Brio.Brio<TKey>>
|
|
108
|
+
return self:_observeKeyValueChanged(function(key: TKey, _value: TValue)
|
|
93
109
|
return Brio.new(key)
|
|
94
|
-
end)
|
|
110
|
+
end) :: any
|
|
95
111
|
end
|
|
96
112
|
|
|
97
113
|
--[=[
|
|
98
114
|
Observes all keys in the map
|
|
99
115
|
@return Observable<Brio<TKey>>
|
|
100
116
|
]=]
|
|
101
|
-
function ObservableMap
|
|
102
|
-
return self:_observeKeyValueChanged(function(_key, value)
|
|
117
|
+
function ObservableMap.ObserveValuesBrio<TKey, TValue>(self: ObservableMap<TKey, TValue>): Observable.Observable<Brio.Brio<TValue>>
|
|
118
|
+
return self:_observeKeyValueChanged(function(_key: TKey, value: TValue)
|
|
103
119
|
return Brio.new(value)
|
|
104
|
-
end)
|
|
120
|
+
end) :: any
|
|
105
121
|
end
|
|
106
122
|
|
|
107
123
|
--[=[
|
|
108
124
|
Observes all keys in the map
|
|
109
125
|
@return Observable<Brio<(TKey, TValue)>>
|
|
110
126
|
]=]
|
|
111
|
-
function ObservableMap
|
|
112
|
-
|
|
127
|
+
function ObservableMap.ObservePairsBrio<TKey, TValue>(
|
|
128
|
+
self: ObservableMap<TKey, TValue>
|
|
129
|
+
): Observable.Observable<Brio.Brio<(TKey, TValue)>>
|
|
130
|
+
return self:_observeKeyValueChanged(function(key: TKey, value: TValue)
|
|
113
131
|
return Brio.new(key, value)
|
|
114
132
|
end)
|
|
115
133
|
end
|
|
116
134
|
|
|
117
|
-
function ObservableMap
|
|
135
|
+
function ObservableMap._observeKeyValueChanged<TKey, TValue>(
|
|
136
|
+
self: ObservableMap<TKey, TValue>,
|
|
137
|
+
packValue: (TKey, TValue) -> any
|
|
138
|
+
): Observable.Observable<Brio.Brio<(TKey, TValue)>>
|
|
118
139
|
return Observable.new(function(sub)
|
|
119
140
|
local maid = Maid.new()
|
|
120
141
|
|
|
121
|
-
local function handleValue(key, value)
|
|
142
|
+
local function handleValue(key: TKey, value: TValue?, _oldValue: TValue?)
|
|
122
143
|
if value ~= nil then
|
|
123
144
|
local brio = packValue(key, value)
|
|
124
|
-
maid[key] = brio
|
|
145
|
+
maid[key :: any] = brio
|
|
125
146
|
sub:Fire(brio)
|
|
126
147
|
else
|
|
127
|
-
maid[key] = nil
|
|
148
|
+
maid[key :: any] = nil
|
|
128
149
|
end
|
|
129
150
|
end
|
|
130
151
|
|
|
131
|
-
for key, value in
|
|
152
|
+
for key, value in self._map do
|
|
132
153
|
handleValue(key, value)
|
|
133
154
|
end
|
|
134
155
|
|
|
135
156
|
local conn = self.KeyValueChanged:Connect(handleValue)
|
|
136
157
|
|
|
137
158
|
local function cleanup()
|
|
138
|
-
self._maid[sub] = nil
|
|
159
|
+
self._maid[sub :: any] = nil
|
|
139
160
|
conn:Disconnect()
|
|
140
161
|
sub:Complete()
|
|
141
162
|
maid:Destroy()
|
|
142
163
|
end
|
|
143
|
-
self._maid[sub] = cleanup
|
|
164
|
+
self._maid[sub :: any] = cleanup
|
|
144
165
|
return cleanup
|
|
145
|
-
end)
|
|
166
|
+
end) :: any
|
|
146
167
|
end
|
|
147
168
|
|
|
148
169
|
--[=[
|
|
@@ -150,7 +171,7 @@ end
|
|
|
150
171
|
@param key TKey
|
|
151
172
|
@return TValue
|
|
152
173
|
]=]
|
|
153
|
-
function ObservableMap
|
|
174
|
+
function ObservableMap.Get<TKey, TValue>(self: ObservableMap<TKey, TValue>, key: TKey): TValue?
|
|
154
175
|
assert(key ~= nil, "Bad key")
|
|
155
176
|
|
|
156
177
|
return self._map[key]
|
|
@@ -161,7 +182,7 @@ end
|
|
|
161
182
|
@param key TKey
|
|
162
183
|
@return boolean
|
|
163
184
|
]=]
|
|
164
|
-
function ObservableMap
|
|
185
|
+
function ObservableMap.ContainsKey<TKey, TValue>(self: ObservableMap<TKey, TValue>, key: TKey): boolean
|
|
165
186
|
assert(key ~= nil, "Bad key")
|
|
166
187
|
|
|
167
188
|
return self._map[key] ~= nil
|
|
@@ -171,7 +192,7 @@ end
|
|
|
171
192
|
Gets the count of items in the set
|
|
172
193
|
@return number
|
|
173
194
|
]=]
|
|
174
|
-
function ObservableMap
|
|
195
|
+
function ObservableMap.GetCount<TKey, TValue>(self: ObservableMap<TKey, TValue>): number
|
|
175
196
|
return self._countValue.Value or 0
|
|
176
197
|
end
|
|
177
198
|
|
|
@@ -182,7 +203,7 @@ ObservableMap.__len = ObservableMap.GetCount
|
|
|
182
203
|
|
|
183
204
|
@return Observable<number>
|
|
184
205
|
]=]
|
|
185
|
-
function ObservableMap
|
|
206
|
+
function ObservableMap.ObserveCount<TKey, TValue>(self: ObservableMap<TKey, TValue>): Observable.Observable<number>
|
|
186
207
|
return self._countValue:Observe()
|
|
187
208
|
end
|
|
188
209
|
|
|
@@ -192,14 +213,17 @@ end
|
|
|
192
213
|
@param key TKey
|
|
193
214
|
@return Observable<Brio<TValue>>
|
|
194
215
|
]=]
|
|
195
|
-
function ObservableMap
|
|
216
|
+
function ObservableMap.ObserveAtKeyBrio<TKey, TValue>(
|
|
217
|
+
self: ObservableMap<TKey, TValue>,
|
|
218
|
+
key: TKey
|
|
219
|
+
): Observable.Observable<Brio.Brio<TValue>>
|
|
196
220
|
assert(key ~= nil, "Bad key")
|
|
197
221
|
|
|
198
222
|
return self:ObserveAtKey(key):Pipe({
|
|
199
223
|
RxBrioUtils.switchToBrio(function(value)
|
|
200
224
|
return value ~= nil
|
|
201
|
-
end)
|
|
202
|
-
})
|
|
225
|
+
end),
|
|
226
|
+
}) :: any
|
|
203
227
|
end
|
|
204
228
|
|
|
205
229
|
--[=[
|
|
@@ -208,12 +232,12 @@ end
|
|
|
208
232
|
@param key TKey
|
|
209
233
|
@return Observable<TValue?>
|
|
210
234
|
]=]
|
|
211
|
-
function ObservableMap
|
|
235
|
+
function ObservableMap.ObserveAtKey<TKey, TValue>(self: ObservableMap<TKey, TValue>, key: TKey): Observable.Observable<TValue?>
|
|
212
236
|
assert(key ~= nil, "Bad key")
|
|
213
237
|
|
|
214
238
|
return self._keySubTable:Observe(key, function(sub)
|
|
215
|
-
sub:Fire(self._map[key])
|
|
216
|
-
end)
|
|
239
|
+
sub:Fire(self._map[key] :: any)
|
|
240
|
+
end) :: any
|
|
217
241
|
end
|
|
218
242
|
|
|
219
243
|
--[=[
|
|
@@ -232,25 +256,23 @@ ObservableMap.ObserveValueForKey = ObservableMap.ObserveAtKey
|
|
|
232
256
|
@param value TValue?
|
|
233
257
|
@return callback -- Call to remove the value if it was added
|
|
234
258
|
]=]
|
|
235
|
-
function ObservableMap
|
|
259
|
+
function ObservableMap.Set<TKey, TValue>(self: ObservableMap<TKey, TValue>, key: TKey, value: TValue?): () -> ()
|
|
236
260
|
assert(key ~= nil, "Bad key")
|
|
237
261
|
|
|
238
|
-
local oldValue = self._map[key]
|
|
262
|
+
local oldValue: TValue? = self._map[key]
|
|
239
263
|
if oldValue == value then
|
|
240
264
|
-- no removal since we never added. this is a tad messy.
|
|
241
|
-
return function()
|
|
242
|
-
|
|
243
|
-
end
|
|
265
|
+
return function() end
|
|
244
266
|
end
|
|
245
267
|
|
|
246
|
-
self._map[key] = value
|
|
268
|
+
self._map[key] = value :: any
|
|
247
269
|
|
|
248
|
-
if
|
|
249
|
-
self._countValue.Value = self._countValue.Value + 1
|
|
250
|
-
self.KeyAdded:Fire(key, value)
|
|
251
|
-
elseif value == nil then
|
|
270
|
+
if value == nil then
|
|
252
271
|
self._countValue.Value = self._countValue.Value - 1
|
|
253
272
|
self.KeyRemoved:Fire(key)
|
|
273
|
+
elseif oldValue == nil then
|
|
274
|
+
self._countValue.Value = self._countValue.Value + 1
|
|
275
|
+
self.KeyAdded:Fire(key, value)
|
|
254
276
|
end
|
|
255
277
|
|
|
256
278
|
self.KeyValueChanged:Fire(key, value, oldValue)
|
|
@@ -259,7 +281,7 @@ function ObservableMap:Set(key, value)
|
|
|
259
281
|
return self:_getRemovalCallback(key, value)
|
|
260
282
|
end
|
|
261
283
|
|
|
262
|
-
function ObservableMap
|
|
284
|
+
function ObservableMap._getRemovalCallback<TKey, TValue>(self: ObservableMap<TKey, TValue>, key: TKey, value: TValue?): () -> ()
|
|
263
285
|
return function()
|
|
264
286
|
if not self.Destroy then
|
|
265
287
|
return
|
|
@@ -275,7 +297,7 @@ end
|
|
|
275
297
|
Removes the item from the map if it exists.
|
|
276
298
|
@param key TKey
|
|
277
299
|
]=]
|
|
278
|
-
function ObservableMap
|
|
300
|
+
function ObservableMap.Remove<TKey, TValue>(self: ObservableMap<TKey, TValue>, key: TKey): ()
|
|
279
301
|
assert(key ~= nil, "Bad key")
|
|
280
302
|
|
|
281
303
|
self:Set(key, nil)
|
|
@@ -285,9 +307,9 @@ end
|
|
|
285
307
|
Gets a list of all values.
|
|
286
308
|
@return { TValue }
|
|
287
309
|
]=]
|
|
288
|
-
function ObservableMap
|
|
310
|
+
function ObservableMap.GetValueList<TKey, TValue>(self: ObservableMap<TKey, TValue>): { TValue }
|
|
289
311
|
local list = table.create(self._countValue.Value)
|
|
290
|
-
for _, value in
|
|
312
|
+
for _, value in self._map do
|
|
291
313
|
table.insert(list, value)
|
|
292
314
|
end
|
|
293
315
|
return list
|
|
@@ -297,9 +319,9 @@ end
|
|
|
297
319
|
Gets a list of all keys.
|
|
298
320
|
@return { TKey }
|
|
299
321
|
]=]
|
|
300
|
-
function ObservableMap
|
|
322
|
+
function ObservableMap.GetKeyList<TKey, TValue>(self: ObservableMap<TKey, TValue>): { TKey }
|
|
301
323
|
local list = table.create(self._countValue.Value)
|
|
302
|
-
for key, _ in
|
|
324
|
+
for key, _ in self._map do
|
|
303
325
|
table.insert(list, key)
|
|
304
326
|
end
|
|
305
327
|
return list
|
|
@@ -309,13 +331,13 @@ end
|
|
|
309
331
|
Observes the list of all keys.
|
|
310
332
|
@return Observable<{ TKey }>
|
|
311
333
|
]=]
|
|
312
|
-
function ObservableMap
|
|
334
|
+
function ObservableMap.ObserveKeyList<TKey, TValue>(self: ObservableMap<TKey, TValue>): Observable.Observable<{ TKey }>
|
|
313
335
|
return Observable.new(function(sub)
|
|
314
336
|
local topMaid = Maid.new()
|
|
315
337
|
|
|
316
338
|
-- TODO: maybe don't allocate as much here?
|
|
317
339
|
local keyList = table.create(self._countValue.Value)
|
|
318
|
-
for key, _ in
|
|
340
|
+
for key, _ in self._map do
|
|
319
341
|
table.insert(keyList, key)
|
|
320
342
|
end
|
|
321
343
|
|
|
@@ -335,15 +357,15 @@ function ObservableMap:ObserveKeyList()
|
|
|
335
357
|
sub:Fire(table.clone(keyList))
|
|
336
358
|
|
|
337
359
|
return topMaid
|
|
338
|
-
end)
|
|
360
|
+
end) :: any
|
|
339
361
|
end
|
|
340
362
|
|
|
341
363
|
--[=[
|
|
342
364
|
Cleans up the ObservableMap and sets the metatable to nil.
|
|
343
365
|
]=]
|
|
344
|
-
function ObservableMap
|
|
366
|
+
function ObservableMap.Destroy<TKey, TValue>(self: ObservableMap<TKey, TValue>)
|
|
345
367
|
self._maid:DoCleaning()
|
|
346
|
-
setmetatable(self, nil)
|
|
368
|
+
setmetatable(self :: any, nil)
|
|
347
369
|
end
|
|
348
370
|
|
|
349
371
|
return ObservableMap
|
|
@@ -299,12 +299,12 @@ end
|
|
|
299
299
|
@param index number
|
|
300
300
|
@return ObservableList<TValue>
|
|
301
301
|
]=]
|
|
302
|
-
function ObservableMapList:GetListOfValuesAtListIndex(index)
|
|
302
|
+
function ObservableMapList:GetListOfValuesAtListIndex(index: number)
|
|
303
303
|
assert(type(index) == "number", "Bad index")
|
|
304
304
|
|
|
305
305
|
local list = table.create(self._observableMapOfLists:GetCount())
|
|
306
306
|
|
|
307
|
-
for _, observableList in
|
|
307
|
+
for _, observableList in self._observableMapOfLists:GetValueList() do
|
|
308
308
|
local value = observableList:Get(index)
|
|
309
309
|
if value ~= nil then
|
|
310
310
|
table.insert(list, value)
|