add gs
This commit is contained in:
+12
@@ -0,0 +1,12 @@
|
||||
--[[
|
||||
Package link auto-generated by Rotriever
|
||||
]]
|
||||
local PackageIndex = script.Parent.Parent
|
||||
|
||||
local package = PackageIndex["roblox_cryo"]["cryo"]
|
||||
|
||||
if package.ClassName == "ModuleScript" then
|
||||
return require(package)
|
||||
end
|
||||
|
||||
return package
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
--[[
|
||||
Package link auto-generated by Rotriever
|
||||
]]
|
||||
local PackageIndex = script.Parent.Parent
|
||||
|
||||
local package = PackageIndex["roblox_roact-fit-components"]["roact-fit-components"]
|
||||
|
||||
if package.ClassName == "ModuleScript" then
|
||||
return require(package)
|
||||
end
|
||||
|
||||
return package
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
--[[
|
||||
Package link auto-generated by Rotriever
|
||||
]]
|
||||
local PackageIndex = script.Parent.Parent
|
||||
|
||||
local package = PackageIndex["roblox_otter"]["otter"]
|
||||
|
||||
if package.ClassName == "ModuleScript" then
|
||||
return require(package)
|
||||
end
|
||||
|
||||
return package
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
--[[
|
||||
Package link auto-generated by Rotriever
|
||||
]]
|
||||
local PackageIndex = script.Parent.Parent
|
||||
|
||||
local package = PackageIndex["roblox_roact"]["roact"]
|
||||
|
||||
if package.ClassName == "ModuleScript" then
|
||||
return require(package)
|
||||
end
|
||||
|
||||
return package
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
return {
|
||||
-- Returns the signed distance from a point to a range. Returns 0 if the
|
||||
-- point is within the range, positive if it's below and negative if it's
|
||||
-- above.
|
||||
fromPointToRangeSigned = function(point, rangeTop, rangeSize)
|
||||
local rangeBottom = rangeTop + rangeSize
|
||||
|
||||
if point < rangeTop then
|
||||
return point - rangeTop
|
||||
elseif point > rangeBottom then
|
||||
return point - rangeBottom
|
||||
else
|
||||
return 0
|
||||
end
|
||||
end
|
||||
}
|
||||
+80
@@ -0,0 +1,80 @@
|
||||
--[[
|
||||
KeyPool provides a pool of objects suitable for use as map keys.
|
||||
|
||||
Create a new KeyPool, then call pool:get() to get a new key. Once you're done with it, call key:release().
|
||||
|
||||
Example:
|
||||
local pool = KeyPool.new("foo")
|
||||
...
|
||||
local key1 = pool:get()
|
||||
local key2 = pool:get()
|
||||
map[key1] = thing1
|
||||
map[key2] = thing2
|
||||
...
|
||||
map[key1] = nil
|
||||
key1:release()
|
||||
key1 = nil
|
||||
]]
|
||||
local Root = script:FindFirstAncestor("infinite-scroller").Parent
|
||||
local t = require(Root.t)
|
||||
|
||||
-- Forward declarations
|
||||
local KeyPool = {}
|
||||
KeyPool.__index = KeyPool
|
||||
|
||||
local Key = {}
|
||||
Key.__index = Key
|
||||
|
||||
-- This is Key.new, but we don't want to expose that publicly.
|
||||
local function newkey(pool, index)
|
||||
local key = {
|
||||
pool = pool,
|
||||
index = index,
|
||||
}
|
||||
|
||||
setmetatable(key, Key)
|
||||
return key
|
||||
end
|
||||
|
||||
-- KeyPool functions
|
||||
|
||||
function KeyPool.new(class)
|
||||
assert(t.string(class))
|
||||
|
||||
local pool = {
|
||||
class = class,
|
||||
available = {},
|
||||
limit = 0,
|
||||
count = 0,
|
||||
}
|
||||
|
||||
setmetatable(pool, KeyPool)
|
||||
return pool
|
||||
end
|
||||
|
||||
-- Get a currently unused key, or create a new one if everything is in use.
|
||||
function KeyPool:get()
|
||||
if self.count == 0 then
|
||||
self.limit = self.limit + 1
|
||||
return newkey(self, self.limit)
|
||||
end
|
||||
|
||||
local key = self.available[self.count]
|
||||
self.count = self.count - 1
|
||||
return key
|
||||
end
|
||||
|
||||
-- Key functions
|
||||
|
||||
function Key:__tostring()
|
||||
return self.pool.class .. "_" .. string.format("%02d", tostring(self.index))
|
||||
end
|
||||
|
||||
-- Return this key to the pool it came from. Whatever previously held this key should not keep the reference after
|
||||
-- calling this.
|
||||
function Key:release()
|
||||
self.pool.count = self.pool.count + 1
|
||||
self.pool.available[self.pool.count] = self
|
||||
end
|
||||
|
||||
return KeyPool
|
||||
+1
@@ -0,0 +1 @@
|
||||
return {}
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
-- Enum for specifying the leading edge of the scroller.
|
||||
local Root = script:FindFirstAncestor("infinite-scroller").Parent
|
||||
local t = require(Root.t)
|
||||
|
||||
local Orientation = {
|
||||
Up = "Orientation.Up",
|
||||
Down = "Orientation.Down",
|
||||
Left = "Orientation.Left",
|
||||
Right = "Orientation.Right",
|
||||
}
|
||||
|
||||
local metaindex = {
|
||||
isOrientation = t.union(
|
||||
t.literal(Orientation.Up),
|
||||
t.literal(Orientation.Down),
|
||||
t.literal(Orientation.Left),
|
||||
t.literal(Orientation.Right)
|
||||
)
|
||||
}
|
||||
|
||||
setmetatable(Orientation, {
|
||||
__index = function(self, key)
|
||||
return metaindex[key] or
|
||||
error(tostring(key) .. " is not a valid member of Scroller.Orientation", 2)
|
||||
end,
|
||||
__newindex = function()
|
||||
error("Scroller.Orientation is read-only", 2)
|
||||
end,
|
||||
})
|
||||
|
||||
return Orientation
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
local epsilon = 1e-15
|
||||
|
||||
return {
|
||||
nearest = function(num)
|
||||
local q, r = math.modf(num)
|
||||
if r <= -0.5 then
|
||||
return q - 1
|
||||
elseif r >= 0.5 then
|
||||
return q + 1
|
||||
else
|
||||
return q
|
||||
end
|
||||
end,
|
||||
towardsZero = function(num)
|
||||
local result, _ = math.modf(num)
|
||||
return result
|
||||
end,
|
||||
awayFromZero = function(num)
|
||||
local q, r = math.modf(num)
|
||||
if r < -epsilon then
|
||||
return q - 1
|
||||
elseif r > epsilon then
|
||||
return q + 1
|
||||
else
|
||||
return q
|
||||
end
|
||||
end,
|
||||
}
|
||||
+1365
File diff suppressed because it is too large
Load Diff
+67
@@ -0,0 +1,67 @@
|
||||
-- Find the new indicies of the trailing, anchor and leading elements.
|
||||
-- props is expected to contain itemList, the identifier function and the maximum search distance.
|
||||
-- state is expected to contain the old top, anchor and bottom indices and ids.
|
||||
return function(props, state)
|
||||
local topIndex = state.trail.index
|
||||
local topID = state.trail.id
|
||||
local anchorIndex = state.anchor.index
|
||||
local anchorID = state.anchor.id
|
||||
local bottomIndex = state.lead.index
|
||||
local bottomID = state.lead.id
|
||||
|
||||
local listSize = #props.itemList
|
||||
|
||||
-- If too much got deleted and the previous anchor index is off the bottom of the list, start the search from
|
||||
-- the bottom.
|
||||
if topIndex > listSize then
|
||||
topIndex = listSize
|
||||
end
|
||||
if anchorIndex > listSize then
|
||||
anchorIndex = listSize
|
||||
end
|
||||
if bottomIndex > listSize then
|
||||
bottomIndex = listSize
|
||||
end
|
||||
|
||||
-- No access to self:getID
|
||||
local getID = function(index)
|
||||
return props.identifier(props.itemList[index])
|
||||
end
|
||||
local topStill = getID(topIndex) == topID
|
||||
local anchorStill = getID(anchorIndex) == anchorID
|
||||
local bottomStill = getID(bottomIndex) == bottomID
|
||||
if topStill and anchorStill and bottomStill then
|
||||
-- Nothing important moved
|
||||
return topIndex, anchorIndex, bottomIndex
|
||||
end
|
||||
|
||||
local step = 0
|
||||
local foundTop = topStill and topIndex or nil
|
||||
local foundAnchor = nil
|
||||
local foundBottom = bottomStill and bottomIndex or nil
|
||||
|
||||
-- Scan outward from the old anchor index until we find the top and bottom or hit the max distance
|
||||
local deltas = {top=-1, bottom=1}
|
||||
repeat
|
||||
for _, delta in pairs(deltas) do
|
||||
local pos = anchorIndex + delta * step
|
||||
|
||||
if pos >= 1 and pos <= listSize then
|
||||
local id = getID(pos)
|
||||
if id == topID then
|
||||
foundTop = pos
|
||||
end
|
||||
if id == anchorID then
|
||||
foundAnchor = pos
|
||||
end
|
||||
if id == bottomID then
|
||||
foundBottom = pos
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
step = step + 1
|
||||
until (foundTop and foundAnchor and foundBottom) or step > props.maximumSearchDistance
|
||||
|
||||
return foundTop, foundAnchor, foundBottom
|
||||
end
|
||||
+57
@@ -0,0 +1,57 @@
|
||||
local Round = require(script.Parent.Round)
|
||||
|
||||
-- Returns the three new indices with any nils filled in and any misorderings corrected.
|
||||
-- new and old should be tables containing an anchorIndex, a leadIndex and a trailIndex.
|
||||
return function(new, old, listSize)
|
||||
local newAnchor = new.anchorIndex
|
||||
local newLead = new.leadIndex
|
||||
local newTrail = new.trailIndex
|
||||
|
||||
-- There are 8 possibilities here as any combination of these could be deleted. Also, we can't use findIndexAt
|
||||
-- here since that requires access to the children's measurements.
|
||||
if not newAnchor then
|
||||
if newLead and newTrail then
|
||||
-- Estimate that the new anchor is proportionally the same distance from the lead and trail indices.
|
||||
if newLead == newTrail then
|
||||
-- Guard against divide by zero.
|
||||
newAnchor = newLead
|
||||
else
|
||||
local oldRatio = (old.anchorIndex - old.leadIndex) / (old.trailIndex - old.leadIndex)
|
||||
newAnchor = Round.nearest((newTrail - newLead) * oldRatio + newLead)
|
||||
newAnchor = math.min(math.max(newAnchor, 1), listSize)
|
||||
end
|
||||
elseif newLead then
|
||||
-- Given only the new leading index, estimate that the new anchor is the same distance away as it was.
|
||||
newAnchor = newLead + old.anchorIndex - old.leadIndex
|
||||
newAnchor = math.min(math.max(newAnchor, 1), listSize)
|
||||
elseif newTrail then
|
||||
-- Given only the new trailing index, estimate that the new anchor is the same distance away as it was.
|
||||
newAnchor = newTrail + old.anchorIndex - old.trailIndex
|
||||
newAnchor = math.min(math.max(newAnchor, 1), listSize)
|
||||
else
|
||||
-- Everything is gone. Just reuse the same index if that's still within the bounds of the list.
|
||||
newAnchor = math.min(math.max(old.anchorIndex, 1), listSize)
|
||||
end
|
||||
end
|
||||
|
||||
-- If the leading and trailing indices haven't been worked out yet, estimate that the new ones should be the
|
||||
-- same distance from the anchor as the old ones were.
|
||||
if not newTrail then
|
||||
newTrail = newAnchor + old.trailIndex - old.anchorIndex
|
||||
newTrail = math.min(math.max(newTrail, 1), listSize)
|
||||
end
|
||||
if not newLead then
|
||||
newLead = newAnchor + old.leadIndex - old.anchorIndex
|
||||
newLead = math.min(math.max(newLead, 1), listSize)
|
||||
end
|
||||
|
||||
-- Make sure the resulting indices are in the right order.
|
||||
local minIndex = math.min(newAnchor, newLead, newTrail)
|
||||
local maxIndex = math.max(newAnchor, newLead, newTrail)
|
||||
|
||||
return {
|
||||
trailIndex = minIndex,
|
||||
anchorIndex = newAnchor,
|
||||
leadIndex = maxIndex,
|
||||
}
|
||||
end
|
||||
+56
@@ -0,0 +1,56 @@
|
||||
local Root = script:FindFirstAncestor("infinite-scroller").Parent
|
||||
local Roact = require(Root.Roact)
|
||||
|
||||
ComplexThing = Roact.PureComponent:extend("ComplexThing")
|
||||
|
||||
ComplexThing.defaultProps = {
|
||||
-- things start to lag at 5?
|
||||
nestedLayer = 3,
|
||||
Size = UDim2.fromScale(0.5, 0.5),
|
||||
}
|
||||
|
||||
function ComplexThing:render()
|
||||
--temporary hard limit
|
||||
if self.props.nestedLayer > 6 then
|
||||
return Roact.createElement("Frame", {
|
||||
Size = UDim2.fromOffset(100, 100)
|
||||
})
|
||||
end
|
||||
|
||||
local children = {}
|
||||
|
||||
if self.props.nestedLayer > 1 then
|
||||
children = {
|
||||
["TL"..self.props.nestedLayer] = Roact.createElement(ComplexThing, {
|
||||
Position = UDim2.fromScale(0, 0),
|
||||
nestedLayer = self.props.nestedLayer - 1,
|
||||
}),
|
||||
["TR"..self.props.nestedLayer] = Roact.createElement(ComplexThing, {
|
||||
Position = UDim2.fromScale(0.5, 0),
|
||||
nestedLayer = self.props.nestedLayer - 1,
|
||||
}),
|
||||
["BL"..self.props.nestedLayer] = Roact.createElement(ComplexThing, {
|
||||
Position = UDim2.fromScale(0, 0.5),
|
||||
nestedLayer = self.props.nestedLayer - 1,
|
||||
}),
|
||||
["BR"..self.props.nestedLayer] = Roact.createElement(ComplexThing, {
|
||||
Position = UDim2.fromScale(0.5, 0.5),
|
||||
nestedLayer = self.props.nestedLayer - 1,
|
||||
}),
|
||||
}
|
||||
end
|
||||
|
||||
local r = math.random(255)
|
||||
local g = math.random(255)
|
||||
local b = math.random(255)
|
||||
|
||||
return Roact.createElement("Frame", {
|
||||
Size = self.props.Size,
|
||||
Position = self.props.Position,
|
||||
BackgroundColor3 = Color3.fromRGB(r, g, b),
|
||||
BorderSizePixel = self.props.Size.X.Scale == 0.5 and 0 or 4,
|
||||
BorderColor3 = Color3.fromRGB(255, 255, 255),
|
||||
}, children)
|
||||
end
|
||||
|
||||
return ComplexThing
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
local Root = script:FindFirstAncestor("infinite-scroller").Parent
|
||||
local Roact = require(Root.Roact)
|
||||
|
||||
return function(props)
|
||||
return Roact.createFragment({
|
||||
foo = Roact.createElement("Frame", {
|
||||
BackgroundColor3 = props.color,
|
||||
Size = UDim2.new(0, props.width, 0, props.width),
|
||||
LayoutOrder = props.LayoutOrder,
|
||||
}),
|
||||
bar = Roact.createElement("Frame", {
|
||||
BackgroundColor3 = props.color,
|
||||
Size = UDim2.new(0, props.width, 0, props.width),
|
||||
LayoutOrder = props.LayoutOrder + 1,
|
||||
})
|
||||
})
|
||||
end
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
local Root = script:FindFirstAncestor("infinite-scroller").Parent
|
||||
local Roact = require(Root.Roact)
|
||||
|
||||
return function(props)
|
||||
return Roact.createElement("Frame", {
|
||||
BackgroundColor3 = props.color,
|
||||
Size = UDim2.new(0, props.width, 0, props.width),
|
||||
LayoutOrder = props.LayoutOrder,
|
||||
})
|
||||
end
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
local Root = script:FindFirstAncestor("infinite-scroller").Parent
|
||||
local Roact = require(Root.Roact)
|
||||
|
||||
local Thing = Roact.PureComponent:extend("Thing")
|
||||
|
||||
function Thing:render()
|
||||
return Roact.createElement("Frame", {
|
||||
BackgroundColor3 = self.props.color,
|
||||
Size = UDim2.new(0, self.props.width, 0, self.props.width),
|
||||
LayoutOrder = self.props.LayoutOrder,
|
||||
})
|
||||
end
|
||||
|
||||
local ThingRoot = Roact.PureComponent:extend("ThingRoot")
|
||||
|
||||
function ThingRoot:render()
|
||||
return Roact.createElement(Thing, {
|
||||
color = self.props.color,
|
||||
width = self.props.width,
|
||||
LayoutOrder = self.props.LayoutOrder,
|
||||
})
|
||||
end
|
||||
|
||||
return ThingRoot
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
local Root = script:FindFirstAncestor("infinite-scroller").Parent
|
||||
local Roact = require(Root.Roact)
|
||||
|
||||
local Thing = Roact.PureComponent:extend("Thing")
|
||||
|
||||
function Thing:init()
|
||||
self.state = {
|
||||
clicked = false,
|
||||
token = nil,
|
||||
}
|
||||
end
|
||||
|
||||
function Thing.getDerivedStateFromProps(nextProps, lastState)
|
||||
-- Use the token we're already being passed as a surrogate lock, just for this story.
|
||||
-- Normally, this would be a separate prop.
|
||||
if nextProps.token ~= lastState.token then
|
||||
return {
|
||||
clicked = false,
|
||||
token = nextProps.token,
|
||||
}
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
function Thing:render()
|
||||
return Roact.createElement("Frame", {
|
||||
BackgroundColor3 = self.props.color,
|
||||
Size = UDim2.new(1, -self.props.width, 0, self.state.clicked and 10 or self.props.width),
|
||||
LayoutOrder = self.props.LayoutOrder,
|
||||
[Roact.Event.InputBegan] = function(rbx, input)
|
||||
if input.UserInputType == Enum.UserInputType.MouseButton1 then
|
||||
self:setState({clicked = not self.state.clicked})
|
||||
end
|
||||
end,
|
||||
})
|
||||
end
|
||||
|
||||
return Thing
|
||||
+154
@@ -0,0 +1,154 @@
|
||||
local InfiniteScroller = script:FindFirstAncestor("infinite-scroller")
|
||||
local Root = InfiniteScroller.Parent
|
||||
local Roact = require(Root.Roact)
|
||||
local Cryo = require(Root.Cryo)
|
||||
local Scroller = require(InfiniteScroller).Scroller
|
||||
|
||||
local Story = Roact.PureComponent:extend("Story")
|
||||
|
||||
function Story:init()
|
||||
local startingItems = {}
|
||||
for i = 1, self.props.startingItems or 50 do
|
||||
table.insert(startingItems, i)
|
||||
end
|
||||
self:setState({
|
||||
items = startingItems,
|
||||
lock = 1,
|
||||
width = 260,
|
||||
itemSize = 30,
|
||||
})
|
||||
|
||||
self.focus = self.props.startingFocus or 1
|
||||
end
|
||||
|
||||
function Story:render()
|
||||
return Roact.createFragment({
|
||||
output = Roact.createElement("Frame", {
|
||||
Size = UDim2.new(0, self.state.width, 0, self.state.itemSize + 30),
|
||||
BackgroundTransparency = 1,
|
||||
},{
|
||||
scroller = Roact.createElement(Scroller, Cryo.Dictionary.join({
|
||||
BackgroundColor3 = Color3.fromRGB(255, 0, 0),
|
||||
Size = UDim2.new(1, 0, 1, 0),
|
||||
orientation = Scroller.Orientation.Right,
|
||||
padding = UDim.new(0, 5),
|
||||
itemList = self.state.items,
|
||||
focusIndex = self.focus,
|
||||
focusLock = self.state.lock,
|
||||
anchorLocation = UDim.new(1, -15),
|
||||
loadingBuffer = 2,
|
||||
mountingBuffer = 99,
|
||||
estimatedItemSize = 10,
|
||||
dragBuffer = 120,
|
||||
animateScrolling = true,
|
||||
identifier = function(item)
|
||||
assert(item)
|
||||
return item
|
||||
end,
|
||||
renderItem = function(item, _)
|
||||
return Roact.createElement("TextLabel", {
|
||||
Size = UDim2.new(0, self.state.itemSize, 0, self.state.itemSize),
|
||||
Text = tostring(item),
|
||||
BackgroundColor3 = Color3.fromRGB(255, item*5, (51 - item)*5),
|
||||
}, {
|
||||
["INDEX" .. tostring(item)] = Roact.createElement("Frame"),
|
||||
})
|
||||
end,
|
||||
onScrollUpdate = function(data)
|
||||
self.focus = data.anchorIndex
|
||||
self.animationActive = data.animationActive
|
||||
end,
|
||||
}, self.props, {
|
||||
startingItems = Cryo.None,
|
||||
startingFocus = Cryo.None,
|
||||
})),
|
||||
}),
|
||||
scrollLeft = Roact.createElement("TextButton", {
|
||||
Size = UDim2.new(0, 30, 0, 30),
|
||||
Position = UDim2.new(0, 0, 0, 100),
|
||||
Text = "<",
|
||||
[Roact.Event.Activated] = function()
|
||||
if self.animationActive then
|
||||
return
|
||||
end
|
||||
self.focus = math.max(self.focus - 4, 1)
|
||||
self:setState({lock = self.state.lock + 1})
|
||||
end,
|
||||
}),
|
||||
scrollRight = Roact.createElement("TextButton", {
|
||||
Size = UDim2.new(0, 30, 0, 30),
|
||||
Position = UDim2.new(0, 270, 0, 100),
|
||||
Text = ">",
|
||||
[Roact.Event.Activated] = function()
|
||||
if self.animationActive then
|
||||
return
|
||||
end
|
||||
self.focus = math.min(self.focus + 4, #self.state.items)
|
||||
self:setState({lock = self.state.lock + 1})
|
||||
end,
|
||||
}),
|
||||
decreaseWidth = Roact.createElement("TextButton", {
|
||||
Size = UDim2.new(0, 60, 0, 30),
|
||||
Position = UDim2.new(0, 90, 0, 100),
|
||||
Text = "Width -",
|
||||
[Roact.Event.Activated] = function()
|
||||
if self.animationActive then
|
||||
return
|
||||
end
|
||||
self.focus = math.max(self.focus - 4, 1)
|
||||
self:setState({
|
||||
width = self.state.width - 10,
|
||||
})
|
||||
end,
|
||||
}),
|
||||
increaseWidth = Roact.createElement("TextButton", {
|
||||
Size = UDim2.new(0, 60, 0, 30),
|
||||
Position = UDim2.new(0, 150, 0, 100),
|
||||
Text = "Width +",
|
||||
[Roact.Event.Activated] = function()
|
||||
if self.animationActive then
|
||||
return
|
||||
end
|
||||
self:setState({
|
||||
width = self.state.width + 10,
|
||||
})
|
||||
end,
|
||||
}),
|
||||
removeItem = Roact.createElement("TextButton", {
|
||||
Size = UDim2.new(0, 60, 0, 30),
|
||||
Position = UDim2.new(0, 30, 0, 100),
|
||||
Text = "Item -",
|
||||
[Roact.Event.Activated] = function()
|
||||
if self.animationActive then
|
||||
return
|
||||
end
|
||||
local items = self.state.items
|
||||
local lock = nil
|
||||
if self.focus >= #items then
|
||||
self.focus = #items - 1
|
||||
lock = self.state.lock + 1
|
||||
end
|
||||
self:setState({
|
||||
items = Cryo.List.removeIndex(items, #items),
|
||||
lock = lock,
|
||||
})
|
||||
end,
|
||||
}),
|
||||
addItem = Roact.createElement("TextButton", {
|
||||
Size = UDim2.new(0, 60, 0, 30),
|
||||
Position = UDim2.new(0, 210, 0, 100),
|
||||
Text = "Item +",
|
||||
[Roact.Event.Activated] = function()
|
||||
if self.animationActive then
|
||||
return
|
||||
end
|
||||
local items = self.state.items
|
||||
self:setState({
|
||||
items = Cryo.List.join(items, {#items + 1}),
|
||||
})
|
||||
end,
|
||||
}),
|
||||
})
|
||||
end
|
||||
|
||||
return Story
|
||||
+87
@@ -0,0 +1,87 @@
|
||||
local HttpService = game:GetService("HttpService")
|
||||
|
||||
local InfiniteScroller = script:FindFirstAncestor("infinite-scroller")
|
||||
local Root = InfiniteScroller.Parent
|
||||
local Roact = require(Root.Roact)
|
||||
local Cryo = require(Root.Cryo)
|
||||
local Scroller = require(InfiniteScroller).Scroller
|
||||
|
||||
local Box = function(props)
|
||||
return Roact.createElement("TextLabel", {
|
||||
Size = UDim2.new(1, 0, 0, 40),
|
||||
Text = props.text,
|
||||
})
|
||||
end
|
||||
|
||||
local Story = Roact.PureComponent:extend("Story")
|
||||
|
||||
function Story:init()
|
||||
self.state = {
|
||||
items = {},
|
||||
lock = 0,
|
||||
index = 1,
|
||||
size = Vector2.new(400, -100),
|
||||
}
|
||||
end
|
||||
|
||||
function Story:render()
|
||||
return Roact.createFragment({
|
||||
scroller = Roact.createElement(Scroller, {
|
||||
BackgroundColor3 = Color3.fromRGB(56, 19, 18),
|
||||
Size = UDim2.new(0, self.state.size.X, 1, self.state.size.Y),
|
||||
Position = UDim2.new(0, 50, 0, 50),
|
||||
ScrollBarThickness = 8,
|
||||
padding = UDim.new(0, 5),
|
||||
orientation = Scroller.Orientation.Down,
|
||||
itemList = self.state.items,
|
||||
focusLock = self.state.lock,
|
||||
focusIndex = self.state.index,
|
||||
anchorLocation = UDim.new(0, 0),
|
||||
estimatedItemSize = 40,
|
||||
dragBuffer = 0,
|
||||
extraProps = self.state.items,
|
||||
identifier = function(item)
|
||||
return item.guid
|
||||
end,
|
||||
renderItem = function(item, _)
|
||||
return Roact.createElement(Box, item)
|
||||
end,
|
||||
onScrollUpdate = function(data)
|
||||
self.indexData = data
|
||||
end
|
||||
}),
|
||||
textbox = Roact.createElement("TextBox", {
|
||||
Size = UDim2.new(0, 100, 0, 50),
|
||||
Position = UDim2.new(1, -100, 0, 0),
|
||||
[Roact.Event.FocusLost] = function(rbx, entered)
|
||||
if entered and rbx.Text ~= "" then
|
||||
local newItem = {
|
||||
text = rbx.Text,
|
||||
guid = HttpService:GenerateGUID(false),
|
||||
}
|
||||
|
||||
local newState
|
||||
if self.state.items then
|
||||
newState = { items = Cryo.List.join(self.state.items, { newItem })}
|
||||
|
||||
if self.indexData and self.indexData.anchorIndex == #self.state.items then
|
||||
newState.lock = self.state.lock + 1
|
||||
newState.index = #newState.items
|
||||
end
|
||||
else
|
||||
newState = {
|
||||
items = { newItem },
|
||||
index = 1,
|
||||
lock = 1,
|
||||
}
|
||||
end
|
||||
|
||||
rbx.Text = ""
|
||||
self:setState(newState)
|
||||
end
|
||||
end
|
||||
}),
|
||||
})
|
||||
end
|
||||
|
||||
return Story
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
local InfiniteScroller = script:FindFirstAncestor("infinite-scroller")
|
||||
local Root = InfiniteScroller.Parent
|
||||
local Roact = require(Root.Roact)
|
||||
|
||||
local ComplexThing = require(script.Parent.ComplexThing)
|
||||
local Story = Roact.PureComponent:extend("Story")
|
||||
|
||||
Story.defaultProps = {
|
||||
numThings = 5,
|
||||
}
|
||||
|
||||
function Story:init()
|
||||
self.ref = Roact.createRef()
|
||||
|
||||
self.manyComplexThings = {
|
||||
layout = Roact.createElement("UIListLayout", {
|
||||
|
||||
})
|
||||
}
|
||||
local function makeComplexThing()
|
||||
return Roact.createElement(ComplexThing, {
|
||||
Size = UDim2.fromOffset(256, 256),
|
||||
nestedLayer = 5,
|
||||
})
|
||||
end
|
||||
for _ = 1, self.props.numThings do
|
||||
table.insert(self.manyComplexThings, makeComplexThing())
|
||||
end
|
||||
end
|
||||
|
||||
function Story:render()
|
||||
return Roact.createElement("ScrollingFrame", {
|
||||
Position = UDim2.new(0, 0, 0, 300),
|
||||
ClipsDescendants = false,
|
||||
Size = UDim2.fromOffset(256, 256),
|
||||
CanvasSize = UDim2.new(1, 0, 0, self.props.numThings * 256),
|
||||
ScrollingDirection = Enum.ScrollingDirection.Y,
|
||||
}, self.manyComplexThings)
|
||||
end
|
||||
|
||||
return Story
|
||||
+80
@@ -0,0 +1,80 @@
|
||||
local InfiniteScroller = script:FindFirstAncestor("infinite-scroller")
|
||||
local Root = InfiniteScroller.Parent
|
||||
local Roact = require(Root.Roact)
|
||||
local Cryo = require(Root.Cryo)
|
||||
local Scroller = require(InfiniteScroller).Scroller
|
||||
|
||||
local Story = Roact.PureComponent:extend("Rhodium Story - item shuffle test")
|
||||
|
||||
local NUM_ITEMS = 10
|
||||
function Story:init()
|
||||
self.state.items = {}
|
||||
for i = 1,NUM_ITEMS do
|
||||
table.insert(self.state.items, {id = i})
|
||||
end
|
||||
|
||||
self.state.focusLock = 1
|
||||
end
|
||||
|
||||
function Story:render()
|
||||
return Roact.createElement("Frame", {
|
||||
Size=UDim2.new(1, 0, 1, 0),
|
||||
BackgroundTransparency = 1,
|
||||
}, {
|
||||
scroll = Roact.createElement(Scroller, Cryo.Dictionary.join(
|
||||
{
|
||||
BackgroundColor3 = Color3.fromRGB(255, 0, 0),
|
||||
Size = UDim2.new(0, 100, 0, 100),
|
||||
padding = UDim.new(),
|
||||
itemList = self.state.items,
|
||||
focusIndex = 1,
|
||||
focusLock = self.state.focusLock,
|
||||
anchorLocation = UDim.new(1, 0),
|
||||
loadingBuffer = 2,
|
||||
mountingBuffer = 99,
|
||||
estimatedItemSize = 10,
|
||||
identifier = function(item)
|
||||
return item.id
|
||||
end,
|
||||
renderItem = function(item, _)
|
||||
return Roact.createElement("Frame", {
|
||||
Size = UDim2.new(0, 20, 0, 20),
|
||||
BackgroundColor3 = Color3.fromRGB(0, 128 - 8*item.id, 128 + 8*item.id),
|
||||
}, {
|
||||
["INDEX" .. tostring(item.id)] = Roact.createElement("TextLabel", {
|
||||
Size = UDim2.new(1, 0, 1, 0),
|
||||
Text = item.id,
|
||||
TextColor3 = Color3.new(1, 1, 1),
|
||||
BackgroundTransparency = 1,
|
||||
}),
|
||||
})
|
||||
end,
|
||||
},
|
||||
self.props,
|
||||
{toDelete = Cryo.None}
|
||||
)),
|
||||
shuffle = Roact.createElement("TextButton", {
|
||||
Size = UDim2.new(0, 100, 0, 50),
|
||||
Position = UDim2.new(0.5, 0, 0, 0),
|
||||
AnchorPoint = Vector2.new(1, 0),
|
||||
Text = "Shuffle",
|
||||
[Roact.Event.Activated] = function()
|
||||
local nextItems = self.state.items
|
||||
|
||||
for _, v in pairs(nextItems) do
|
||||
v.id = v.id+1
|
||||
if v.id > NUM_ITEMS then
|
||||
v.id = 1
|
||||
end
|
||||
end
|
||||
|
||||
self:setState({
|
||||
items = nextItems,
|
||||
focusLock = self.state.focusLock + 1,
|
||||
})
|
||||
end,
|
||||
}),
|
||||
})
|
||||
end
|
||||
|
||||
return Story
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
local Root = script:FindFirstAncestor("infinite-scroller").Parent
|
||||
local Roact = require(Root.Roact)
|
||||
|
||||
Roact.setGlobalConfig({
|
||||
propValidation = true,
|
||||
})
|
||||
|
||||
local SCREEN_SIZE = Vector2.new(800, 800)
|
||||
|
||||
return {
|
||||
name = "Scroller",
|
||||
storyRoot = script,
|
||||
middleware = function(story, target)
|
||||
local tree = Roact.createElement("Frame", {
|
||||
BackgroundColor3 = Color3.fromRGB(30, 31, 28),
|
||||
Size = UDim2.new(0, SCREEN_SIZE.X, 0, SCREEN_SIZE.Y),
|
||||
ClipsDescendants = true,
|
||||
}, {
|
||||
Story = Roact.createElement(story)
|
||||
})
|
||||
|
||||
local handle = Roact.mount(tree, target, "Root")
|
||||
return function()
|
||||
Roact.unmount(handle)
|
||||
end
|
||||
end,
|
||||
}
|
||||
+88
@@ -0,0 +1,88 @@
|
||||
local InfiniteScroller = script:FindFirstAncestor("infinite-scroller")
|
||||
local Root = InfiniteScroller.Parent
|
||||
local Roact = require(Root.Roact)
|
||||
local Cryo = require(Root.Cryo)
|
||||
local Scroller = require(InfiniteScroller).Scroller
|
||||
|
||||
local Story = Roact.PureComponent:extend("Rhodium Story - item addition test")
|
||||
|
||||
function Story:init()
|
||||
local items = {}
|
||||
local numberOfItems = self.props.numberOfItems or 30
|
||||
for i = 1, numberOfItems do
|
||||
table.insert(items, {id = i})
|
||||
end
|
||||
|
||||
self.state = {
|
||||
itemList = items,
|
||||
}
|
||||
end
|
||||
|
||||
function Story:render()
|
||||
local focusIndex = self.props.addToFront and 1 or #self.state.itemList
|
||||
|
||||
return Roact.createElement("Frame", {
|
||||
Size = UDim2.new(1, 0, 1, 0),
|
||||
BackgroundTransparency = 1,
|
||||
}, {
|
||||
scroll = Roact.createElement(Scroller, Cryo.Dictionary.join(
|
||||
{
|
||||
Size = UDim2.new(0, 100, 0, 200),
|
||||
focusIndex = focusIndex,
|
||||
focusLock = self.state.itemList[focusIndex].id,
|
||||
anchorLocation = UDim.new(1, 0),
|
||||
dragBuffer = 200,
|
||||
itemList = self.state.itemList,
|
||||
orientation = Scroller.Orientation.Up,
|
||||
identifier = function(item)
|
||||
return item.id
|
||||
end,
|
||||
renderItem = function(item, _)
|
||||
local r = 88+88*math.sin(math.rad(8*item.id+90))
|
||||
local g = 88+44*math.sin(math.rad(8*item.id+0))
|
||||
local b = 88+88*math.sin(math.rad(8*item.id+180))
|
||||
|
||||
return Roact.createElement("Frame", {
|
||||
Size = UDim2.new(0, 20, 0, 20),
|
||||
BackgroundColor3 = Color3.fromRGB(r, g, b),
|
||||
}, {
|
||||
["INDEX" .. tostring(item.id)] = Roact.createElement("TextLabel", {
|
||||
Size = UDim2.new(1, 0, 1, 0),
|
||||
Text = item.id,
|
||||
TextColor3 = Color3.new(1, 1, 1),
|
||||
BackgroundTransparency = 1,
|
||||
}),
|
||||
})
|
||||
end,
|
||||
},
|
||||
self.props,
|
||||
{
|
||||
addToFront = Cryo.None,
|
||||
numberOfItems = Cryo.None,
|
||||
}
|
||||
)),
|
||||
addition = Roact.createElement("TextButton", {
|
||||
Size = UDim2.new(0, 100, 0, 50),
|
||||
Position = UDim2.new(0.5, 0, 0, 0),
|
||||
AnchorPoint = Vector2.new(1, 0),
|
||||
Text = "Add Item",
|
||||
|
||||
[Roact.Event.Activated] = function()
|
||||
local nextId = #self.state.itemList + 1
|
||||
|
||||
local nextItems
|
||||
if self.props.addToFront then
|
||||
nextItems = Cryo.List.join({{id = nextId}}, self.state.itemList)
|
||||
else
|
||||
nextItems = Cryo.List.join(self.state.itemList, {{id = nextId}})
|
||||
end
|
||||
|
||||
self:setState({
|
||||
itemList = nextItems,
|
||||
})
|
||||
end,
|
||||
}),
|
||||
})
|
||||
end
|
||||
|
||||
return Story
|
||||
+78
@@ -0,0 +1,78 @@
|
||||
local InfiniteScroller = script:FindFirstAncestor("infinite-scroller")
|
||||
local Root = InfiniteScroller.Parent
|
||||
local Roact = require(Root.Roact)
|
||||
local Cryo = require(Root.Cryo)
|
||||
local Scroller = require(InfiniteScroller).Scroller
|
||||
|
||||
local Story = Roact.PureComponent:extend("Rhodium Story - item deletion test")
|
||||
|
||||
function Story:init()
|
||||
self.state.items = {}
|
||||
for i = -20,20 do
|
||||
table.insert(self.state.items, {id = i})
|
||||
end
|
||||
end
|
||||
|
||||
function Story:render()
|
||||
return Roact.createElement("Frame", {
|
||||
Size=UDim2.new(1, 0, 1, 0),
|
||||
BackgroundTransparency = 1,
|
||||
}, {
|
||||
scroll = Roact.createElement(Scroller, Cryo.Dictionary.join(
|
||||
{
|
||||
BackgroundColor3 = Color3.fromRGB(255, 0, 0),
|
||||
Size = UDim2.new(0, 100, 0, 100),
|
||||
padding = UDim.new(),
|
||||
itemList = self.state.items,
|
||||
focusIndex = 21,
|
||||
anchorLocation = UDim.new(0.5, 0),
|
||||
loadingBuffer = 2,
|
||||
mountingBuffer = 99,
|
||||
estimatedItemSize = 10,
|
||||
identifier = function(item)
|
||||
return item.id
|
||||
end,
|
||||
renderItem = function(item, _)
|
||||
return Roact.createElement("Frame", {
|
||||
Size = UDim2.new(0, 10, 0, 10),
|
||||
BackgroundColor3 = item == 0
|
||||
and Color3.fromRGB(255, 255, 255)
|
||||
or Color3.fromRGB(0, 128 - 8*item.id, 128 + 8*item.id),
|
||||
}, {
|
||||
["INDEX" .. tostring(item.id)] = Roact.createElement("Frame"),
|
||||
})
|
||||
end,
|
||||
},
|
||||
self.props,
|
||||
{toDelete = Cryo.None}
|
||||
)),
|
||||
deletion = Roact.createElement("TextButton", {
|
||||
Size = UDim2.new(0, 100, 0, 50),
|
||||
Position = UDim2.new(0.5, 0, 0, 0),
|
||||
AnchorPoint = Vector2.new(1, 0),
|
||||
Text = "Delete",
|
||||
[Roact.Event.Activated] = function()
|
||||
local nextItems
|
||||
if self.props.toDelete then
|
||||
nextItems = Cryo.List.filter(self.state.items, function(item)
|
||||
for _, v in pairs(self.props.toDelete) do
|
||||
if item.id == v then
|
||||
return false
|
||||
end
|
||||
end
|
||||
return true
|
||||
end)
|
||||
else
|
||||
local n = math.random(1, #self.state.items)
|
||||
print("Deleting index " .. tostring(n))
|
||||
nextItems = Cryo.List.removeIndex(self.state.items, n)
|
||||
end
|
||||
self:setState({
|
||||
items = nextItems
|
||||
})
|
||||
end,
|
||||
}),
|
||||
})
|
||||
end
|
||||
|
||||
return Story
|
||||
+78
@@ -0,0 +1,78 @@
|
||||
local InfiniteScroller = script:FindFirstAncestor("infinite-scroller")
|
||||
local Root = InfiniteScroller.Parent
|
||||
local Roact = require(Root.Roact)
|
||||
local Cryo = require(Root.Cryo)
|
||||
local Scroller = require(InfiniteScroller).Scroller
|
||||
|
||||
local Story = Roact.PureComponent:extend("Rhodium Story - extra props test")
|
||||
|
||||
local smallScroll = Roact.PureComponent:extend("smallScroll")
|
||||
function smallScroll:render()
|
||||
return Roact.createElement(Scroller, Cryo.Dictionary.join({
|
||||
BackgroundColor3 = Color3.fromRGB(255, 0, 0),
|
||||
Size = UDim2.new(0, 50, 0, 50),
|
||||
padding = UDim.new(),
|
||||
focusIndex = 6,
|
||||
anchorLocation = UDim.new(0.5, 0),
|
||||
loadingBuffer = 2,
|
||||
mountingBuffer = 99,
|
||||
estimatedItemSize = 10,
|
||||
}, self.props))
|
||||
end
|
||||
|
||||
function Story:init()
|
||||
self.state = {
|
||||
items = {},
|
||||
store = {},
|
||||
}
|
||||
for i = 1, 11 do
|
||||
self.state.items[i] = i
|
||||
self.state.store[i] = (i == 6
|
||||
and Color3.fromRGB(255, 255, 255)
|
||||
or Color3.fromRGB(0, i*23, i*23))
|
||||
end
|
||||
|
||||
self.renderItem = function(item)
|
||||
return Roact.createElement("Frame", {
|
||||
Size = UDim2.new(0, 10, 0, 10),
|
||||
BackgroundColor3 = self.state.store[item],
|
||||
}, {
|
||||
["INDEX" .. tostring(item)] = Roact.createElement("Frame"),
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
function Story:render()
|
||||
return Roact.createElement("Frame", {}, {
|
||||
scroller = Roact.createElement(smallScroll, Cryo.Dictionary.join({
|
||||
itemList = self.state.items,
|
||||
renderItem = self.renderItem,
|
||||
extraProps = {self.state.store},
|
||||
}, self.props, {newColor = Cryo.None})),
|
||||
change = Roact.createElement("TextButton", {
|
||||
Size = UDim2.new(0, 30, 0, 30),
|
||||
Position = UDim2.new(0, 100, 0, 10),
|
||||
BackgroundColor3 = Color3.new(1, 1, 1),
|
||||
Text = "X",
|
||||
[Roact.Event.Activated] = function()
|
||||
local newColor = self.props.newColor
|
||||
if not newColor then
|
||||
newColor = Color3.fromRGB(
|
||||
math.random(0, 255),
|
||||
math.random(0, 255),
|
||||
math.random(0, 255)
|
||||
)
|
||||
print("Changing color to ", newColor)
|
||||
end
|
||||
|
||||
local store = {}
|
||||
for i = 1, 11 do
|
||||
store[i] = newColor
|
||||
end
|
||||
self:setState({store = store})
|
||||
end,
|
||||
}),
|
||||
})
|
||||
end
|
||||
|
||||
return Story
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
local InfiniteScroller = script:FindFirstAncestor("infinite-scroller")
|
||||
local Root = InfiniteScroller.Parent
|
||||
local Roact = require(Root.Roact)
|
||||
local Cryo = require(Root.Cryo)
|
||||
local Scroller = require(InfiniteScroller).Scroller
|
||||
|
||||
local Story = Roact.PureComponent:extend("Rhodium Story - a few large items")
|
||||
|
||||
function Story:render()
|
||||
return Roact.createElement(Scroller, Cryo.Dictionary.join({
|
||||
BackgroundColor3 = Color3.fromRGB(255, 0, 0),
|
||||
Size = UDim2.new(0, 50, 0, 50),
|
||||
padding = UDim.new(),
|
||||
itemList = {1, 2, 3, 4, 5, 6, 7},
|
||||
focusIndex = 4,
|
||||
anchorLocation = UDim.new(0.5, 0),
|
||||
loadingBuffer = 2,
|
||||
mountingBuffer = 49,
|
||||
renderItem = function(item, _)
|
||||
return Roact.createElement("Frame", {
|
||||
Size = UDim2.new(0, 50, 0, 50),
|
||||
BackgroundColor3 = Color3.fromRGB(item*30, item*30, item*30),
|
||||
}, {
|
||||
["INDEX" .. tostring(item)] = Roact.createElement("Frame"),
|
||||
})
|
||||
end,
|
||||
}, self.props))
|
||||
end
|
||||
|
||||
return Story
|
||||
+125
@@ -0,0 +1,125 @@
|
||||
local InfiniteScroller = script:FindFirstAncestor("infinite-scroller")
|
||||
local Root = InfiniteScroller.Parent
|
||||
local Roact = require(Root.Roact)
|
||||
local Cryo = require(Root.Cryo)
|
||||
local Scroller = require(InfiniteScroller).Scroller
|
||||
|
||||
local Story = Roact.PureComponent:extend("Rhodium Story - infinite scroll in both directions")
|
||||
|
||||
function Story:init()
|
||||
self.state.items = {
|
||||
{
|
||||
token = 0,
|
||||
color = Color3.fromRGB(255, 255, 255),
|
||||
}
|
||||
}
|
||||
self.state.size = Vector2.new(50, 50)
|
||||
|
||||
self.loadPrevious = function()
|
||||
local newItems = {}
|
||||
local n = self.state.items[1].token
|
||||
for i = n-10, n-1 do
|
||||
table.insert(newItems, {
|
||||
token = i,
|
||||
color = Color3.fromRGB(0, 128 - i, 128 + i),
|
||||
})
|
||||
end
|
||||
self:setState({
|
||||
items = Cryo.List.join(newItems, self.state.items)
|
||||
})
|
||||
end
|
||||
|
||||
self.loadNext = function()
|
||||
local newItems = {}
|
||||
local n = self.state.items[#self.state.items].token
|
||||
for i = n+1, n+10 do
|
||||
table.insert(newItems, {
|
||||
token = i,
|
||||
color = Color3.fromRGB(0, 128 - i, 128 + i),
|
||||
})
|
||||
end
|
||||
self:setState({
|
||||
items = Cryo.List.join(self.state.items, newItems)
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
function Story:render()
|
||||
return Roact.createElement("Frame", {
|
||||
Size = UDim2.new(1, 0, 1, 0),
|
||||
BackgroundTransparency = 1,
|
||||
}, {
|
||||
scroll = Roact.createElement(Scroller, Cryo.Dictionary.join({
|
||||
BackgroundColor3 = Color3.fromRGB(255, 0, 0),
|
||||
Size = UDim2.new(0, self.state.size.X, 0, self.state.size.Y),
|
||||
padding = UDim.new(0, 3),
|
||||
itemList = self.state.items,
|
||||
loadNext = self.loadNext,
|
||||
loadPrevious = self.loadPrevious,
|
||||
focusIndex = 1,
|
||||
anchorLocation = UDim.new(0.5, 0),
|
||||
orientation = Scroller.Orientation.Up,
|
||||
estimatedItemSize = 10,
|
||||
mountingBuffer = 50,
|
||||
identifier = function(item)
|
||||
return item.token
|
||||
end,
|
||||
renderItem = function(item, _)
|
||||
assert(item.token, "Item's token is unset")
|
||||
assert(item.color, "Item's color is unset")
|
||||
return Roact.createElement("Frame", {
|
||||
Size = UDim2.new(0, 10, 0, 10),
|
||||
BackgroundColor3 = item.color,
|
||||
}, {
|
||||
["INDEX" .. tostring(item.token)] = Roact.createElement("Frame"),
|
||||
})
|
||||
end,
|
||||
}, self.props)),
|
||||
moveUp = Roact.createElement("TextButton", {
|
||||
Size = UDim2.new(0, 50, 0, 50),
|
||||
Position = UDim2.new(0.5, -50, 0, 0),
|
||||
AnchorPoint = Vector2.new(1, 0),
|
||||
Text = "^",
|
||||
[Roact.Event.Activated] = function()
|
||||
self:setState({
|
||||
size = self.state.size + Vector2.new(0, -20)
|
||||
})
|
||||
end,
|
||||
}),
|
||||
moveDown = Roact.createElement("TextButton", {
|
||||
Size = UDim2.new(0, 50, 0, 50),
|
||||
Position = UDim2.new(0.5, -50, 0, 100),
|
||||
AnchorPoint = Vector2.new(1, 0),
|
||||
Text = "v",
|
||||
[Roact.Event.Activated] = function()
|
||||
self:setState({
|
||||
size = self.state.size + Vector2.new(0, 20)
|
||||
})
|
||||
end,
|
||||
}),
|
||||
moveLeft = Roact.createElement("TextButton", {
|
||||
Size = UDim2.new(0, 50, 0, 50),
|
||||
Position = UDim2.new(0.5, -100, 0, 50),
|
||||
AnchorPoint = Vector2.new(1, 0),
|
||||
Text = "<",
|
||||
[Roact.Event.Activated] = function()
|
||||
self:setState({
|
||||
size = self.state.size + Vector2.new(-20, 0)
|
||||
})
|
||||
end,
|
||||
}),
|
||||
moveRight = Roact.createElement("TextButton", {
|
||||
Size = UDim2.new(0, 50, 0, 50),
|
||||
Position = UDim2.new(0.5, 0, 0, 50),
|
||||
AnchorPoint = Vector2.new(1, 0),
|
||||
Text = ">",
|
||||
[Roact.Event.Activated] = function()
|
||||
self:setState({
|
||||
size = self.state.size + Vector2.new(20, 0)
|
||||
})
|
||||
end,
|
||||
}),
|
||||
})
|
||||
end
|
||||
|
||||
return Story
|
||||
+69
@@ -0,0 +1,69 @@
|
||||
local InfiniteScroller = script:FindFirstAncestor("infinite-scroller")
|
||||
local Root = InfiniteScroller.Parent
|
||||
local Roact = require(Root.Roact)
|
||||
local Cryo = require(Root.Cryo)
|
||||
local Scroller = require(InfiniteScroller).Scroller
|
||||
|
||||
local Story = Roact.PureComponent:extend("Rhodium Story - enough small items to fill the view")
|
||||
|
||||
Story.defaultProps = {
|
||||
startItems = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11},
|
||||
newItems = {11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1},
|
||||
}
|
||||
|
||||
function Story:init()
|
||||
self.state.items = self.props.startItems
|
||||
end
|
||||
|
||||
function Story:render()
|
||||
return Roact.createElement("Frame", {
|
||||
Size = UDim2.fromScale(1, 1),
|
||||
BackgroundTransparency = 1,
|
||||
}, {
|
||||
Scroller = Roact.createElement(Scroller, Cryo.Dictionary.join(
|
||||
{
|
||||
BackgroundColor3 = Color3.fromRGB(255, 0, 0),
|
||||
Size = UDim2.fromOffset(50, 50),
|
||||
padding = UDim.new(),
|
||||
itemList = self.state.items,
|
||||
focusIndex = 6,
|
||||
anchorLocation = UDim.new(0.5, 0),
|
||||
loadingBuffer = 2,
|
||||
mountingBuffer = 99,
|
||||
estimatedItemSize = 10,
|
||||
renderItem = function(item, _)
|
||||
return Roact.createElement("Frame", {
|
||||
Size = UDim2.new(0, 10, 0, 10),
|
||||
BackgroundColor3 = item == 6
|
||||
and Color3.fromRGB(255, 255, 255)
|
||||
or Color3.fromRGB(0, item*23, item*23),
|
||||
}, {
|
||||
["INDEX" .. tostring(item)] = Roact.createElement("Frame"),
|
||||
})
|
||||
end,
|
||||
},
|
||||
self.props,
|
||||
{
|
||||
startItems = Cryo.None,
|
||||
newItems = Cryo.None,
|
||||
clicked = Cryo.None,
|
||||
}
|
||||
)),
|
||||
Button = Roact.createElement("TextButton", {
|
||||
Size = UDim2.fromOffset(100, 50),
|
||||
Position = UDim2.fromScale(1, 0),
|
||||
AnchorPoint = Vector2.new(1, 0),
|
||||
Text = "Rearrange",
|
||||
[Roact.Event.Activated] = function()
|
||||
self:setState({
|
||||
items = self.props.newItems,
|
||||
})
|
||||
if self.props.clicked then
|
||||
self.props.clicked()
|
||||
end
|
||||
end,
|
||||
})
|
||||
})
|
||||
end
|
||||
|
||||
return Story
|
||||
+96
@@ -0,0 +1,96 @@
|
||||
local InfiniteScroller = script:FindFirstAncestor("infinite-scroller")
|
||||
local Root = InfiniteScroller.Parent
|
||||
local Roact = require(Root.Roact)
|
||||
local Cryo = require(Root.Cryo)
|
||||
local Scroller = require(InfiniteScroller).Scroller
|
||||
|
||||
local Story = Roact.PureComponent:extend("Rhodium Story - delete top item test")
|
||||
|
||||
local END_OF_LIST_INDEX = 100
|
||||
|
||||
function Story:init()
|
||||
self.state.items = {}
|
||||
|
||||
if self.props.loadAll then
|
||||
for i = 1, END_OF_LIST_INDEX do
|
||||
table.insert(self.state.items, {id = i})
|
||||
end
|
||||
else
|
||||
for i = 1, 20 do
|
||||
table.insert(self.state.items, {id = i})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function Story:render()
|
||||
return Roact.createElement("Frame", {
|
||||
Size = UDim2.new(1, 0, 1, 0),
|
||||
BackgroundTransparency = 1,
|
||||
}, {
|
||||
scroll = Roact.createElement(Scroller, Cryo.Dictionary.join(
|
||||
{
|
||||
BackgroundColor3 = Color3.fromRGB(38, 161, 38),
|
||||
Size = UDim2.new(0, 100, 0, 100),
|
||||
padding = UDim.new(),
|
||||
itemList = self.state.items,
|
||||
focusIndex = 1,
|
||||
anchorLocation = UDim.new(1, 0),
|
||||
estimatedItemSize = 20,
|
||||
orientation = Scroller.Orientation.Up,
|
||||
BackgroundTransparency = 0,
|
||||
dragBuffer = 0,
|
||||
ElasticBehavior = Enum.ElasticBehavior.Always,
|
||||
ScrollBarThickness = 10,
|
||||
VerticalScrollBarInset = Enum.ScrollBarInset.Always,
|
||||
identifier = function(item)
|
||||
return item.id
|
||||
end,
|
||||
renderItem = function(item, _)
|
||||
return Roact.createElement("TextButton", {
|
||||
Size = UDim2.new(0, 20, 0, 20),
|
||||
BackgroundColor3 = Color3.fromRGB(200,200, 200),
|
||||
Text = tostring(item.id)
|
||||
}, {
|
||||
["INDEX" .. tostring(item.id)] = Roact.createElement("Frame"),
|
||||
})
|
||||
end,
|
||||
loadNext = function()
|
||||
if not self.props.loadAll then
|
||||
local newItems = {}
|
||||
local n = self.state.items[#self.state.items].id
|
||||
local endIndex = math.min(n + 10, END_OF_LIST_INDEX)
|
||||
for i = n+1, endIndex do
|
||||
table.insert(newItems, {
|
||||
id = i,
|
||||
})
|
||||
end
|
||||
|
||||
if not Cryo.isEmpty(newItems) then
|
||||
self:setState({
|
||||
items = Cryo.List.join(self.state.items, newItems)
|
||||
})
|
||||
end
|
||||
end
|
||||
end,
|
||||
},
|
||||
self.props,
|
||||
{deleteLastItem = Cryo.None},
|
||||
{loadAll = Cryo.None}
|
||||
)),
|
||||
deletion = Roact.createElement("TextButton", {
|
||||
Size = UDim2.new(0, 100, 0, 50),
|
||||
Position = UDim2.new(0.5, 0, 0, 0),
|
||||
AnchorPoint = Vector2.new(1, 0),
|
||||
Text = "Delete",
|
||||
[Roact.Event.Activated] = function()
|
||||
local indexToDelete = self.props.deleteLastItem and #self.state.items or 1
|
||||
local nextItems = Cryo.List.removeIndex(self.state.items, indexToDelete)
|
||||
self:setState({
|
||||
items = nextItems
|
||||
})
|
||||
end,
|
||||
}),
|
||||
})
|
||||
end
|
||||
|
||||
return Story
|
||||
+121
@@ -0,0 +1,121 @@
|
||||
local InfiniteScroller = script:FindFirstAncestor("infinite-scroller")
|
||||
local Root = InfiniteScroller.Parent
|
||||
local Roact = require(Root.Roact)
|
||||
local Cryo = require(Root.Cryo)
|
||||
local Scroller = require(InfiniteScroller).Scroller
|
||||
|
||||
local Bar = Roact.PureComponent:extend("Bar")
|
||||
|
||||
function Bar:init()
|
||||
self.state = {
|
||||
clicked = false,
|
||||
}
|
||||
end
|
||||
|
||||
function Bar:render()
|
||||
return Roact.createElement("TextButton", Cryo.Dictionary.join(
|
||||
{
|
||||
Size = UDim2.new(1, 0, 0, self.state.clicked and 30 or 10),
|
||||
[Roact.Event.Activated] = function()
|
||||
self:setState({
|
||||
clicked = not self.state.clicked,
|
||||
})
|
||||
end,
|
||||
},
|
||||
self.props
|
||||
))
|
||||
end
|
||||
|
||||
local Story = Roact.PureComponent:extend("Rhodium Story - frame resize test")
|
||||
Story.defaultProps = {
|
||||
resizeAmount = 20,
|
||||
initialHeight = 50,
|
||||
}
|
||||
|
||||
function Story:init()
|
||||
self.state = {
|
||||
size = Vector2.new(50, self.props.initialHeight),
|
||||
}
|
||||
end
|
||||
|
||||
function Story:render()
|
||||
return Roact.createElement("Frame", {
|
||||
Size=UDim2.new(1, 0, 1, 0),
|
||||
BackgroundTransparency = 1,
|
||||
}, {
|
||||
scroll = Roact.createElement(Scroller, Cryo.Dictionary.join(
|
||||
{
|
||||
BackgroundColor3 = Color3.fromRGB(255, 0, 0),
|
||||
Size = UDim2.new(0, self.state.size.X, 0, self.state.size.Y),
|
||||
padding = UDim.new(),
|
||||
itemList = {1, 2, 3},
|
||||
focusIndex = 2,
|
||||
anchorLocation = UDim.new(0, 0),
|
||||
orientation = Scroller.Orientation.Down,
|
||||
loadingBuffer = 2,
|
||||
mountingBuffer = 99,
|
||||
estimatedItemSize = 10,
|
||||
renderItem = function(item, _)
|
||||
return Roact.createElement(Bar, {
|
||||
BackgroundColor3 = item == 2
|
||||
and Color3.fromRGB(255, 255, 255)
|
||||
or Color3.fromRGB(0, -128 + 128*item, 376 - 128*item),
|
||||
}, {
|
||||
["INDEX" .. tostring(item)] = Roact.createElement("Frame"),
|
||||
})
|
||||
end,
|
||||
},
|
||||
self.props,
|
||||
{
|
||||
resizeAmount = Cryo.None,
|
||||
initialHeight = Cryo.None,
|
||||
}
|
||||
)),
|
||||
moveUp = Roact.createElement("TextButton", {
|
||||
Size = UDim2.new(0, 50, 0, 50),
|
||||
Position = UDim2.new(0.5, -50, 0, 0),
|
||||
AnchorPoint = Vector2.new(1, 0),
|
||||
Text = "^",
|
||||
[Roact.Event.Activated] = function()
|
||||
self:setState({
|
||||
size = self.state.size + Vector2.new(0, -self.props.resizeAmount)
|
||||
})
|
||||
end,
|
||||
}),
|
||||
moveDown = Roact.createElement("TextButton", {
|
||||
Size = UDim2.new(0, 50, 0, 50),
|
||||
Position = UDim2.new(0.5, -50, 0, 100),
|
||||
AnchorPoint = Vector2.new(1, 0),
|
||||
Text = "v",
|
||||
[Roact.Event.Activated] = function()
|
||||
self:setState({
|
||||
size = self.state.size + Vector2.new(0, self.props.resizeAmount)
|
||||
})
|
||||
end,
|
||||
}),
|
||||
moveLeft = Roact.createElement("TextButton", {
|
||||
Size = UDim2.new(0, 50, 0, 50),
|
||||
Position = UDim2.new(0.5, -100, 0, 50),
|
||||
AnchorPoint = Vector2.new(1, 0),
|
||||
Text = "<",
|
||||
[Roact.Event.Activated] = function()
|
||||
self:setState({
|
||||
size = self.state.size + Vector2.new(-self.props.resizeAmount, 0)
|
||||
})
|
||||
end,
|
||||
}),
|
||||
moveRight = Roact.createElement("TextButton", {
|
||||
Size = UDim2.new(0, 50, 0, 50),
|
||||
Position = UDim2.new(0.5, 0, 0, 50),
|
||||
AnchorPoint = Vector2.new(1, 0),
|
||||
Text = ">",
|
||||
[Roact.Event.Activated] = function()
|
||||
self:setState({
|
||||
size = self.state.size + Vector2.new(self.props.resizeAmount, 0)
|
||||
})
|
||||
end,
|
||||
}),
|
||||
})
|
||||
end
|
||||
|
||||
return Story
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
local InfiniteScroller = script:FindFirstAncestor("infinite-scroller")
|
||||
local Root = InfiniteScroller.Parent
|
||||
local Roact = require(Root.Roact)
|
||||
local Cryo = require(Root.Cryo)
|
||||
local Scroller = require(InfiniteScroller).Scroller
|
||||
|
||||
local Story = Roact.PureComponent:extend("Rhodium Story - enough small items to fill the view")
|
||||
|
||||
function Story:render()
|
||||
return Roact.createElement("Frame", {
|
||||
BackgroundTransparency = 1,
|
||||
Size = self.props.frameSize or UDim2.new(0, 50, 0, 50),
|
||||
}, {
|
||||
layout = Roact.createElement("UIListLayout", {
|
||||
VerticalAlignment = Enum.VerticalAlignment.Center,
|
||||
HorizontalAlignment = Enum.HorizontalAlignment.Center,
|
||||
}),
|
||||
|
||||
scroll = Roact.createElement(Scroller, Cryo.Dictionary.join({
|
||||
BackgroundColor3 = Color3.fromRGB(255, 0, 0),
|
||||
Size = UDim2.new(0, 50, 0, 50),
|
||||
padding = UDim.new(),
|
||||
itemList = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11},
|
||||
focusIndex = 6,
|
||||
anchorLocation = UDim.new(0.5, 0),
|
||||
loadingBuffer = 2,
|
||||
mountingBuffer = 99,
|
||||
estimatedItemSize = 10,
|
||||
renderItem = function(item, _)
|
||||
return Roact.createElement("Frame", {
|
||||
Size = UDim2.new(0, 10, 0, 10),
|
||||
BackgroundColor3 = item == 6
|
||||
and Color3.fromRGB(255, 255, 255)
|
||||
or Color3.fromRGB(0, item*23, item*23),
|
||||
}, {
|
||||
["INDEX" .. tostring(item)] = Roact.createElement("Frame"),
|
||||
})
|
||||
end,
|
||||
},
|
||||
self.props,
|
||||
{ frameSize = Cryo.None }
|
||||
))
|
||||
})
|
||||
end
|
||||
|
||||
return Story
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
local InfiniteScroller = script:FindFirstAncestor("infinite-scroller")
|
||||
local Root = InfiniteScroller.Parent
|
||||
local Roact = require(Root.Roact)
|
||||
local Cryo = require(Root.Cryo)
|
||||
local Scroller = require(InfiniteScroller).Scroller
|
||||
|
||||
local Story = Roact.PureComponent:extend("Rhodium Story - a single small item")
|
||||
|
||||
function Story:render()
|
||||
return Roact.createElement(Scroller, Cryo.Dictionary.join({
|
||||
BackgroundColor3 = Color3.fromRGB(255, 0, 0),
|
||||
Size = UDim2.new(0, 50, 0, 50),
|
||||
itemList = {1},
|
||||
anchorLocation = UDim.new(0.5, 0),
|
||||
dragBuffer = 0,
|
||||
renderItem = function()
|
||||
return Roact.createElement("Frame", {Size=UDim2.new(0, 10, 0, 10)})
|
||||
end,
|
||||
}, self.props))
|
||||
end
|
||||
|
||||
return Story
|
||||
+87
@@ -0,0 +1,87 @@
|
||||
local InfiniteScroller = script:FindFirstAncestor("infinite-scroller")
|
||||
local Root = InfiniteScroller.Parent
|
||||
local Roact = require(Root.Roact)
|
||||
local Cryo = require(Root.Cryo)
|
||||
local Scroller = require(InfiniteScroller).Scroller
|
||||
|
||||
local Story = Roact.PureComponent:extend("Rhodium Story - Swap a large list for a smaller one")
|
||||
Story.defaultProps = {
|
||||
anchorLocation = UDim.new(1, -10),
|
||||
focusIndex = 1,
|
||||
orientation = Scroller.Orientation.Up,
|
||||
size = UDim2.new(0, 400, 0, 300),
|
||||
|
||||
shortToLong = false, -- Swap from a short list to a long list when true, swap from a long list to a short list when false
|
||||
longItemList = {"a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z"},
|
||||
shortItemList = {"Z", "X", "Y"},
|
||||
}
|
||||
|
||||
function Story:init()
|
||||
self.state = {
|
||||
items = self.props.shortToLong and self.props.shortItemList or self.props.longItemList,
|
||||
}
|
||||
end
|
||||
|
||||
function Story:render()
|
||||
return Roact.createElement("Frame", {
|
||||
Size = UDim2.new(1, 0, 1, 0),
|
||||
BackgroundTransparency = 1,
|
||||
}, {
|
||||
scroller = Roact.createElement(Scroller, Cryo.Dictionary.join(
|
||||
{
|
||||
BackgroundColor3 = Color3.fromRGB(56, 19, 18),
|
||||
Size = self.props.size,
|
||||
orientation = self.props.orientation,
|
||||
itemList = self.state.items,
|
||||
focusLock = self.state.items[1],
|
||||
focusIndex = self.props.focusIndex,
|
||||
anchorLocation = self.props.anchorLocation,
|
||||
estimatedItemSize = 40,
|
||||
dragBuffer = 0,
|
||||
identifier = function(item)
|
||||
return item
|
||||
end,
|
||||
renderItem = function(item, _)
|
||||
return Roact.createElement("Frame", {
|
||||
Size = UDim2.new(0, 300, 0, 40),
|
||||
BackgroundColor3 = Color3.fromRGB(0, 255, 21),
|
||||
}, {
|
||||
["INDEX" .. tostring(item)] = Roact.createElement("TextLabel", {
|
||||
Size = UDim2.new(1, 0, 1, 0),
|
||||
Text = item,
|
||||
TextColor3 = Color3.new(0, 0, 0),
|
||||
BackgroundTransparency = 1,
|
||||
}),
|
||||
})
|
||||
end,
|
||||
},
|
||||
self.props,
|
||||
{
|
||||
shortToLong = Cryo.None,
|
||||
longItemList = Cryo.None,
|
||||
shortItemList = Cryo.None,
|
||||
size = Cryo.None,
|
||||
}
|
||||
)),
|
||||
swapButton = Roact.createElement("TextButton", {
|
||||
Size = UDim2.new(0, 100, 0, 50),
|
||||
Position = UDim2.new(1, -100, 0, 0),
|
||||
Text = "Swap Lists",
|
||||
|
||||
[Roact.Event.Activated] = function()
|
||||
-- Swap lists
|
||||
if #self.state.items == #self.props.shortItemList then
|
||||
self:setState({
|
||||
items = self.props.longItemList,
|
||||
})
|
||||
else
|
||||
self:setState({
|
||||
items = self.props.shortItemList,
|
||||
})
|
||||
end
|
||||
end,
|
||||
}),
|
||||
})
|
||||
end
|
||||
|
||||
return Story
|
||||
+204
@@ -0,0 +1,204 @@
|
||||
local InfiniteScroller = script:FindFirstAncestor("infinite-scroller")
|
||||
local Root = InfiniteScroller.Parent
|
||||
local Roact = require(Root.Roact)
|
||||
local Cryo = require(Root.Cryo)
|
||||
local Scroller = require(InfiniteScroller).Scroller
|
||||
|
||||
-- Note: if you set this to ComplexThing, you may crash
|
||||
local Thing = require(script.Parent.ResizingThing)
|
||||
|
||||
local Story = Roact.PureComponent:extend("Story")
|
||||
|
||||
function Story:render()
|
||||
return Roact.createFragment({
|
||||
scroller = Roact.createElement(Scroller, {
|
||||
BackgroundColor3 = Color3.fromRGB(56, 19, 18),
|
||||
Size = UDim2.new(0, self.state.size.X, 1, self.state.size.Y),
|
||||
Position = UDim2.new(0, 50, 0, 50),
|
||||
ScrollBarThickness = 8,
|
||||
padding = UDim.new(0, 5),
|
||||
orientation = Scroller.Orientation.Down,
|
||||
itemList = self.state.items,
|
||||
loadNext = self.loadNext,
|
||||
loadPrevious = self.loadPrevious,
|
||||
focusLock = self.state.lock,
|
||||
focusIndex = self.state.index,
|
||||
anchorLocation = UDim.new(0, 0),
|
||||
estimatedItemSize = 40,
|
||||
identifier = function(item) return item.token end,
|
||||
renderItem = function(item, _)
|
||||
return Roact.createElement(Thing, item)
|
||||
end,
|
||||
onScrollUpdate = function(data)
|
||||
self.indexData = data
|
||||
end
|
||||
}),
|
||||
refresh = Roact.createElement("TextButton", {
|
||||
Size = UDim2.new(0, 110, 0, 30),
|
||||
Position = UDim2.new(1, -50, 0, 50),
|
||||
AnchorPoint = Vector2.new(1, 0),
|
||||
Text = "Refresh",
|
||||
BackgroundColor3 = Color3.fromRGB(255, 255, 255),
|
||||
[Roact.Event.Activated] = self.clickRefresh,
|
||||
}),
|
||||
up = Roact.createElement("TextButton", {
|
||||
Size = UDim2.new(0, 30, 0, 30),
|
||||
Position = UDim2.new(1, -90, 0, 90),
|
||||
AnchorPoint = Vector2.new(1, 0),
|
||||
Text = "^",
|
||||
BackgroundColor3 = Color3.fromRGB(255, 255, 255),
|
||||
[Roact.Event.Activated] = self.clickUp,
|
||||
}),
|
||||
down = Roact.createElement("TextButton", {
|
||||
Size = UDim2.new(0, 30, 0, 30),
|
||||
Position = UDim2.new(1, -90, 0, 170),
|
||||
AnchorPoint = Vector2.new(1, 0),
|
||||
Text = "v",
|
||||
BackgroundColor3 = Color3.fromRGB(255, 255, 255),
|
||||
[Roact.Event.Activated] = self.clickDown,
|
||||
}),
|
||||
left = Roact.createElement("TextButton", {
|
||||
Size = UDim2.new(0, 30, 0, 30),
|
||||
Position = UDim2.new(1, -130, 0, 130),
|
||||
AnchorPoint = Vector2.new(1, 0),
|
||||
Text = "<",
|
||||
BackgroundColor3 = Color3.fromRGB(255, 255, 255),
|
||||
[Roact.Event.Activated] = self.clickLeft,
|
||||
}),
|
||||
right = Roact.createElement("TextButton", {
|
||||
Size = UDim2.new(0, 30, 0, 30),
|
||||
Position = UDim2.new(1, -50, 0, 130),
|
||||
AnchorPoint = Vector2.new(1, 0),
|
||||
Text = ">",
|
||||
BackgroundColor3 = Color3.fromRGB(255, 255, 255),
|
||||
[Roact.Event.Activated] = self.clickRight,
|
||||
}),
|
||||
skipUp = Roact.createElement("TextButton", {
|
||||
Size = UDim2.new(0, 60, 0, 30),
|
||||
Position = UDim2.new(1, -90, 0, 220),
|
||||
AnchorPoint = Vector2.new(1, 0),
|
||||
Text = "SkipUp",
|
||||
BackgroundColor3 = Color3.fromRGB(255, 255, 255),
|
||||
[Roact.Event.Activated] = self.skipUp,
|
||||
}),
|
||||
skipDown = Roact.createElement("TextButton", {
|
||||
Size = UDim2.new(0, 60, 0, 30),
|
||||
Position = UDim2.new(1, -90, 0, 270),
|
||||
AnchorPoint = Vector2.new(1, 0),
|
||||
Text = "SkipDown",
|
||||
BackgroundColor3 = Color3.fromRGB(255, 255, 255),
|
||||
[Roact.Event.Activated] = self.skipDown,
|
||||
}),
|
||||
SkipAmount = Roact.createElement("TextBox", {
|
||||
Size = UDim2.new(0, 60, 0, 30),
|
||||
Position = UDim2.new(1, 0, 0, 270),
|
||||
AnchorPoint = Vector2.new(1, 0),
|
||||
BackgroundColor3 = Color3.fromRGB(255, 255, 255),
|
||||
Text = "SkipAmt",
|
||||
PlaceholderText = "Skip",
|
||||
ClearTextOnFocus = true,
|
||||
[Roact.Change.Text] = self.onChangeText,
|
||||
}),
|
||||
})
|
||||
end
|
||||
|
||||
local function generate(token)
|
||||
if token == 0 then
|
||||
return {color=Color3.fromRGB(255, 255, 255), width=50, token=0}
|
||||
end
|
||||
return {color=Color3.fromRGB(128-token, 255, 128+token), width=50+40*math.sin(token/5), token=token}
|
||||
end
|
||||
|
||||
function Story:init()
|
||||
local items = {}
|
||||
for i = -100,100 do table.insert(items, generate(i)) end
|
||||
self.state = {
|
||||
lock = 1,
|
||||
index = 101,
|
||||
skipAmount = 1,
|
||||
size = Vector2.new(200, -100),
|
||||
items = items,
|
||||
}
|
||||
self.indexData = {
|
||||
anchorIndex = 101,
|
||||
}
|
||||
|
||||
self.loadNext = function()
|
||||
self:setState({
|
||||
items = Cryo.List.join(self.state.items, {generate(self.state.items[#self.state.items].token + 1)}),
|
||||
})
|
||||
end
|
||||
|
||||
self.loadPrevious = function()
|
||||
self:setState({
|
||||
items = Cryo.List.join({generate(self.state.items[1].token - 1)}, self.state.items),
|
||||
})
|
||||
end
|
||||
|
||||
self.clickRefresh = function()
|
||||
print("Recentering")
|
||||
self:setState({
|
||||
lock = self.state.lock + 1,
|
||||
})
|
||||
end
|
||||
|
||||
self.clickUp = function()
|
||||
print("Moving up")
|
||||
self:setState({
|
||||
size = self.state.size + Vector2.new(0, -20),
|
||||
})
|
||||
end
|
||||
|
||||
self.clickDown = function()
|
||||
print("Moving down")
|
||||
self:setState({
|
||||
size = self.state.size + Vector2.new(0, 20),
|
||||
})
|
||||
end
|
||||
|
||||
self.clickLeft = function()
|
||||
print("Moving left")
|
||||
self:setState({
|
||||
size = self.state.size + Vector2.new(-20, 0),
|
||||
})
|
||||
end
|
||||
|
||||
self.clickRight = function()
|
||||
print("Moving right")
|
||||
self:setState({
|
||||
size = self.state.size + Vector2.new(20, 0),
|
||||
})
|
||||
end
|
||||
|
||||
self.skipUp = function()
|
||||
local newIndex = self.indexData.anchorIndex + self.state.skipAmount
|
||||
print("Skipping up to index:", newIndex)
|
||||
self:setState({
|
||||
lock = self.state.lock + 1,
|
||||
index = newIndex,
|
||||
})
|
||||
end
|
||||
|
||||
self.skipDown = function()
|
||||
local newIndex = self.indexData.anchorIndex - self.state.skipAmount
|
||||
print("Skipping down to index:", newIndex)
|
||||
self:setState({
|
||||
lock = self.state.lock + 1,
|
||||
index = newIndex,
|
||||
})
|
||||
end
|
||||
|
||||
self.onChangeText = function(rbx)
|
||||
local skipAmount = tonumber(rbx.Text)
|
||||
print("skipAmount:", skipAmount)
|
||||
if skipAmount then
|
||||
self:setState({
|
||||
skipAmount = skipAmount,
|
||||
})
|
||||
else
|
||||
rbx.Text = self.state.skipAmount
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return Story
|
||||
+513
@@ -0,0 +1,513 @@
|
||||
local InfiniteScroller = script:FindFirstAncestor("infinite-scroller")
|
||||
local Root = InfiniteScroller.Parent
|
||||
local Roact = require(Root.Roact)
|
||||
local Cryo = require(Root.Cryo)
|
||||
local Scroller = require(InfiniteScroller).Scroller
|
||||
local ComplexThing = require(script.Parent.ComplexThing)
|
||||
|
||||
local TextService = game:GetService("TextService")
|
||||
|
||||
local debugScroller = Roact.PureComponent:extend("debugScroller")
|
||||
|
||||
local COLORS = {
|
||||
DEFAULT = Color3.fromRGB(188, 188, 188),
|
||||
WHITE = Color3.fromRGB(244, 244, 244),
|
||||
BLACK = Color3.fromRGB(0, 0, 0),
|
||||
TRUE = Color3.fromRGB(188, 222, 188),
|
||||
FALSE = Color3.fromRGB(222, 188, 188),
|
||||
|
||||
FOCUS_INDEX = Color3.fromRGB(0, 255, 0),
|
||||
ANCHOR_LOCATION = Color3.fromRGB(0, 127, 255),
|
||||
DRAG_BUFFER = Color3.fromRGB(222, 0, 222),
|
||||
CANVAS = Color3.fromRGB(244, 188, 66),
|
||||
LEAD_INDEX = Color3.fromRGB(0, 255, 0),
|
||||
TRAIL_INDEX = Color3.fromRGB(255, 0, 0),
|
||||
ANCHOR_INDEX = Color3.fromRGB(255, 255, 0),
|
||||
PADDING = Color3.fromRGB(145, 88, 222),
|
||||
}
|
||||
|
||||
local COMPLEX_THING_SIZE = 128
|
||||
|
||||
local LAYOUT_ORDER_INDEX = 0
|
||||
function getNextLayout()
|
||||
LAYOUT_ORDER_INDEX = LAYOUT_ORDER_INDEX + 1
|
||||
return LAYOUT_ORDER_INDEX
|
||||
end
|
||||
|
||||
function makeLabel(text, value, color)
|
||||
return Roact.createElement("TextLabel", {
|
||||
Size = UDim2.new(1, 0, 0, 20),
|
||||
Text = string.format("%s: %s", text, tostring(value)),
|
||||
TextColor3 = color or COLORS.WHITE,
|
||||
TextXAlignment = Enum.TextXAlignment.Left,
|
||||
BorderSizePixel = 0,
|
||||
BackgroundTransparency = 1,
|
||||
LayoutOrder = getNextLayout(),
|
||||
})
|
||||
end
|
||||
|
||||
function makeButton(text, func, color)
|
||||
color = color or COLORS.DEFAULT
|
||||
return Roact.createElement("TextButton", {
|
||||
Size = UDim2.fromOffset(110, 30),
|
||||
BackgroundColor3 = color,
|
||||
TextWrapped = true,
|
||||
Text = text,
|
||||
[Roact.Event.Activated] = func,
|
||||
LayoutOrder = getNextLayout(),
|
||||
})
|
||||
end
|
||||
|
||||
function debugScroller:makeToggleButton(value)
|
||||
local function doToggle()
|
||||
self:setState({
|
||||
[value] = not self.state[value]
|
||||
})
|
||||
end
|
||||
return makeButton(value, doToggle, self.state[value] and COLORS.TRUE or COLORS.FALSE)
|
||||
end
|
||||
|
||||
function makeLabelLine(text, position, color, pointsRight)
|
||||
color = color or COLORS.BLACK
|
||||
local LINE_WIDTH = 20
|
||||
|
||||
local textSize = TextService:GetTextSize(text, 8, Enum.Font.Legacy, Vector2.new())
|
||||
return Roact.createElement("Frame", {
|
||||
Size = UDim2.fromOffset(textSize.X + LINE_WIDTH, textSize.Y),
|
||||
Position = position,
|
||||
AnchorPoint = pointsRight and Vector2.new(1, 0.5) or Vector2.new(0, 0.5),
|
||||
BackgroundTransparency = 1,
|
||||
}, {
|
||||
Roact.createFragment({
|
||||
layout = Roact.createElement("UIListLayout", {
|
||||
SortOrder = Enum.SortOrder.LayoutOrder,
|
||||
FillDirection = Enum.FillDirection.Horizontal,
|
||||
VerticalAlignment = Enum.VerticalAlignment.Center,
|
||||
}),
|
||||
labelLine = Roact.createElement("Frame", {
|
||||
Position = position,
|
||||
Size = UDim2.fromOffset(LINE_WIDTH, 1),
|
||||
BorderSizePixel = 0,
|
||||
BackgroundColor3 = color,
|
||||
LayoutOrder = 2,
|
||||
}),
|
||||
label = Roact.createElement("TextLabel", {
|
||||
AnchorPoint = Vector2.new(0, 0.5),
|
||||
Size = UDim2.new(1, -LINE_WIDTH, 0, 8),
|
||||
Text = text,
|
||||
TextColor3 = color,
|
||||
BackgroundTransparency = 1,
|
||||
LayoutOrder = pointsRight and 1 or 3
|
||||
})
|
||||
})
|
||||
})
|
||||
end
|
||||
|
||||
debugScroller.defaultProps = {
|
||||
anchorLocation = UDim.new(1, 0),
|
||||
mountingBuffer = 150,
|
||||
dragBuffer = 0,
|
||||
focusIndex = 1,
|
||||
|
||||
Size = UDim2.new(1, -20, 0, 100),
|
||||
numItems = 20,
|
||||
}
|
||||
|
||||
function debugScroller:init()
|
||||
self.initialState = {
|
||||
items = {},
|
||||
-- Scroller props. These can be changed by debugger buttons
|
||||
focusLock = 1,
|
||||
orientation = Scroller.Orientation.Up,
|
||||
clipsDescendants = false,
|
||||
nestedLayer = 1,
|
||||
|
||||
-- Scroller internals. Don't change these manually, meant for DISPLAY ONLY
|
||||
canvasPosition = 0,
|
||||
canvasSize = 0,
|
||||
paddingSize = -1,
|
||||
paddingPosition = 0,
|
||||
anchorLinePositionY = 0,
|
||||
leadIndex = -1,
|
||||
trailIndex = -1,
|
||||
anchorIndex = -1,
|
||||
}
|
||||
|
||||
self.mutableState = {
|
||||
loadPreviousEnabled = false,
|
||||
loadNextEnabled = false,
|
||||
}
|
||||
|
||||
for i = 1,self.props.numItems do
|
||||
table.insert(self.initialState.items, {id = i})
|
||||
end
|
||||
|
||||
self.state = Cryo.Dictionary.join(self.initialState, self.mutableState)
|
||||
|
||||
-- horsecat storybooks have a Y-offset that we need to address before using absolutePosition
|
||||
self.initialY, self.updateInitialY = Roact.createBinding(0)
|
||||
|
||||
self.ref = Roact.createRef()
|
||||
end
|
||||
|
||||
function debugScroller:render()
|
||||
return Roact.createElement("Frame", {
|
||||
Size=UDim2.new(1, 0, 1, 0),
|
||||
BackgroundTransparency = 1,
|
||||
[Roact.Change.AbsolutePosition] = function(rbx)
|
||||
self.updateInitialY(rbx.AbsolutePosition.Y)
|
||||
end
|
||||
}, {
|
||||
layout = Roact.createElement("UIListLayout", {
|
||||
SortOrder = Enum.SortOrder.LayoutOrder,
|
||||
FillDirection = Enum.FillDirection.Horizontal,
|
||||
}),
|
||||
visibilityFrame = Roact.createElement("Frame", {
|
||||
LayoutOrder = 1,
|
||||
Size = UDim2.new(0, 200, 1, 0),
|
||||
BackgroundTransparency = 1,
|
||||
}, {
|
||||
layout = Roact.createElement("UIListLayout", {
|
||||
SortOrder = Enum.SortOrder.LayoutOrder,
|
||||
}),
|
||||
anchorLocationLabel = makeLabel("anchorLocation", self.props.anchorLocation, COLORS.ANCHOR_LOCATION),
|
||||
anchorIndexLabel = makeLabel("anchorIndex", self.state.anchorIndex, COLORS.ANCHOR_INDEX),
|
||||
leadIndexLabel = makeLabel("leadIndex", self.state.leadIndex, COLORS.LEAD_INDEX),
|
||||
trailIndexLabel = makeLabel("trailIndex", self.state.trailIndex, COLORS.TRAIL_INDEX),
|
||||
canvasPositionLabel = makeLabel("canvasPosition", self.state.canvasPosition, COLORS.CANVAS),
|
||||
canvasSizeLabel = makeLabel("canvasSize", self.state.canvasSize, COLORS.CANVAS),
|
||||
paddingSizeLabel = makeLabel("size of padding Frame", self.state.paddingSize, COLORS.PADDING),
|
||||
|
||||
whiteSpace = Roact.createElement("Frame", { Size = UDim2.fromOffset(0, 20), BackgroundTransparency = 1, LayoutOrder = getNextLayout()}),
|
||||
|
||||
disableLoadPrevious = self:makeToggleButton("loadPreviousEnabled"),
|
||||
disableLoadNext = self:makeToggleButton("loadNextEnabled"),
|
||||
clipsDescendants = self:makeToggleButton("clipsDescendants"),
|
||||
}),
|
||||
|
||||
scrollerFrame = Roact.createElement("Frame", {
|
||||
LayoutOrder = 2,
|
||||
Size = UDim2.new(0, 160, 0, 300),
|
||||
BackgroundTransparency = 1,
|
||||
}, {
|
||||
scroller = Roact.createElement(Scroller, {
|
||||
ElasticBehavior = Enum.ElasticBehavior.Always,
|
||||
ClipsDescendants = self.state.clipsDescendants,
|
||||
Position = UDim2.fromOffset(0, 200),
|
||||
BackgroundColor3 = Color3.fromRGB(111, 111, 111),
|
||||
Size = self.props.Size,
|
||||
|
||||
orientation = self.state.orientation,
|
||||
padding = UDim.new(),
|
||||
itemList = self.state.items,
|
||||
focusIndex = self.props.focusIndex,
|
||||
focusLock = self.state.focusLock,
|
||||
anchorLocation = self.props.anchorLocation,
|
||||
dragBuffer = self.props.dragBuffer,
|
||||
mountingBuffer = self.props.mountingBuffer,
|
||||
estimatedItemSize = self.state.nestedLayer ~= 1 and COMPLEX_THING_SIZE or 20,
|
||||
[Roact.Ref] = self.ref,
|
||||
identifier = function(item)
|
||||
return item.id
|
||||
end,
|
||||
--recyclingDisabledFor={"ComplexThing"},
|
||||
renderItem = function(item, _)
|
||||
if self.state.nestedLayer ~= 1 then
|
||||
return Roact.createElement(ComplexThing, {
|
||||
Size = UDim2.fromOffset(COMPLEX_THING_SIZE, COMPLEX_THING_SIZE),
|
||||
nestedLayer = self.state.nestedLayer,
|
||||
})
|
||||
else
|
||||
local r = 88+88*math.sin(math.rad(8*item.id+90))
|
||||
local g = 88+44*math.sin(math.rad(8*item.id+0))
|
||||
local b = 88+88*math.sin(math.rad(8*item.id+180))
|
||||
|
||||
local leadIndexId = self.state.items[self.state.leadIndex] and self.state.items[self.state.leadIndex].id
|
||||
local trailIndexId = self.state.items[self.state.trailIndex] and self.state.items[self.state.trailIndex].id
|
||||
local anchorIndexId = self.state.items[self.state.anchorIndex] and self.state.items[self.state.anchorIndex].id
|
||||
|
||||
return Roact.createElement("Frame", {
|
||||
Size = UDim2.new(0, 20, 0, 20),
|
||||
BackgroundColor3 = Color3.fromRGB(r, g, b),
|
||||
}, {
|
||||
["INDEX" .. tostring(item.id)] = Roact.createElement("TextLabel", {
|
||||
Size = UDim2.new(1, 0, 1, 0),
|
||||
Text = item.id,
|
||||
TextColor3 = Color3.new(1, 1, 1),
|
||||
BackgroundTransparency = 1,
|
||||
}, {
|
||||
item.id == leadIndexId and makeLabelLine("leadIndex ",
|
||||
UDim2.fromScale(1, 0),
|
||||
COLORS.LEAD_INDEX,
|
||||
false),
|
||||
item.id == trailIndexId and makeLabelLine("trailIndex ",
|
||||
UDim2.fromScale(1, 0),
|
||||
COLORS.TRAIL_INDEX,
|
||||
false),
|
||||
item.id == anchorIndexId and makeLabelLine("anchorIndex ",
|
||||
UDim2.new(),
|
||||
COLORS.ANCHOR_INDEX,
|
||||
true)
|
||||
}),
|
||||
})
|
||||
end
|
||||
end,
|
||||
|
||||
loadPrevious = function()
|
||||
if not self.state.loadPreviousEnabled then
|
||||
return
|
||||
end
|
||||
local newItems = {}
|
||||
local n = self.state.items[1].id
|
||||
for i = n-10, n-1 do
|
||||
table.insert(newItems, {
|
||||
id = i,
|
||||
})
|
||||
end
|
||||
self:setState({
|
||||
items = Cryo.List.join(newItems, self.state.items)
|
||||
})
|
||||
end,
|
||||
|
||||
loadNext = function()
|
||||
if not self.state.loadNextEnabled then
|
||||
return
|
||||
end
|
||||
local newItems = {}
|
||||
local n = self.state.items[#self.state.items].id
|
||||
for i = n+1, n+10 do
|
||||
table.insert(newItems, {
|
||||
id = i,
|
||||
})
|
||||
end
|
||||
self:setState({
|
||||
items = Cryo.List.join(self.state.items, newItems)
|
||||
})
|
||||
end,
|
||||
|
||||
[Roact.Change.CanvasPosition] = function()
|
||||
if not self.ref.current then
|
||||
return
|
||||
end
|
||||
|
||||
local rbx = self.ref.current
|
||||
|
||||
-- this feels dirty, but allows us to visualize the padding frame
|
||||
local padding_rbx = rbx:FindFirstChild("padding")
|
||||
|
||||
local anchorLinePositionY = rbx.AbsolutePosition.Y - self.props.anchorLocation.Offset
|
||||
if self.state.orientation == Scroller.Orientation.Down then
|
||||
anchorLinePositionY = anchorLinePositionY + (1 - self.props.anchorLocation.Scale) * rbx.AbsoluteSize.Y
|
||||
elseif self.state.orientation == Scroller.Orientation.Up then
|
||||
anchorLinePositionY = anchorLinePositionY + self.props.anchorLocation.Scale * rbx.AbsoluteSize.Y
|
||||
else
|
||||
anchorLinePositionY = 0
|
||||
end
|
||||
|
||||
self:setState({
|
||||
canvasPosition = rbx.CanvasPosition.Y,
|
||||
canvasSize = rbx.CanvasSize.Y.Offset,
|
||||
paddingSize = padding_rbx.Size.Y.Offset,
|
||||
|
||||
anchorLinePositionY = anchorLinePositionY,
|
||||
paddingPosition = padding_rbx.AbsolutePosition.Y,
|
||||
})
|
||||
end,
|
||||
|
||||
onScrollUpdate = function(indices)
|
||||
self.state.leadIndex = indices.leadIndex
|
||||
self.state.anchorIndex = indices.anchorIndex
|
||||
self.state.trailIndex = indices.trailIndex
|
||||
end
|
||||
}),
|
||||
|
||||
anchorLine = self.ref.current and makeLabelLine("anchorLocation ",
|
||||
UDim2.fromOffset(20, self.state.anchorLinePositionY - self.initialY:getValue()),
|
||||
COLORS.ANCHOR_LOCATION,
|
||||
true),
|
||||
|
||||
dragBuffer1 = self.ref.current and self.props.dragBuffer ~= 0 and makeLabelLine("dragBuffer ",
|
||||
UDim2.fromOffset(20, self.props.dragBuffer + self.ref.current.AbsolutePosition.Y - self.initialY:getValue()),
|
||||
COLORS.DRAG_BUFFER,
|
||||
true),
|
||||
|
||||
dragBuffer2 = self.ref.current and self.props.dragBuffer ~= 0 and makeLabelLine("dragBuffer ",
|
||||
UDim2.fromOffset(20, self.ref.current.AbsoluteSize.Y - self.props.dragBuffer + self.ref.current.AbsolutePosition.Y - self.initialY:getValue()),
|
||||
COLORS.DRAG_BUFFER,
|
||||
true),
|
||||
|
||||
mountingBuffer1 = self.ref.current and makeLabelLine("mountingBuffer ",
|
||||
UDim2.fromOffset(20, -self.props.mountingBuffer + self.ref.current.AbsolutePosition.Y - self.initialY:getValue()),
|
||||
COLORS.WHITE,
|
||||
true),
|
||||
|
||||
mountingBuffer2 = self.ref.current and makeLabelLine("mountingBuffer ",
|
||||
UDim2.fromOffset(20, self.ref.current.AbsoluteSize.Y + self.props.mountingBuffer + self.ref.current.AbsolutePosition.Y - self.initialY:getValue()),
|
||||
COLORS.WHITE,
|
||||
true),
|
||||
|
||||
canvasEstimate = self.ref.current and Roact.createElement("Frame", {
|
||||
Size = UDim2.fromOffset(40, self.state.canvasSize),
|
||||
Position = UDim2.fromOffset(20, self.state.paddingPosition - self.initialY:getValue()),
|
||||
BackgroundColor3 = COLORS.CANVAS,
|
||||
BorderSizePixel = 0,
|
||||
ZIndex = -10,
|
||||
}),
|
||||
|
||||
paddingEstimate = self.ref.current and Roact.createElement("Frame", {
|
||||
Size = UDim2.fromOffset(30, self.state.paddingSize),
|
||||
Position = UDim2.fromOffset(0, self.state.paddingPosition - self.initialY:getValue()),
|
||||
BackgroundColor3 = COLORS.PADDING,
|
||||
BorderSizePixel = 0,
|
||||
ZIndex = -9,
|
||||
}),
|
||||
}),
|
||||
operationsFrame = Roact.createElement("Frame", {
|
||||
LayoutOrder = 3,
|
||||
Size = UDim2.new(0, 100, 1, 0),
|
||||
BackgroundTransparency = 1,
|
||||
}, {
|
||||
layout = Roact.createElement("UIListLayout", {
|
||||
SortOrder = Enum.SortOrder.LayoutOrder,
|
||||
}),
|
||||
reset = makeButton("Reset ItemList", function()
|
||||
local newState = Cryo.Dictionary.join(self.initialState, {
|
||||
focusLock = self.state.focusLock + 1,
|
||||
loadNext = self.state.loadNext,
|
||||
loadPrev = self.state.loadPrev,
|
||||
clipsDescendants = self.state.clipsDescendants,
|
||||
})
|
||||
self:setState(newState)
|
||||
end),
|
||||
|
||||
-- Reversing the Orientation currently does not call resize, does not update the anchorLocation
|
||||
-- reverse = makeButton("Reverse Orientation", function()
|
||||
-- local newOrientation
|
||||
-- if self.state.orientation == Scroller.Orientation.Down then
|
||||
-- newOrientation = Scroller.Orientation.Up
|
||||
-- else
|
||||
-- newOrientation = Scroller.Orientation.Down
|
||||
-- end
|
||||
-- self:setState({
|
||||
-- orientation = newOrientation,
|
||||
-- focusLock = self.state.focusLock + 1,
|
||||
-- })
|
||||
-- end),
|
||||
|
||||
rotateForward = makeButton("Rotate Forward", function()
|
||||
local nextItems = {}
|
||||
local numItems = #self.state.items
|
||||
local a = self.state.items[numItems]
|
||||
table.insert(nextItems, a)
|
||||
for i = 1, numItems-1 do
|
||||
table.insert(nextItems, self.state.items[i])
|
||||
end
|
||||
|
||||
self:setState({
|
||||
focusLock = self.state.focusLock + 1,
|
||||
items = nextItems,
|
||||
})
|
||||
end),
|
||||
|
||||
rotateBack = makeButton("Rotate Backward", function()
|
||||
local nextItems = {}
|
||||
local a = self.state.items[1]
|
||||
for i = 2, #self.state.items do
|
||||
table.insert(nextItems, self.state.items[i])
|
||||
end
|
||||
table.insert(nextItems, a)
|
||||
|
||||
self:setState({
|
||||
focusLock = self.state.focusLock + 1,
|
||||
items = nextItems,
|
||||
})
|
||||
end),
|
||||
|
||||
insertFront = makeButton("Insert Front", function()
|
||||
local nextItems = {}
|
||||
table.insert(nextItems, {id = self.state.items[1].id-1 })
|
||||
for k, v in pairs(self.state.items) do
|
||||
table.insert(nextItems, v)
|
||||
end
|
||||
|
||||
self:setState({
|
||||
focusLock = self.state.focusLock + 1,
|
||||
items = nextItems,
|
||||
})
|
||||
end),
|
||||
|
||||
insertBack = makeButton("Insert Back", function()
|
||||
local nextItems = {}
|
||||
for k, v in pairs(self.state.items) do
|
||||
table.insert(nextItems, v)
|
||||
end
|
||||
table.insert(nextItems, {id = self.state.items[#self.state.items].id+1 })
|
||||
|
||||
self:setState({
|
||||
focusLock = self.state.focusLock + 1,
|
||||
items = nextItems,
|
||||
})
|
||||
end),
|
||||
|
||||
removeFront = makeButton("Remove Front", function()
|
||||
local nextItems = {}
|
||||
local numItems = #self.state.items
|
||||
for i = 2, numItems do
|
||||
table.insert(nextItems, self.state.items[i])
|
||||
end
|
||||
|
||||
self:setState({
|
||||
focusLock = self.state.focusLock + 1,
|
||||
items = nextItems,
|
||||
})
|
||||
end),
|
||||
|
||||
removeBack = makeButton("Remove Back", function()
|
||||
local nextItems = {}
|
||||
local numItems = #self.state.items
|
||||
for i = 1, numItems-1 do
|
||||
table.insert(nextItems, self.state.items[i])
|
||||
end
|
||||
|
||||
self:setState({
|
||||
focusLock = self.state.focusLock + 1,
|
||||
items = nextItems,
|
||||
})
|
||||
end),
|
||||
|
||||
|
||||
reverseList = makeButton("Reverse List", function()
|
||||
local nextItems = {}
|
||||
local numItems = #self.state.items
|
||||
for i = 1, numItems do
|
||||
nextItems[i] = self.state.items[numItems - i + 1]
|
||||
end
|
||||
|
||||
self:setState({
|
||||
focusLock = self.state.focusLock + 1,
|
||||
items = nextItems,
|
||||
})
|
||||
end),
|
||||
|
||||
scrollUpOnce = makeButton("Scroll Up 1px", function()
|
||||
if self.ref.current then
|
||||
self.ref.current.CanvasPosition = self.ref.current.CanvasPosition - Vector2.new(0, 1)
|
||||
end
|
||||
end),
|
||||
|
||||
scrollDownOnce = makeButton("Scroll Down 1px", function()
|
||||
if self.ref.current then
|
||||
self.ref.current.CanvasPosition = self.ref.current.CanvasPosition + Vector2.new(0, 1)
|
||||
end
|
||||
end),
|
||||
|
||||
toggleComplexity = makeButton("Toggle Complexity", function()
|
||||
self:setState({
|
||||
nestedLayer = self.state.nestedLayer%5 + 1
|
||||
})
|
||||
end),
|
||||
})
|
||||
})
|
||||
end
|
||||
|
||||
return debugScroller
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
local Scroller = require(script.Components.Scroller)
|
||||
|
||||
return {
|
||||
Scroller = Scroller,
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
# Generated by Rotriever. Format subject to change in future releases.
|
||||
name = "roblox/infinite-scroller"
|
||||
version = "0.5.6"
|
||||
commit = "d622d74bec4a599c5f8ef642194fa9eaf973b5c0"
|
||||
source = "url+https://github.com/roblox/infinite-scroller"
|
||||
dependencies = [
|
||||
"Cryo roblox/cryo 1.0.0 url+https://github.com/roblox/cryo",
|
||||
"FitFrame roblox/roact-fit-components 1.2.5 url+https://github.com/roblox/roact-fit-components",
|
||||
"Otter roblox/otter 0.1.2 url+https://github.com/roblox/otter",
|
||||
"Roact roblox/roact 1.3.0 url+https://github.com/roblox/roact",
|
||||
"t roblox/t 1.2.5 url+https://github.com/roblox/t",
|
||||
]
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
--[[
|
||||
Package link auto-generated by Rotriever
|
||||
]]
|
||||
local PackageIndex = script.Parent.Parent
|
||||
|
||||
local package = PackageIndex["roblox_t"]["t"]
|
||||
|
||||
if package.ClassName == "ModuleScript" then
|
||||
return require(package)
|
||||
end
|
||||
|
||||
return package
|
||||
Reference in New Issue
Block a user