@quenty/flipbook 9.17.0 → 9.17.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 CHANGED
@@ -3,6 +3,17 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ ## [9.17.1](https://github.com/Quenty/NevermoreEngine/compare/@quenty/flipbook@9.17.0...@quenty/flipbook@9.17.1) (2025-04-05)
7
+
8
+
9
+ ### Bug Fixes
10
+
11
+ * Add types to packages ([2374fb2](https://github.com/Quenty/NevermoreEngine/commit/2374fb2b043cfbe0e9b507b3316eec46a4e353a0))
12
+
13
+
14
+
15
+
16
+
6
17
  # [9.17.0](https://github.com/Quenty/NevermoreEngine/compare/@quenty/flipbook@9.16.2...@quenty/flipbook@9.17.0) (2025-04-02)
7
18
 
8
19
  **Note:** Version bump only for package @quenty/flipbook
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@quenty/flipbook",
3
- "version": "9.17.0",
3
+ "version": "9.17.1",
4
4
  "description": "Handles playing back animated spritesheets",
5
5
  "keywords": [
6
6
  "Roblox",
@@ -25,19 +25,19 @@
25
25
  "Quenty"
26
26
  ],
27
27
  "dependencies": {
28
- "@quenty/baseobject": "^10.8.0",
29
- "@quenty/ducktype": "^5.8.1",
30
- "@quenty/instanceutils": "^13.17.0",
31
- "@quenty/loader": "^10.8.0",
32
- "@quenty/maid": "^3.4.0",
33
- "@quenty/promise": "^10.10.1",
34
- "@quenty/rx": "^13.17.0",
35
- "@quenty/sprites": "^13.16.0",
36
- "@quenty/uiobjectutils": "^6.16.0",
37
- "@quenty/valueobject": "^13.17.0"
28
+ "@quenty/baseobject": "^10.8.1",
29
+ "@quenty/ducktype": "^5.8.2",
30
+ "@quenty/instanceutils": "^13.17.1",
31
+ "@quenty/loader": "^10.8.1",
32
+ "@quenty/maid": "^3.4.1",
33
+ "@quenty/promise": "^10.10.2",
34
+ "@quenty/rx": "^13.17.1",
35
+ "@quenty/sprites": "^13.16.1",
36
+ "@quenty/uiobjectutils": "^6.16.1",
37
+ "@quenty/valueobject": "^13.17.1"
38
38
  },
39
39
  "publishConfig": {
40
40
  "access": "public"
41
41
  },
42
- "gitHead": "e8ea56930e65322fcffc05a1556d5df988068f0b"
42
+ "gitHead": "78c3ac0ab08dd18085b6e6e6e4f745e76ed99f68"
43
43
  }
@@ -1,3 +1,4 @@
1
+ --!strict
1
2
  --[=[
2
3
  A spritesheet that is animated. See [FlipbookPlayer] for playback.
3
4
  @class Flipbook
@@ -16,21 +17,42 @@ local DuckTypeUtils = require("DuckTypeUtils")
16
17
  .columns number
17
18
  .imageRectSize Vector2
18
19
  .frameRate number
19
- .restFrame number | nil -- Optional reset frame
20
+ .restFrame number? -- Optional reset frame
20
21
  @within Flipbook
21
22
  ]=]
23
+ export type FlipbookData = {
24
+ image: string,
25
+ frameCount: number,
26
+ rows: number,
27
+ columns: number,
28
+ imageRectSize: Vector2,
29
+ frameRate: number?,
30
+ restFrame: number?,
31
+ }
22
32
 
23
33
  local Flipbook = {}
24
34
  Flipbook.ClassName = "Flipbook"
25
35
  Flipbook.__index = Flipbook
26
36
 
37
+ export type Flipbook = typeof(setmetatable(
38
+ {} :: {
39
+ _frameSprites: { [number]: Sprite.Sprite? },
40
+ _frameCount: number,
41
+ _frameRate: number,
42
+ _imageRectSize: Vector2,
43
+ _restFrame: number?,
44
+ _imageId: string,
45
+ },
46
+ Flipbook
47
+ ))
48
+
27
49
  --[=[
28
50
  Constructs a new Flipbook
29
51
  @param data FlipbookData
30
52
  @return Flipbook
31
53
  ]=]
32
- function Flipbook.new(data)
33
- local self = setmetatable({}, Flipbook)
54
+ function Flipbook.new(data: FlipbookData): Flipbook
55
+ local self: Flipbook = setmetatable({} :: any, Flipbook)
34
56
 
35
57
  self._frameSprites = {}
36
58
  self._frameRate = 60
@@ -44,7 +66,7 @@ function Flipbook.new(data)
44
66
  assert(data.columns, "Bad columns")
45
67
  assert(data.rows, "Bad rows")
46
68
 
47
- self:SetFrameCount(data.rows*data.columns)
69
+ self:SetFrameCount(data.rows * data.columns)
48
70
  end
49
71
 
50
72
  if data.frameRate then
@@ -62,73 +84,76 @@ function Flipbook.new(data)
62
84
  return self
63
85
  end
64
86
 
65
- function Flipbook.isFlipbook(value)
87
+ function Flipbook.isFlipbook(value: any): boolean
66
88
  return DuckTypeUtils.isImplementation(Flipbook, value)
67
89
  end
68
90
 
69
- function Flipbook:_loadFrames(image, columns, imageRectSize)
91
+ function Flipbook._loadFrames(self: Flipbook, image: string, columns: number, imageRectSize: Vector2)
70
92
  assert(type(columns) == "number", "Bad columns")
71
93
  assert(typeof(imageRectSize) == "Vector2", "Bad imageRectSize")
72
94
 
73
95
  self:SetImageRectSize(imageRectSize)
74
96
 
75
- for i=0, self._frameCount do
97
+ for i = 0, self._frameCount do
76
98
  local x = i % columns
77
99
  local y = math.floor(i / columns)
78
- local position = imageRectSize*Vector2.new(x, y)
100
+ local position = imageRectSize * Vector2.new(x, y)
79
101
 
80
102
  local index = i + 1
81
103
  local name = string.format("Frame_%d", index)
82
104
 
83
- self:SetSpriteAtIndex(index, Sprite.new({
84
- Texture = image;
85
- Size = imageRectSize;
86
- Position = position;
87
- Name = name;
88
- }))
105
+ self:SetSpriteAtIndex(
106
+ index,
107
+ Sprite.new({
108
+ Texture = image,
109
+ Size = imageRectSize,
110
+ Position = position,
111
+ Name = name,
112
+ })
113
+ )
89
114
  end
90
115
  end
91
116
 
92
- function Flipbook:GetRestFrame()
117
+ function Flipbook.GetRestFrame(self: Flipbook): number?
93
118
  return self._restFrame
94
119
  end
95
120
 
96
- function Flipbook:SetSpriteAtIndex(index, sprite)
121
+ function Flipbook.SetSpriteAtIndex(self: Flipbook, index: number, sprite: Sprite.Sprite)
97
122
  assert(type(index) == "number", "Bad index")
98
123
  assert(type(sprite) == "table", "Bad sprite")
99
124
 
100
125
  self._frameSprites[index] = sprite
101
126
  end
102
127
 
103
- function Flipbook:SetImageRectSize(imageRectSize)
128
+ function Flipbook.SetImageRectSize(self: Flipbook, imageRectSize: Vector2)
104
129
  assert(typeof(imageRectSize) == "Vector2", "No imageRectSize")
105
130
 
106
131
  self._imageRectSize = imageRectSize
107
132
  end
108
133
 
109
- function Flipbook:SetFrameCount(frameCount)
134
+ function Flipbook.SetFrameCount(self: Flipbook, frameCount: number)
110
135
  assert(type(frameCount) == "number", "Bad frameCount")
111
136
 
112
137
  self._frameCount = frameCount
113
138
  end
114
139
 
115
- function Flipbook:SetFrameRate(frameRate)
140
+ function Flipbook.SetFrameRate(self: Flipbook, frameRate: number)
116
141
  assert(type(frameRate) == "number", "Bad frameRate")
117
142
 
118
143
  self._frameRate = frameRate
119
144
  end
120
145
 
121
- function Flipbook:GetPreloadAssetId()
146
+ function Flipbook.GetPreloadAssetId(self: Flipbook): { string }
122
147
  return { self._imageId }
123
148
  end
124
149
 
125
- function Flipbook:GetSprite(index)
150
+ function Flipbook.GetSprite(self: Flipbook, index: number): Sprite.Sprite?
126
151
  assert(type(index) == "number", "Bad index")
127
152
 
128
153
  return self._frameSprites[index]
129
154
  end
130
155
 
131
- function Flipbook:HasSprite(index)
156
+ function Flipbook.HasSprite(self: Flipbook, index: number): boolean
132
157
  assert(type(index) == "number", "Bad index")
133
158
 
134
159
  return self._frameSprites[index] ~= nil
@@ -138,7 +163,7 @@ end
138
163
  Gets the sprite size
139
164
  @return Vector2
140
165
  ]=]
141
- function Flipbook:GetImageRectSize()
166
+ function Flipbook.GetImageRectSize(self: Flipbook): Vector2
142
167
  return self._imageRectSize
143
168
  end
144
169
 
@@ -146,7 +171,7 @@ end
146
171
  Gets the frames per a second
147
172
  @return number
148
173
  ]=]
149
- function Flipbook:GetFrameRate()
174
+ function Flipbook.GetFrameRate(self: Flipbook): number
150
175
  return self._frameRate
151
176
  end
152
177
 
@@ -154,15 +179,15 @@ end
154
179
  Gets the play time for the animated sheet
155
180
  @return number
156
181
  ]=]
157
- function Flipbook:GetPlayTime()
158
- return self._frameCount/self._frameRate
182
+ function Flipbook.GetPlayTime(self: Flipbook): number
183
+ return self._frameCount / self._frameRate
159
184
  end
160
185
 
161
186
  --[=[
162
187
  Retrieves the frames for the sprite sheet.
163
- @return frames
188
+ @return number
164
189
  ]=]
165
- function Flipbook:GetFrameCount()
190
+ function Flipbook.GetFrameCount(self: Flipbook): number
166
191
  return self._frameCount
167
192
  end
168
193
 
@@ -6,6 +6,7 @@
6
6
  local require = require(script.Parent.loader).load(script)
7
7
 
8
8
  local Flipbook = require("Flipbook")
9
+ local _ServiceBag = require("ServiceBag")
9
10
 
10
11
  local FlipbookLibrary = {}
11
12
  FlipbookLibrary.__index = FlipbookLibrary
@@ -23,7 +24,7 @@ function FlipbookLibrary.new(serviceName, register)
23
24
  return self
24
25
  end
25
26
 
26
- function FlipbookLibrary:Init(serviceBag)
27
+ function FlipbookLibrary:Init(serviceBag: _ServiceBag.ServiceBag)
27
28
  assert(self ~= FlipbookLibrary, "Should construct new FlipbookLibrary")
28
29
  assert(not self._spritesheets, "Already initialized")
29
30
  self._serviceBag = assert(serviceBag, "No serviceBag")
@@ -37,7 +38,7 @@ function FlipbookLibrary:GetPreloadAssetIds()
37
38
  assert(self._spritesheets, "Not initialized")
38
39
 
39
40
  local assets = {}
40
- for _, sheet in pairs(self._spritesheets) do
41
+ for _, sheet in self._spritesheets do
41
42
  table.insert(assets, sheet:GetPreloadAssetId())
42
43
  end
43
44
  return assets
@@ -1,3 +1,4 @@
1
+ --!strict
1
2
  --[=[
2
3
  Plays an [Flipbook] on a given imagelabel.
3
4
  @class FlipbookPlayer
@@ -13,42 +14,70 @@ local Maid = require("Maid")
13
14
  local Promise = require("Promise")
14
15
  local Rx = require("Rx")
15
16
  local ValueObject = require("ValueObject")
17
+ local _Observable = require("Observable")
16
18
 
17
19
  local FlipbookPlayer = setmetatable({}, BaseObject)
18
20
  FlipbookPlayer.ClassName = "FlipbookPlayer"
19
21
  FlipbookPlayer.__index = FlipbookPlayer
20
22
 
23
+ type PlayData = {
24
+ startTime: number,
25
+ times: number,
26
+ }
27
+
28
+ export type FlipbookPlayer = typeof(setmetatable(
29
+ {} :: {
30
+ _obj: ImageLabel | ImageButton,
31
+ _maid: Maid.Maid,
32
+ _isPlaying: ValueObject.ValueObject<boolean>,
33
+ _isBoomarang: ValueObject.ValueObject<boolean>,
34
+ _playData: ValueObject.ValueObject<PlayData>,
35
+ _flipbook: ValueObject.ValueObject<Flipbook.Flipbook>,
36
+
37
+ _originalImage: string,
38
+ _originalRectOffset: UDim2,
39
+ _originalRectSize: UDim2,
40
+ },
41
+ { __index = FlipbookPlayer}
42
+ ))
43
+
44
+ type State = {
45
+ flipbook: Flipbook.Flipbook?,
46
+ playData: PlayData?,
47
+ }
48
+
21
49
  --[=[
22
50
  Constructs a new FlipbookPlayer
23
51
 
24
- @param imageLabel ImageLabel
52
+ @param imageLabel ImageLabel | ImageButton
25
53
  @return FlipbookPlayer
26
54
  ]=]
27
- function FlipbookPlayer.new(imageLabel)
28
- local self = setmetatable(BaseObject.new(imageLabel), FlipbookPlayer)
55
+ function FlipbookPlayer.new(imageLabel: ImageLabel | ImageButton): FlipbookPlayer
56
+ local self: FlipbookPlayer = setmetatable(BaseObject.new(imageLabel) :: any, FlipbookPlayer)
29
57
 
30
- assert(typeof(self._obj) == "Instance" and (self._obj:IsA("ImageLabel") or self._obj:IsA("ImageButton")), "Bad imageLabel")
58
+ assert(
59
+ typeof(self._obj) == "Instance" and (self._obj:IsA("ImageLabel") or self._obj:IsA("ImageButton")),
60
+ "Bad imageLabel"
61
+ )
31
62
 
32
63
  self._isPlaying = self._maid:Add(ValueObject.new(false, "boolean"))
33
-
34
64
  self._isBoomarang = self._maid:Add(ValueObject.new(false, "boolean"))
35
-
36
65
  self._playData = self._maid:Add(ValueObject.new(nil))
37
-
38
66
  self._flipbook = self._maid:Add(ValueObject.new(nil))
39
67
 
40
- self._originalImage = self._obj.Image
41
- self._originalRectOffset = self._obj.ImageRectOffset
42
- self._originalRectSize = self._obj.ImageRectSize
68
+ local obj: any = self._obj
69
+ self._originalImage = obj.Image
70
+ self._originalRectOffset = obj.ImageRectOffset
71
+ self._originalRectSize = obj.ImageRectSize
43
72
 
44
73
  self._maid:GiveTask(Rx.combineLatest({
45
- playData = self._playData:Observe();
46
- flipbook = self._flipbook:Observe();
74
+ playData = self._playData:Observe(),
75
+ flipbook = self._flipbook:Observe(),
47
76
  }):Subscribe(function(state)
48
77
  if state.flipbook then
49
78
  if state.playData then
50
79
  self._isPlaying.Value = true
51
- self._maid._playing = self:_execPlay(state.flipbook, state.playData)
80
+ self._maid._playing = self:_execPlay(state.flipbook, state.playData :: any)
52
81
  else
53
82
  self._isPlaying.Value = false
54
83
  self._maid._playing = nil
@@ -57,16 +86,16 @@ function FlipbookPlayer.new(imageLabel)
57
86
  if restFrame then
58
87
  self:_updateToFrame(state.flipbook, restFrame)
59
88
  else
60
- self._obj.Image = self._originalImage
61
- self._obj.ImageRectOffset = self._originalRectOffset
62
- self._obj.ImageRectSize = self._originalRectSize
89
+ obj.Image = self._originalImage
90
+ obj.ImageRectOffset = self._originalRectOffset
91
+ obj.ImageRectSize = self._originalRectSize
63
92
  end
64
93
  end
65
94
  else
66
95
  self._isPlaying.Value = false
67
- self._obj.Image = self._originalImage
68
- self._obj.ImageRectOffset = self._originalRectOffset
69
- self._obj.ImageRectSize = self._originalRectSize
96
+ obj.Image = self._originalImage
97
+ obj.ImageRectOffset = self._originalRectOffset
98
+ obj.ImageRectSize = self._originalRectSize
70
99
  end
71
100
  end))
72
101
 
@@ -77,7 +106,7 @@ end
77
106
  Sets the current sheet and starts play if needed
78
107
  @param flipbook Flipbook
79
108
  ]=]
80
- function FlipbookPlayer:SetFlipbook(flipbook)
109
+ function FlipbookPlayer:SetFlipbook(flipbook: Flipbook.Flipbook)
81
110
  assert(Flipbook.isFlipbook(flipbook), "Bad flipbook")
82
111
 
83
112
  self._flipbook.Value = flipbook
@@ -87,7 +116,7 @@ end
87
116
  Gets the current flipbook
88
117
  @return Flipbook?
89
118
  ]=]
90
- function FlipbookPlayer:GetFlipbook()
119
+ function FlipbookPlayer:GetFlipbook(): Flipbook.Flipbook?
91
120
  return self._flipbook.Value
92
121
  end
93
122
 
@@ -96,7 +125,7 @@ end
96
125
 
97
126
  @return Promise
98
127
  ]=]
99
- function FlipbookPlayer:PromisePlayOnce()
128
+ function FlipbookPlayer:PromisePlayOnce(): Promise.Promise<()>
100
129
  return self:PromisePlayRepeat(1)
101
130
  end
102
131
 
@@ -106,12 +135,12 @@ end
106
135
  @param times number
107
136
  @return Promise
108
137
  ]=]
109
- function FlipbookPlayer:PromisePlayRepeat(times)
138
+ function FlipbookPlayer:PromisePlayRepeat(times: number): Promise.Promise<()>
110
139
  assert(type(times) == "number", "Bad times")
111
140
 
112
- local data = {
113
- startTime = os.clock();
114
- times = times;
141
+ local data: PlayData = {
142
+ startTime = os.clock(),
143
+ times = times,
115
144
  }
116
145
 
117
146
  self._playData.Value = data
@@ -124,7 +153,7 @@ end
124
153
 
125
154
  @param isBoomarang boolean
126
155
  ]=]
127
- function FlipbookPlayer:SetIsBoomarang(isBoomarang)
156
+ function FlipbookPlayer:SetIsBoomarang(isBoomarang: boolean)
128
157
  assert(type(isBoomarang) == "boolean", "Bad isBoomarang")
129
158
 
130
159
  self._isBoomarang.Value = isBoomarang
@@ -133,17 +162,17 @@ end
133
162
  --[=[
134
163
  Plays the flipbook indefinitely
135
164
  ]=]
136
- function FlipbookPlayer:Play()
165
+ function FlipbookPlayer:Play(): ()
137
166
  self._playData.Value = {
138
- startTime = 0; -- Synchronize with other variants
139
- times = math.huge;
167
+ startTime = 0, -- Synchronize with other variants
168
+ times = math.huge,
140
169
  }
141
170
  end
142
171
 
143
172
  --[=[
144
173
  Stops the flipbook
145
174
  ]=]
146
- function FlipbookPlayer:Stop()
175
+ function FlipbookPlayer:Stop(): ()
147
176
  self._playData.Value = nil
148
177
  end
149
178
 
@@ -151,7 +180,7 @@ end
151
180
  Returns true if the flipbook is playing
152
181
  @return boolean
153
182
  ]=]
154
- function FlipbookPlayer:IsPlaying()
183
+ function FlipbookPlayer:IsPlaying(): boolean
155
184
  return self._isPlaying.Value
156
185
  end
157
186
 
@@ -159,11 +188,11 @@ end
159
188
  Observes if the flipbook is playing
160
189
  @return Observable<boolean>
161
190
  ]=]
162
- function FlipbookPlayer:ObserveIsPlaying()
191
+ function FlipbookPlayer:ObserveIsPlaying(): _Observable.Observable<boolean>
163
192
  return self._isPlaying:Observe()
164
193
  end
165
194
 
166
- function FlipbookPlayer:_promiseDonePlaying(data)
195
+ function FlipbookPlayer:_promiseDonePlaying(data: { any }): Promise.Promise<()>
167
196
  assert(type(data) == "table", "Bad data")
168
197
 
169
198
  local maid = Maid.new()
@@ -191,7 +220,7 @@ function FlipbookPlayer:_promiseDonePlaying(data)
191
220
  return promise
192
221
  end
193
222
 
194
- function FlipbookPlayer:_execPlay(flipbook, playData)
223
+ function FlipbookPlayer:_execPlay(flipbook: Flipbook.Flipbook, playData: PlayData): Maid.Maid
195
224
  assert(type(playData) == "table", "Bad playData")
196
225
  assert(type(playData.startTime) == "number", "Bad playData.startTime")
197
226
 
@@ -205,21 +234,21 @@ function FlipbookPlayer:_execPlay(flipbook, playData)
205
234
  return maid
206
235
  end
207
236
 
208
- function FlipbookPlayer:_computeFrameCount(originalFrameCount, isBoomarang)
237
+ function FlipbookPlayer:_computeFrameCount(originalFrameCount: number, isBoomarang: boolean): number
209
238
  if isBoomarang then
210
- return 2*originalFrameCount - 2
239
+ return 2 * originalFrameCount - 2
211
240
  else
212
241
  return originalFrameCount
213
242
  end
214
243
  end
215
244
 
216
- function FlipbookPlayer:_update(flipbook, currentTime, playData)
245
+ function FlipbookPlayer:_update(flipbook: Flipbook.Flipbook, currentTime: number, playData: PlayData)
217
246
  local isBoomarang = self._isBoomarang.Value
218
- local fps = flipbook:GetFrameRate()
219
- local originalFrameCount = flipbook:GetFrameCount()
247
+ local fps: number = flipbook:GetFrameRate()
248
+ local originalFrameCount: number = flipbook:GetFrameCount()
220
249
 
221
- local frameCount = self:_computeFrameCount(originalFrameCount, isBoomarang)
222
- local frame = (math.floor((currentTime - playData.startTime)*fps)%frameCount) + 1
250
+ local frameCount: number = self:_computeFrameCount(originalFrameCount, isBoomarang)
251
+ local frame: number = (math.floor((currentTime - playData.startTime) * fps) % frameCount) + 1
223
252
 
224
253
  if isBoomarang then
225
254
  if frame > originalFrameCount then
@@ -231,11 +260,11 @@ function FlipbookPlayer:_update(flipbook, currentTime, playData)
231
260
  if playData.times ~= math.huge then
232
261
  local executeFrameCount = originalFrameCount
233
262
  if isBoomarang then
234
- executeFrameCount = 2*originalFrameCount - 1
263
+ executeFrameCount = 2 * originalFrameCount - 1
235
264
  end
236
265
 
237
266
  local elapsed = os.clock() - playData.startTime
238
- local totalPlayTimeAllowed = playData.times*executeFrameCount/fps
267
+ local totalPlayTimeAllowed = playData.times * executeFrameCount / fps
239
268
 
240
269
  if elapsed > totalPlayTimeAllowed then
241
270
  isOver = true
@@ -250,7 +279,7 @@ function FlipbookPlayer:_update(flipbook, currentTime, playData)
250
279
  end
251
280
  end
252
281
 
253
- function FlipbookPlayer:_updateToFrame(flipbook, frame)
282
+ function FlipbookPlayer:_updateToFrame(flipbook: Flipbook.Flipbook, frame: number)
254
283
  local sprite = flipbook:GetSprite(frame)
255
284
  if sprite then
256
285
  sprite:Style(self._obj)
@@ -9,7 +9,7 @@ local FlipbookPlayer = require("FlipbookPlayer")
9
9
  local Maid = require("Maid")
10
10
  local UICornerUtils = require("UICornerUtils")
11
11
 
12
- local function makeLabel(maid, flipbook, target, isBoomarang)
12
+ local function makeLabel(maid: Maid.Maid, flipbook: Flipbook.Flipbook, target: Instance, isBoomarang: boolean)
13
13
  local size = flipbook:GetImageRectSize()
14
14
 
15
15
  local imageLabel = Instance.new("ImageLabel")
@@ -65,7 +65,7 @@ local function makeButton(maid, flipbook, target, isBoomarang)
65
65
  return imageButton
66
66
  end
67
67
 
68
- return function(target)
68
+ return function(target: Instance)
69
69
  local maid = Maid.new()
70
70
 
71
71
  local container = Instance.new("Frame")