add gs
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"language": {
|
||||
"mode": "nocheck"
|
||||
},
|
||||
"lint": {
|
||||
"*": "disabled"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
--[[
|
||||
Package link auto-generated by Rotriever
|
||||
]]
|
||||
local PackageIndex = script.Parent._Index
|
||||
|
||||
local package = PackageIndex["AvatarExperienceDeps"]["AvatarExperienceDeps"]
|
||||
|
||||
if package.ClassName == "ModuleScript" then
|
||||
return require(package)
|
||||
end
|
||||
|
||||
return package
|
||||
@@ -0,0 +1,12 @@
|
||||
--[[
|
||||
Package link auto-generated by Rotriever
|
||||
]]
|
||||
local PackageIndex = script.Parent._Index
|
||||
|
||||
local package = PackageIndex["roblox_cryo"]["cryo"]
|
||||
|
||||
if package.ClassName == "ModuleScript" then
|
||||
return require(package)
|
||||
end
|
||||
|
||||
return package
|
||||
@@ -0,0 +1,12 @@
|
||||
--[[
|
||||
Package link auto-generated by Rotriever
|
||||
]]
|
||||
local PackageIndex = script.Parent.Parent._Index
|
||||
|
||||
local package = PackageIndex["roblox_rhodium"]["rhodium"]
|
||||
|
||||
if package.ClassName == "ModuleScript" then
|
||||
return require(package)
|
||||
end
|
||||
|
||||
return package
|
||||
@@ -0,0 +1,12 @@
|
||||
--[[
|
||||
Package link auto-generated by Rotriever
|
||||
]]
|
||||
local PackageIndex = script.Parent.Parent._Index
|
||||
|
||||
local package = PackageIndex["roblox_testez"]["testez"]
|
||||
|
||||
if package.ClassName == "ModuleScript" then
|
||||
return require(package)
|
||||
end
|
||||
|
||||
return package
|
||||
@@ -0,0 +1,12 @@
|
||||
--[[
|
||||
Package link auto-generated by Rotriever
|
||||
]]
|
||||
local PackageIndex = script.Parent._Index
|
||||
|
||||
local package = PackageIndex["InGameMenuDependencies"]["InGameMenuDependencies"]
|
||||
|
||||
if package.ClassName == "ModuleScript" then
|
||||
return require(package)
|
||||
end
|
||||
|
||||
return package
|
||||
@@ -0,0 +1,12 @@
|
||||
--[[
|
||||
Package link auto-generated by Rotriever
|
||||
]]
|
||||
local PackageIndex = script.Parent._Index
|
||||
|
||||
local package = PackageIndex["LuaChatDeps"]["LuaChatDeps"]
|
||||
|
||||
if package.ClassName == "ModuleScript" then
|
||||
return require(package)
|
||||
end
|
||||
|
||||
return package
|
||||
@@ -0,0 +1,12 @@
|
||||
--[[
|
||||
Package link auto-generated by Rotriever
|
||||
]]
|
||||
local PackageIndex = script.Parent._Index
|
||||
|
||||
local package = PackageIndex["LuaDiscussionsDeps"]["LuaDiscussionsDeps"]
|
||||
|
||||
if package.ClassName == "ModuleScript" then
|
||||
return require(package)
|
||||
end
|
||||
|
||||
return package
|
||||
@@ -0,0 +1,12 @@
|
||||
--[[
|
||||
Package link auto-generated by Rotriever
|
||||
]]
|
||||
local PackageIndex = script.Parent._Index
|
||||
|
||||
local package = PackageIndex["LuaSocialLibrariesDeps"]["LuaSocialLibrariesDeps"]
|
||||
|
||||
if package.ClassName == "ModuleScript" then
|
||||
return require(package)
|
||||
end
|
||||
|
||||
return package
|
||||
@@ -0,0 +1,12 @@
|
||||
--[[
|
||||
Package link auto-generated by Rotriever
|
||||
]]
|
||||
local PackageIndex = script.Parent._Index
|
||||
|
||||
local package = PackageIndex["roblox_lumberyak"]["lumberyak"]
|
||||
|
||||
if package.ClassName == "ModuleScript" then
|
||||
return require(package)
|
||||
end
|
||||
|
||||
return package
|
||||
@@ -0,0 +1,12 @@
|
||||
--[[
|
||||
Package link auto-generated by Rotriever
|
||||
]]
|
||||
local PackageIndex = script.Parent._Index
|
||||
|
||||
local package = PackageIndex["roblox_otter"]["otter"]
|
||||
|
||||
if package.ClassName == "ModuleScript" then
|
||||
return require(package)
|
||||
end
|
||||
|
||||
return package
|
||||
@@ -0,0 +1,12 @@
|
||||
--[[
|
||||
Package link auto-generated by Rotriever
|
||||
]]
|
||||
local PackageIndex = script.Parent._Index
|
||||
|
||||
local package = PackageIndex["roblox_lua-roact-policy-provider"]["lua-roact-policy-provider"]
|
||||
|
||||
if package.ClassName == "ModuleScript" then
|
||||
return require(package)
|
||||
end
|
||||
|
||||
return package
|
||||
@@ -0,0 +1,12 @@
|
||||
--[[
|
||||
Package link auto-generated by Rotriever
|
||||
]]
|
||||
local PackageIndex = script.Parent._Index
|
||||
|
||||
local package = PackageIndex["PremiumUpsellDeps"]["PremiumUpsellDeps"]
|
||||
|
||||
if package.ClassName == "ModuleScript" then
|
||||
return require(package)
|
||||
end
|
||||
|
||||
return package
|
||||
@@ -0,0 +1,12 @@
|
||||
--[[
|
||||
Package link auto-generated by Rotriever
|
||||
]]
|
||||
local PackageIndex = script.Parent._Index
|
||||
|
||||
local package = PackageIndex["lua-promise"]["lua-promise"]
|
||||
|
||||
if package.ClassName == "ModuleScript" then
|
||||
return require(package)
|
||||
end
|
||||
|
||||
return package
|
||||
@@ -0,0 +1,12 @@
|
||||
--[[
|
||||
Package link auto-generated by Rotriever
|
||||
]]
|
||||
local PackageIndex = script.Parent._Index
|
||||
|
||||
local package = PackageIndex["roblox_purchase-prompt"]["purchase-prompt"]
|
||||
|
||||
if package.ClassName == "ModuleScript" then
|
||||
return require(package)
|
||||
end
|
||||
|
||||
return package
|
||||
@@ -0,0 +1,12 @@
|
||||
--[[
|
||||
Package link auto-generated by Rotriever
|
||||
]]
|
||||
local PackageIndex = script.Parent._Index
|
||||
|
||||
local package = PackageIndex["roblox_lua-result"]["lua-result"]
|
||||
|
||||
if package.ClassName == "ModuleScript" then
|
||||
return require(package)
|
||||
end
|
||||
|
||||
return package
|
||||
@@ -0,0 +1,12 @@
|
||||
--[[
|
||||
Package link auto-generated by Rotriever
|
||||
]]
|
||||
local PackageIndex = script.Parent._Index
|
||||
|
||||
local package = PackageIndex["roblox_roact"]["roact"]
|
||||
|
||||
if package.ClassName == "ModuleScript" then
|
||||
return require(package)
|
||||
end
|
||||
|
||||
return package
|
||||
@@ -0,0 +1,12 @@
|
||||
--[[
|
||||
Package link auto-generated by Rotriever
|
||||
]]
|
||||
local PackageIndex = script.Parent._Index
|
||||
|
||||
local package = PackageIndex["roblox_roact-gamepad"]["roact-gamepad"]
|
||||
|
||||
if package.ClassName == "ModuleScript" then
|
||||
return require(package)
|
||||
end
|
||||
|
||||
return package
|
||||
@@ -0,0 +1,12 @@
|
||||
--[[
|
||||
Package link auto-generated by Rotriever
|
||||
]]
|
||||
local PackageIndex = script.Parent._Index
|
||||
|
||||
local package = PackageIndex["roblox_roact-navigation"]["roact-navigation"]
|
||||
|
||||
if package.ClassName == "ModuleScript" then
|
||||
return require(package)
|
||||
end
|
||||
|
||||
return package
|
||||
@@ -0,0 +1,12 @@
|
||||
--[[
|
||||
Package link auto-generated by Rotriever
|
||||
]]
|
||||
local PackageIndex = script.Parent._Index
|
||||
|
||||
local package = PackageIndex["roblox_roact-rodux"]["roact-rodux"]
|
||||
|
||||
if package.ClassName == "ModuleScript" then
|
||||
return require(package)
|
||||
end
|
||||
|
||||
return package
|
||||
@@ -0,0 +1,12 @@
|
||||
--[[
|
||||
Package link auto-generated by Rotriever
|
||||
]]
|
||||
local PackageIndex = script.Parent._Index
|
||||
|
||||
local package = PackageIndex["roblox_rodux"]["rodux"]
|
||||
|
||||
if package.ClassName == "ModuleScript" then
|
||||
return require(package)
|
||||
end
|
||||
|
||||
return package
|
||||
@@ -0,0 +1,12 @@
|
||||
--[[
|
||||
Package link auto-generated by Rotriever
|
||||
]]
|
||||
local PackageIndex = script.Parent._Index
|
||||
|
||||
local package = PackageIndex["roblox_string-utilities"]["string-utilities"]
|
||||
|
||||
if package.ClassName == "ModuleScript" then
|
||||
return require(package)
|
||||
end
|
||||
|
||||
return package
|
||||
@@ -0,0 +1,12 @@
|
||||
--[[
|
||||
Package link auto-generated by Rotriever
|
||||
]]
|
||||
local PackageIndex = script.Parent._Index
|
||||
|
||||
local package = PackageIndex["UIBlox"]["UIBlox"]
|
||||
|
||||
if package.ClassName == "ModuleScript" then
|
||||
return require(package)
|
||||
end
|
||||
|
||||
return package
|
||||
@@ -0,0 +1,12 @@
|
||||
--[[
|
||||
Package link auto-generated by Rotriever
|
||||
]]
|
||||
local PackageIndex = script.Parent._Index
|
||||
|
||||
local package = PackageIndex["roblox_url-builder"]["url-builder"]
|
||||
|
||||
if package.ClassName == "ModuleScript" then
|
||||
return require(package)
|
||||
end
|
||||
|
||||
return package
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
local AvatarExperineceDeps = script.Parent
|
||||
|
||||
return {
|
||||
RoactFitComponents = require(AvatarExperineceDeps.RoactFitComponents),
|
||||
}
|
||||
+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
|
||||
@@ -0,0 +1,6 @@
|
||||
# Generated by Rotriever. Format subject to change in future releases.
|
||||
name = "AvatarExperienceDeps"
|
||||
version = "0.0.1"
|
||||
commit = "5a31b41867d2c5ebf0b5670d9be27f3edd403545"
|
||||
source = "git+https://github.com/roblox/avatar-experience-deps#master"
|
||||
dependencies = ["RoactFitComponents roblox/roact-fit-components 1.2.5 url+https://github.com/roblox/roact-fit-components"]
|
||||
+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 @@
|
||||
local InGameMenuDependencies = script.Parent
|
||||
|
||||
return {
|
||||
Roact = require(InGameMenuDependencies.Roact),
|
||||
Rodux = require(InGameMenuDependencies.Rodux),
|
||||
RoactRodux = require(InGameMenuDependencies.RoactRodux),
|
||||
UIBlox = require(InGameMenuDependencies.UIBlox),
|
||||
Otter = require(InGameMenuDependencies.Otter),
|
||||
Cryo = require(InGameMenuDependencies.Cryo),
|
||||
t = require(InGameMenuDependencies.t),
|
||||
PolicyProvider = require(InGameMenuDependencies.PolicyProvider),
|
||||
}
|
||||
+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_lua-roact-policy-provider"]["lua-roact-policy-provider"]
|
||||
|
||||
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
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
--[[
|
||||
Package link auto-generated by Rotriever
|
||||
]]
|
||||
local PackageIndex = script.Parent.Parent
|
||||
|
||||
local package = PackageIndex["roblox_roact-rodux"]["roact-rodux"]
|
||||
|
||||
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_rodux"]["rodux"]
|
||||
|
||||
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["UIBlox"]["UIBlox"]
|
||||
|
||||
if package.ClassName == "ModuleScript" then
|
||||
return require(package)
|
||||
end
|
||||
|
||||
return package
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
# Generated by Rotriever. Format subject to change in future releases.
|
||||
name = "InGameMenuDependencies"
|
||||
version = "0.1.0"
|
||||
commit = "aecc56c1fa6348886a1073785dbb196b655a0a90"
|
||||
source = "git+https://github.rbx.com/roblox/in-game-menu-dependencies#master"
|
||||
dependencies = [
|
||||
"Cryo roblox/cryo 1.0.0 url+https://github.com/roblox/cryo",
|
||||
"Otter roblox/otter 0.1.2 url+https://github.com/roblox/otter",
|
||||
"PolicyProvider roblox/lua-roact-policy-provider 1d595dae git+https://github.com/roblox/lua-roact-policy-provider#master",
|
||||
"Roact roblox/roact 1.3.0 url+https://github.com/roblox/roact",
|
||||
"RoactRodux roblox/roact-rodux 0.2.2 url+https://github.com/roblox/roact-rodux",
|
||||
"Rodux roblox/rodux 1.0.0 url+https://github.com/roblox/rodux",
|
||||
"UIBlox <patched> UIBlox a253d523 git+https://github.com/roblox/uiblox#master",
|
||||
"t roblox/t 1.2.5 url+https://github.com/roblox/t",
|
||||
]
|
||||
@@ -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
|
||||
@@ -0,0 +1,12 @@
|
||||
--[[
|
||||
Package link auto-generated by Rotriever
|
||||
]]
|
||||
local PackageIndex = script.Parent.Parent
|
||||
|
||||
local package = PackageIndex["asset-card"]["asset-card"]
|
||||
|
||||
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_infinite-scroller-98304e77-0.5.6"]["infinite-scroller"]
|
||||
|
||||
if package.ClassName == "ModuleScript" then
|
||||
return require(package)
|
||||
end
|
||||
|
||||
return package
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
return function()
|
||||
it("SHOULD initialize UIBlox when required", function()
|
||||
local LuaChatDeps = require(script.Parent)
|
||||
expect(LuaChatDeps.UIBlox.Config).to.be.ok()
|
||||
end)
|
||||
end
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
return {
|
||||
fixToastResizeConfig = true,
|
||||
expandableTextAutomaticResizeConfig = true,
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
local LuaChatDeps = script.Parent
|
||||
|
||||
-- initialize UIBlox once here, there should be no other
|
||||
-- consumers of this instance of UIBlox
|
||||
local UIBloxConfig = require(script.config.UIBlox)
|
||||
local UIBlox = require(LuaChatDeps.UIBlox)
|
||||
UIBlox.init(UIBloxConfig)
|
||||
|
||||
return {
|
||||
InfiniteScroll = require(LuaChatDeps.InfiniteScroller),
|
||||
RoduxNetworking = require(LuaChatDeps.RoduxNetworking),
|
||||
UIBlox = UIBlox,
|
||||
AssetCard = require(LuaChatDeps.AssetCard),
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
--[[
|
||||
Package link auto-generated by Rotriever
|
||||
]]
|
||||
local PackageIndex = script.Parent.Parent
|
||||
|
||||
local package = PackageIndex["rodux-networking"]["rodux-networking"]
|
||||
|
||||
if package.ClassName == "ModuleScript" then
|
||||
return require(package)
|
||||
end
|
||||
|
||||
return package
|
||||
@@ -0,0 +1,12 @@
|
||||
--[[
|
||||
Package link auto-generated by Rotriever
|
||||
]]
|
||||
local PackageIndex = script.Parent.Parent
|
||||
|
||||
local package = PackageIndex["UIBlox"]["UIBlox"]
|
||||
|
||||
if package.ClassName == "ModuleScript" then
|
||||
return require(package)
|
||||
end
|
||||
|
||||
return package
|
||||
@@ -0,0 +1,11 @@
|
||||
# Generated by Rotriever. Format subject to change in future releases.
|
||||
name = "LuaChatDeps"
|
||||
version = "0.1.3"
|
||||
commit = "6144362fd181fe94fd213ec8569ba95f0a61faed"
|
||||
source = "git+https://github.rbx.com/roblox/lua-chat-deps#master"
|
||||
dependencies = [
|
||||
"AssetCard asset-card c7b683fb git+https://github.com/roblox/asset-card#v1.0.2",
|
||||
"InfiniteScroller roblox/infinite-scroller 0.5.6 url+https://github.com/roblox/infinite-scroller",
|
||||
"RoduxNetworking rodux-networking ea19cfe3 git+https://github.rbx.com/roblox/rodux-networking#v1.0.1",
|
||||
"UIBlox UIBlox a253d523 git+https://github.com/roblox/uiblox#master",
|
||||
]
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
--[[
|
||||
Package link auto-generated by Rotriever
|
||||
]]
|
||||
local PackageIndex = script.Parent.Parent
|
||||
|
||||
local package = PackageIndex["roblox_infinite-scroller-98304e77-0.3.4"]["infinite-scroller"]
|
||||
|
||||
if package.ClassName == "ModuleScript" then
|
||||
return require(package)
|
||||
end
|
||||
|
||||
return package
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
local LuaDiscussionsDeps = script.Parent
|
||||
|
||||
return {
|
||||
InfiniteScroll = require(LuaDiscussionsDeps.InfiniteScroll),
|
||||
RoactFitComponents = require(LuaDiscussionsDeps.RoactFitComponents),
|
||||
RoactNavigation = require(LuaDiscussionsDeps.RoactNavigation),
|
||||
RoduxNetworking = require(LuaDiscussionsDeps.RoduxNetworking),
|
||||
}
|
||||
+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["roact-navigation"]["roact-navigation"]
|
||||
|
||||
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["rodux-networking"]["rodux-networking"]
|
||||
|
||||
if package.ClassName == "ModuleScript" then
|
||||
return require(package)
|
||||
end
|
||||
|
||||
return package
|
||||
@@ -0,0 +1,11 @@
|
||||
# Generated by Rotriever. Format subject to change in future releases.
|
||||
name = "LuaDiscussionsDeps"
|
||||
version = "0.1.2"
|
||||
commit = "dfba285e3dd4e0fe5059b93d52880666e2924612"
|
||||
source = "git+https://github.rbx.com/roblox/lua-discussions-deps#master"
|
||||
dependencies = [
|
||||
"InfiniteScroll roblox/infinite-scroller 0.3.4 url+https://github.com/roblox/infinite-scroller",
|
||||
"RoactFitComponents roblox/roact-fit-components 1.2.5 url+https://github.com/roblox/roact-fit-components",
|
||||
"RoactNavigation roact-navigation 0.1.1-linter-fix url+https://github.com/roblox/roact-navigation",
|
||||
"RoduxNetworking rodux-networking ea19cfe3 git+https://github.rbx.com/roblox/rodux-networking#v1.0.1",
|
||||
]
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
--[[
|
||||
Package link auto-generated by Rotriever
|
||||
]]
|
||||
local PackageIndex = script.Parent.Parent
|
||||
|
||||
local package = PackageIndex["roblox_genericpagination"]["genericpagination"]
|
||||
|
||||
if package.ClassName == "ModuleScript" then
|
||||
return require(package)
|
||||
end
|
||||
|
||||
return package
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
local LuaSocialLibrariesDeps = script.Parent
|
||||
|
||||
return {
|
||||
GenericPagination = require(LuaSocialLibrariesDeps.GenericPagination),
|
||||
RoactFitComponents = require(LuaSocialLibrariesDeps.RoactFitComponents),
|
||||
Mock = require(LuaSocialLibrariesDeps.Mock),
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
--[[
|
||||
Package link auto-generated by Rotriever
|
||||
]]
|
||||
local PackageIndex = script.Parent.Parent
|
||||
|
||||
local package = PackageIndex["jtaylor_mock"]["mock"]
|
||||
|
||||
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
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
# Generated by Rotriever. Format subject to change in future releases.
|
||||
name = "LuaSocialLibrariesDeps"
|
||||
version = "0.1.1"
|
||||
commit = "6d4213307f9d059e422026c5f8ad1a37a3489a9b"
|
||||
source = "git+https://github.rbx.com/roblox/lua-social-libraries-deps#master"
|
||||
dependencies = [
|
||||
"GenericPagination roblox/genericpagination 6cc56178 git+https://github.rbx.com/roblox/genericpagination#master",
|
||||
"Mock jtaylor/mock d2c4005c git+https://github.rbx.com/roblox/mock#master",
|
||||
"RoactFitComponents roblox/roact-fit-components 1.2.5 url+https://github.com/roblox/roact-fit-components",
|
||||
]
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
local PremiumUpsellDeps = script.Parent
|
||||
|
||||
return {
|
||||
RoactFitComponents = require(PremiumUpsellDeps.RoactFitComponents),
|
||||
}
|
||||
+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
|
||||
@@ -0,0 +1,6 @@
|
||||
# Generated by Rotriever. Format subject to change in future releases.
|
||||
name = "PremiumUpsellDeps"
|
||||
version = "0.0.0"
|
||||
commit = "c51030b70236f2e9d69bb34348b7e045c2c437f6"
|
||||
source = "git+https://github.com/roblox/premium-upsell-deps#master"
|
||||
dependencies = ["RoactFitComponents roblox/roact-fit-components 1.2.5 url+https://github.com/roblox/roact-fit-components"]
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -0,0 +1,12 @@
|
||||
--[[
|
||||
Package link auto-generated by Rotriever
|
||||
]]
|
||||
local PackageIndex = script.Parent.Parent
|
||||
|
||||
local package = PackageIndex["roblox_infinite-scroller-98304e77-0.5.6"]["infinite-scroller"]
|
||||
|
||||
if package.ClassName == "ModuleScript" then
|
||||
return require(package)
|
||||
end
|
||||
|
||||
return package
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -0,0 +1,12 @@
|
||||
--[[
|
||||
Package link auto-generated by Rotriever
|
||||
]]
|
||||
local PackageIndex = script.Parent.Parent
|
||||
|
||||
local package = PackageIndex["roblox_roact-gamepad"]["roact-gamepad"]
|
||||
|
||||
if package.ClassName == "ModuleScript" then
|
||||
return require(package)
|
||||
end
|
||||
|
||||
return package
|
||||
+314
@@ -0,0 +1,314 @@
|
||||
local AccordionRoot = script.Parent
|
||||
local AppRoot = AccordionRoot.Parent
|
||||
local UIBloxRoot = AppRoot.Parent
|
||||
local Packages = UIBloxRoot.Parent
|
||||
|
||||
local Roact = require(Packages.Roact)
|
||||
local t = require(Packages.t)
|
||||
local SpringAnimatedItem = require(UIBloxRoot.Utility.SpringAnimatedItem)
|
||||
|
||||
local ITEM_PADDING = 10
|
||||
local ITEM_WIDTH_SHRINK_STEP = 20 -- How much each item shrinks below card above it
|
||||
local COMPACT_VIEW_PLACEHOLDER_HEIGHT = 10
|
||||
local PRESSED_SCALE = 0.9
|
||||
|
||||
local ANIMATION_SPRING_SETTINGS = {
|
||||
dampingRatio = 1,
|
||||
frequency = 3.5,
|
||||
}
|
||||
|
||||
local AccordionView = Roact.PureComponent:extend("AccordionView")
|
||||
|
||||
AccordionView.defaultProps = {
|
||||
maxItemsInCompactView = 3,
|
||||
}
|
||||
|
||||
local validateProps = t.strictInterface({
|
||||
items = t.table,
|
||||
itemWidth = t.number,
|
||||
itemHeight = t.number,
|
||||
renderItem = t.callback,
|
||||
|
||||
placeholderColor = t.Color3,
|
||||
placeholderBaseTransparency = t.number,
|
||||
|
||||
collapseButtonSize = t.number,
|
||||
renderCollapseButton = t.callback,
|
||||
|
||||
LayoutOrder = t.optional(t.integer),
|
||||
maxItemsInCompactView = t.numberPositive,
|
||||
})
|
||||
|
||||
function AccordionView:init()
|
||||
self.state = {
|
||||
expanded = false,
|
||||
isExpandButtonPressed = false,
|
||||
}
|
||||
|
||||
self.onExpandButtonActivated = function()
|
||||
self:setState({
|
||||
expanded = true,
|
||||
isExpandButtonPressed = false,
|
||||
})
|
||||
end
|
||||
|
||||
self.onCollapseButtonActivated = function()
|
||||
self:setState({
|
||||
expanded = false,
|
||||
})
|
||||
end
|
||||
|
||||
self.onExpandButtonInputBegan = function(_, inputObject)
|
||||
if inputObject.UserInputState == Enum.UserInputState.Begin and
|
||||
(inputObject.UserInputType == Enum.UserInputType.Touch or
|
||||
inputObject.UserInputType == Enum.UserInputType.MouseButton1) then
|
||||
self:setState({
|
||||
isExpandButtonPressed = true,
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
self.onExpandButtonInputEnded = function()
|
||||
if self.state.isExpandButtonPressed then
|
||||
self:setState({
|
||||
isExpandButtonPressed = false,
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
self.rootFrameRef = Roact.createRef()
|
||||
|
||||
self.onListLayoutAbsoluteContentSizeChanged = function(rbx)
|
||||
if self.rootFrameRef.current then
|
||||
local itemWidth = self.props.itemWidth
|
||||
local minimumHeight = self:getCompactTotalHeight()
|
||||
|
||||
self.rootFrameRef.current.Size = UDim2.new(0, itemWidth,
|
||||
0, math.max(rbx.AbsoluteContentSize.Y, minimumHeight))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function AccordionView:getCompactTotalHeight()
|
||||
local items = self.props.items
|
||||
local itemHeight = self.props.itemHeight
|
||||
local maxItemsInCompactView = self.props.maxItemsInCompactView
|
||||
local totalNumberOfItems = #items
|
||||
|
||||
if totalNumberOfItems == 0 then
|
||||
return 0
|
||||
else
|
||||
return itemHeight + (math.min(maxItemsInCompactView, totalNumberOfItems) - 1) * COMPACT_VIEW_PLACEHOLDER_HEIGHT
|
||||
end
|
||||
end
|
||||
|
||||
function AccordionView:getLayoutInfo()
|
||||
local items = self.props.items
|
||||
local itemWidth = self.props.itemWidth
|
||||
local itemHeight = self.props.itemHeight
|
||||
local placeholderBaseTransparency = self.props.placeholderBaseTransparency
|
||||
local maxItemsInCompactView = self.props.maxItemsInCompactView
|
||||
local expanded = self.state.expanded
|
||||
|
||||
local layoutData = {}
|
||||
local totalNumberOfItems = #items
|
||||
local itemsShownInCompactView = math.min(maxItemsInCompactView, totalNumberOfItems)
|
||||
|
||||
local placeholderTransparencyStep = 0
|
||||
if itemsShownInCompactView > 1 then
|
||||
placeholderTransparencyStep = (1 - placeholderBaseTransparency) / (itemsShownInCompactView - 1)
|
||||
end
|
||||
|
||||
for index = 1, totalNumberOfItems do
|
||||
if expanded then
|
||||
layoutData[index] = {
|
||||
width = itemWidth,
|
||||
height = itemHeight,
|
||||
placeholderTransparency = 1,
|
||||
itemTransparency = 0,
|
||||
}
|
||||
else
|
||||
if index == 1 then
|
||||
layoutData[index] = {
|
||||
width = itemWidth,
|
||||
height = itemHeight,
|
||||
placeholderTransparency = 1,
|
||||
itemTransparency = 0,
|
||||
}
|
||||
elseif index <= maxItemsInCompactView then
|
||||
layoutData[index] = {
|
||||
width = itemWidth - ITEM_WIDTH_SHRINK_STEP * (index - 1),
|
||||
height = COMPACT_VIEW_PLACEHOLDER_HEIGHT,
|
||||
placeholderTransparency = placeholderBaseTransparency + placeholderTransparencyStep * (index - 2),
|
||||
itemTransparency = 1,
|
||||
}
|
||||
else
|
||||
layoutData[index] = {
|
||||
width = itemWidth - ITEM_WIDTH_SHRINK_STEP * (index - 1),
|
||||
height = 0,
|
||||
placeholderTransparency = 1,
|
||||
itemTransparency = 1,
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return layoutData
|
||||
end
|
||||
|
||||
function AccordionView:render()
|
||||
assert(validateProps(self.props))
|
||||
|
||||
local items = self.props.items
|
||||
local totalNumberOfItems = #items
|
||||
|
||||
if totalNumberOfItems == 0 then
|
||||
return nil
|
||||
end
|
||||
|
||||
local layoutOrder = self.props.LayoutOrder
|
||||
local itemWidth = self.props.itemWidth
|
||||
local renderItem = self.props.renderItem
|
||||
local placeholderColor = self.props.placeholderColor
|
||||
local collapseButtonSize = self.props.collapseButtonSize
|
||||
local renderCollapseButton = self.props.renderCollapseButton
|
||||
|
||||
local expanded = self.state.expanded
|
||||
local isExpandButtonPressed = self.state.isExpandButtonPressed
|
||||
|
||||
local layoutData = self:getLayoutInfo()
|
||||
|
||||
local accordionContent = {
|
||||
Layout = Roact.createElement("UIListLayout", {
|
||||
FillDirection = Enum.FillDirection.Vertical,
|
||||
HorizontalAlignment = Enum.HorizontalAlignment.Center,
|
||||
SortOrder = Enum.SortOrder.LayoutOrder,
|
||||
Padding = UDim.new(0, expanded and ITEM_PADDING or 0),
|
||||
[Roact.Change.AbsoluteContentSize] = self.onListLayoutAbsoluteContentSizeChanged,
|
||||
}),
|
||||
Scaler = Roact.createElement(SpringAnimatedItem.AnimatedUIScale, {
|
||||
springOptions = ANIMATION_SPRING_SETTINGS,
|
||||
animatedValues = {
|
||||
scale = isExpandButtonPressed and PRESSED_SCALE or 1,
|
||||
},
|
||||
mapValuesToProps = function(values)
|
||||
return {
|
||||
Scale = values.scale,
|
||||
}
|
||||
end,
|
||||
}),
|
||||
CollapseButton = Roact.createElement(SpringAnimatedItem.AnimatedFrame, {
|
||||
springOptions = ANIMATION_SPRING_SETTINGS,
|
||||
animatedValues = {
|
||||
-- Increase the size by 1 pixel so the animation looks better
|
||||
-- when the spring is damping in the end.
|
||||
sizeOffsetY = expanded and collapseButtonSize + 1 or 0,
|
||||
},
|
||||
mapValuesToProps = function(values)
|
||||
return {
|
||||
Size = UDim2.new(0, collapseButtonSize, 0, values.sizeOffsetY),
|
||||
}
|
||||
end,
|
||||
regularProps = {
|
||||
BackgroundTransparency = 1,
|
||||
ClipsDescendants = true,
|
||||
[Roact.Children] = {
|
||||
ButtonMoveContainer = Roact.createElement(SpringAnimatedItem.AnimatedFrame, {
|
||||
springOptions = ANIMATION_SPRING_SETTINGS,
|
||||
animatedValues = {
|
||||
positionOffsetY = expanded and 0 or collapseButtonSize / 2,
|
||||
},
|
||||
mapValuesToProps = function(values)
|
||||
return {
|
||||
Position = UDim2.new(0, 0, 0, values.positionOffsetY),
|
||||
}
|
||||
end,
|
||||
regularProps = {
|
||||
Size = UDim2.new(0, collapseButtonSize, 0, collapseButtonSize),
|
||||
BackgroundTransparency = 1,
|
||||
[Roact.Children] = {
|
||||
Button = renderCollapseButton(self.onCollapseButtonActivated),
|
||||
},
|
||||
},
|
||||
}),
|
||||
},
|
||||
},
|
||||
}),
|
||||
}
|
||||
|
||||
for index, _ in ipairs(items) do
|
||||
local layout = layoutData[index]
|
||||
|
||||
accordionContent["Item" .. tostring(index)] = Roact.createElement(SpringAnimatedItem.AnimatedFrame, {
|
||||
springOptions = ANIMATION_SPRING_SETTINGS,
|
||||
animatedValues = {
|
||||
width = layout.width,
|
||||
height = layout.height,
|
||||
},
|
||||
mapValuesToProps = function(values)
|
||||
return {
|
||||
Size = UDim2.new(0, values.width, 0, values.height),
|
||||
}
|
||||
end,
|
||||
regularProps = {
|
||||
Size = UDim2.new(1, 0, 0, 0),
|
||||
BackgroundTransparency = 1,
|
||||
BorderSizePixel = 0,
|
||||
LayoutOrder = index + 1,
|
||||
ZIndex = totalNumberOfItems + 1 - index;
|
||||
ClipsDescendants = true,
|
||||
[Roact.Children] = {
|
||||
Item = renderItem(items[index], layout.itemTransparency, ANIMATION_SPRING_SETTINGS),
|
||||
Placeholder = Roact.createElement(SpringAnimatedItem.AnimatedFrame, {
|
||||
springOptions = ANIMATION_SPRING_SETTINGS,
|
||||
animatedValues = {
|
||||
transparency = layout.placeholderTransparency,
|
||||
},
|
||||
mapValuesToProps = function(values)
|
||||
return {
|
||||
BackgroundTransparency = values.transparency,
|
||||
}
|
||||
end,
|
||||
regularProps = {
|
||||
Size = UDim2.new(1, 0, 1, 0),
|
||||
BackgroundColor3 = placeholderColor,
|
||||
BorderSizePixel = 0,
|
||||
},
|
||||
}),
|
||||
},
|
||||
},
|
||||
})
|
||||
end
|
||||
|
||||
local canExpand = (totalNumberOfItems > 1)
|
||||
local clickToExpand = canExpand and not expanded
|
||||
|
||||
return Roact.createElement("Frame", {
|
||||
Size = UDim2.new(0, itemWidth, 0, 0),
|
||||
BackgroundTransparency = 1,
|
||||
BorderSizePixel = 0,
|
||||
LayoutOrder = layoutOrder,
|
||||
[Roact.Ref] = self.rootFrameRef,
|
||||
}, {
|
||||
ContentFrame = Roact.createElement("Frame", {
|
||||
Size = UDim2.new(1, 0, 1, 0),
|
||||
Position = UDim2.new(0.5, 0, 0.5, 0),
|
||||
AnchorPoint = Vector2.new(0.5, 0.5),
|
||||
BackgroundTransparency = 1,
|
||||
},
|
||||
accordionContent
|
||||
),
|
||||
ClickToExpandButton = clickToExpand and Roact.createElement("TextButton", {
|
||||
Size = UDim2.new(1, 0, 1, 0),
|
||||
BackgroundTransparency = 1,
|
||||
BorderSizePixel = 0,
|
||||
ZIndex = totalNumberOfItems + 1,
|
||||
Text = "",
|
||||
[Roact.Event.Activated] = self.onExpandButtonActivated,
|
||||
[Roact.Event.InputBegan] = self.onExpandButtonInputBegan,
|
||||
[Roact.Event.InputEnded] = self.onExpandButtonInputEnded,
|
||||
}),
|
||||
})
|
||||
end
|
||||
|
||||
return AccordionView
|
||||
+72
@@ -0,0 +1,72 @@
|
||||
return function()
|
||||
local AccordionRoot = script.Parent
|
||||
local AppRoot = AccordionRoot.Parent
|
||||
local UIBloxRoot = AppRoot.Parent
|
||||
local Packages = UIBloxRoot.Parent
|
||||
local AccordionView = require(AccordionRoot.AccordionView)
|
||||
local Roact = require(Packages.Roact)
|
||||
|
||||
describe("AccordionView", function()
|
||||
it("should mount correctly", function()
|
||||
local element = Roact.createElement(AccordionView, {
|
||||
items = {"test", "test2"},
|
||||
itemWidth = 355,
|
||||
itemHeight = 188,
|
||||
renderItem = function(item, transparency)
|
||||
return Roact.createElement("TextLabel", {
|
||||
Size = UDim2.new(1, 0, 1, 0),
|
||||
Text = item,
|
||||
BackgroundTransparency = transparency,
|
||||
})
|
||||
end,
|
||||
placeholderColor = Color3.fromRGB(255, 255, 255),
|
||||
placeholderBaseTransparency = 0.5,
|
||||
collapseButtonSize = 40,
|
||||
renderCollapseButton = function(activatedCallback)
|
||||
return Roact.createElement("TextButton", {
|
||||
Size = UDim2.new(1, 0, 1, 0),
|
||||
BackgroundTransparency = 1,
|
||||
Text = "close",
|
||||
AutoButtonColor = false,
|
||||
[Roact.Event.Activated] = activatedCallback,
|
||||
})
|
||||
end,
|
||||
})
|
||||
|
||||
local instance = Roact.mount(element)
|
||||
|
||||
Roact.unmount(instance)
|
||||
end)
|
||||
|
||||
it("should mount correctly with empty items", function()
|
||||
local element = Roact.createElement(AccordionView, {
|
||||
items = {},
|
||||
itemWidth = 355,
|
||||
itemHeight = 188,
|
||||
renderItem = function(item, transparency)
|
||||
return Roact.createElement("TextLabel", {
|
||||
Size = UDim2.new(1, 0, 1, 0),
|
||||
Text = item,
|
||||
BackgroundTransparency = transparency,
|
||||
})
|
||||
end,
|
||||
placeholderColor = Color3.fromRGB(255, 255, 255),
|
||||
placeholderBaseTransparency = 0.5,
|
||||
collapseButtonSize = 40,
|
||||
renderCollapseButton = function(activatedCallback)
|
||||
return Roact.createElement("TextButton", {
|
||||
Size = UDim2.new(1, 0, 1, 0),
|
||||
BackgroundTransparency = 1,
|
||||
Text = "close",
|
||||
AutoButtonColor = false,
|
||||
[Roact.Event.Activated] = activatedCallback,
|
||||
})
|
||||
end,
|
||||
})
|
||||
|
||||
local instance = Roact.mount(element)
|
||||
|
||||
Roact.unmount(instance)
|
||||
end)
|
||||
end)
|
||||
end
|
||||
+221
@@ -0,0 +1,221 @@
|
||||
local Bar = script.Parent
|
||||
local App = Bar.Parent
|
||||
local UIBlox = App.Parent
|
||||
local Packages = UIBlox.Parent
|
||||
|
||||
local Roact = require(Packages.Roact)
|
||||
local Otter = require(Packages.Otter)
|
||||
local t = require(Packages.t)
|
||||
|
||||
local IconButton = require(App.Button.IconButton)
|
||||
local Images = require(App.ImageSet.Images)
|
||||
local IconSize = require(App.ImageSet.Enum.IconSize)
|
||||
local getIconSize = require(App.ImageSet.getIconSize)
|
||||
local ControlState = require(Packages.UIBlox.Core.Control.Enum.ControlState)
|
||||
local withStyle = require(UIBlox.Core.Style.withStyle)
|
||||
local ThreeSectionBar = require(UIBlox.Core.Bar.ThreeSectionBar)
|
||||
|
||||
local lerp = require(Packages.UIBlox.Utility.lerp)
|
||||
local divideTransparency = require(Packages.UIBlox.Utility.divideTransparency)
|
||||
|
||||
local TITLE_BAR_HEIGHT = 64
|
||||
local SHADOW_HEIGHT = 24
|
||||
local MARGIN = 20
|
||||
local PADDING_BETWEEN = 12
|
||||
|
||||
local TITLE_BAR_OFF_POS = UDim2.new(0, 0, 0, -(TITLE_BAR_HEIGHT + SHADOW_HEIGHT))
|
||||
local TITLE_BAR_ON_POS = UDim2.fromOffset(0, 0)
|
||||
|
||||
local EXIT_BUTTON_IMAGE_ID = "icons/actions/previewShrink"
|
||||
local CLOSE_BUTTON_IMAGE_ID = "icons/navigation/close"
|
||||
|
||||
local GRADIENT_OPACITY = 0.25
|
||||
|
||||
local MOTOR_OPTIONS = {
|
||||
frequency = 5,
|
||||
}
|
||||
|
||||
local FullscreenTitleBar = Roact.PureComponent:extend("FullscreenTitleBar")
|
||||
|
||||
FullscreenTitleBar.validateProps = t.strictInterface({
|
||||
title = t.string,
|
||||
isTriggered = t.optional(t.boolean),
|
||||
onDisappear = t.optional(t.callback),
|
||||
|
||||
exitFullscreen = t.optional(t.callback),
|
||||
closeRoblox = t.optional(t.callback),
|
||||
})
|
||||
|
||||
function FullscreenTitleBar:init()
|
||||
local initProgress = self.props.isTriggered and 1 or 0
|
||||
local setProgress
|
||||
self.progress, setProgress = Roact.createBinding(initProgress)
|
||||
|
||||
self.exitControlState, self.setExitControlState = Roact.createBinding(self.state.exitControlState)
|
||||
self.closeControlState, self.setCloseControlState = Roact.createBinding(self.state.closeControlState)
|
||||
|
||||
self.titleBarPosition = self.progress:map(function(value)
|
||||
return TITLE_BAR_OFF_POS:lerp(TITLE_BAR_ON_POS, value)
|
||||
end)
|
||||
|
||||
self.progressMotor = Otter.createSingleMotor(initProgress)
|
||||
self.progressMotor:onStep(setProgress)
|
||||
end
|
||||
|
||||
function FullscreenTitleBar:render()
|
||||
return withStyle(function(style)
|
||||
local theme = style.Theme
|
||||
local font = style.Font
|
||||
|
||||
local backgroundStyle = theme.BackgroundUIDefault
|
||||
local textColorStyle = theme.TextEmphasis
|
||||
|
||||
local centerTextFont = font.Header2
|
||||
local centerTextSize = centerTextFont.RelativeSize * font.BaseSize
|
||||
|
||||
local titleBarTransparency = self.progress:map(function(value)
|
||||
local baseTransparency = backgroundStyle.Transparency
|
||||
return lerp(1, baseTransparency, value)
|
||||
end)
|
||||
|
||||
local exitButtonTransparency = Roact.joinBindings({
|
||||
progress = self.progress,
|
||||
controlState = self.exitControlState,
|
||||
}):map(function(values)
|
||||
local baseTransparency = theme.ContextualPrimaryDefault.Transparency
|
||||
local transparencyDivisor = values.controlState == ControlState.Pressed and 2 or 1
|
||||
return lerp(1, divideTransparency(baseTransparency, transparencyDivisor), values.progress)
|
||||
end)
|
||||
|
||||
local closeButtonTransparency = Roact.joinBindings({
|
||||
progress = self.progress,
|
||||
controlState = self.closeControlState,
|
||||
}):map(function(values)
|
||||
local baseTransparency = theme.ContextualPrimaryDefault.Transparency
|
||||
local transparencyDivisor = values.controlState == ControlState.Pressed and 2 or 1
|
||||
return lerp(1, divideTransparency(baseTransparency, transparencyDivisor), values.progress)
|
||||
end)
|
||||
|
||||
local textTransparency = self.progress:map(function(value)
|
||||
local baseTransparency = textColorStyle.Transparency
|
||||
return lerp(1, baseTransparency, value)
|
||||
end)
|
||||
|
||||
local function renderCenterText()
|
||||
return Roact.createElement("TextLabel", {
|
||||
BackgroundTransparency = 1,
|
||||
Font = centerTextFont.Font,
|
||||
Size = UDim2.new(1, 0, 0, centerTextSize),
|
||||
Text = self.props.title,
|
||||
TextColor3 = textColorStyle.Color,
|
||||
TextSize = centerTextSize,
|
||||
TextTransparency = textTransparency,
|
||||
TextTruncate = Enum.TextTruncate.AtEnd,
|
||||
TextWrapped = false,
|
||||
})
|
||||
end
|
||||
|
||||
local function renderRightButtons()
|
||||
return Roact.createFragment({
|
||||
ExitButton = Roact.createElement(IconButton, {
|
||||
icon = Images[EXIT_BUTTON_IMAGE_ID],
|
||||
iconSize = IconSize.Medium,
|
||||
iconTransparency = exitButtonTransparency,
|
||||
onActivated = self.props.exitFullscreen,
|
||||
layoutOrder = 1,
|
||||
onStateChanged = function(oldState, newState)
|
||||
self.setExitControlState(newState)
|
||||
end
|
||||
}),
|
||||
CloseButton = Roact.createElement(IconButton, {
|
||||
icon = Images[CLOSE_BUTTON_IMAGE_ID],
|
||||
iconSize = IconSize.Medium,
|
||||
iconTransparency = closeButtonTransparency,
|
||||
onActivated = self.props.closeRoblox,
|
||||
layoutOrder = 2,
|
||||
onStateChanged = function(oldState, newState)
|
||||
self.setCloseControlState(newState)
|
||||
end
|
||||
}),
|
||||
})
|
||||
end
|
||||
|
||||
local function renderMirrorButtons()
|
||||
local iconSize = getIconSize(IconSize.Medium)
|
||||
return Roact.createFragment({
|
||||
Roact.createElement("ImageLabel", {
|
||||
BackgroundTransparency = 1,
|
||||
Size = UDim2.fromOffset(iconSize, iconSize),
|
||||
}),
|
||||
Roact.createElement("ImageLabel", {
|
||||
BackgroundTransparency = 1,
|
||||
Size = UDim2.fromOffset(iconSize, iconSize),
|
||||
}),
|
||||
})
|
||||
end
|
||||
|
||||
return Roact.createElement("Frame", {
|
||||
BackgroundTransparency = 1,
|
||||
BorderSizePixel = 0,
|
||||
Position = self.titleBarPosition,
|
||||
Size = UDim2.new(1, 0, 0, TITLE_BAR_HEIGHT + SHADOW_HEIGHT),
|
||||
}, {
|
||||
BarFrame = Roact.createElement("Frame", {
|
||||
BackgroundTransparency = 1,
|
||||
BorderSizePixel = 0,
|
||||
Position = UDim2.fromOffset(0, 0),
|
||||
Size = UDim2.new(1, 0, 0, TITLE_BAR_HEIGHT),
|
||||
[Roact.Event.MouseLeave] = self.props.onDisappear,
|
||||
}, {
|
||||
ThreeSectionBar = Roact.createElement(ThreeSectionBar, {
|
||||
BackgroundColor3 = backgroundStyle.Color,
|
||||
BackgroundTransparency = titleBarTransparency,
|
||||
barHeight = TITLE_BAR_HEIGHT,
|
||||
marginLeft = MARGIN,
|
||||
contentPaddingLeft = UDim.new(0, PADDING_BETWEEN),
|
||||
renderLeft = renderMirrorButtons,
|
||||
renderCenter = renderCenterText,
|
||||
marginRight = MARGIN,
|
||||
contentPaddingRight = UDim.new(0, PADDING_BETWEEN),
|
||||
renderRight = renderRightButtons,
|
||||
}),
|
||||
}),
|
||||
ShadowFrame = Roact.createElement("Frame", {
|
||||
BackgroundTransparency = backgroundStyle.Transparency,
|
||||
BackgroundColor3 = backgroundStyle.Color,
|
||||
BorderSizePixel = 0,
|
||||
Position = UDim2.fromOffset(0, TITLE_BAR_HEIGHT),
|
||||
Size = UDim2.new(1, 0, 0, SHADOW_HEIGHT),
|
||||
}, {
|
||||
UIGradient = Roact.createElement("UIGradient", {
|
||||
Rotation = 90,
|
||||
Color = ColorSequence.new({
|
||||
ColorSequenceKeypoint.new(0, Color3.new(0, 0, 0)),
|
||||
ColorSequenceKeypoint.new(1, Color3.new(0, 0, 0)),
|
||||
}),
|
||||
Transparency = NumberSequence.new({
|
||||
NumberSequenceKeypoint.new(0, 1 - GRADIENT_OPACITY),
|
||||
NumberSequenceKeypoint.new(1, 1.0),
|
||||
}),
|
||||
})
|
||||
})
|
||||
})
|
||||
end)
|
||||
end
|
||||
|
||||
function FullscreenTitleBar:didMount()
|
||||
self.progressMotor:start()
|
||||
end
|
||||
|
||||
function FullscreenTitleBar:didUpdate(prevProps, prevState)
|
||||
if prevProps.isTriggered ~= self.props.isTriggered then
|
||||
local newProgress = self.props.isTriggered and 1 or 0
|
||||
self.progressMotor:setGoal(Otter.spring(newProgress, MOTOR_OPTIONS))
|
||||
end
|
||||
end
|
||||
|
||||
function FullscreenTitleBar:willUnmount()
|
||||
self.progressMotor:destroy()
|
||||
end
|
||||
|
||||
return FullscreenTitleBar
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
return function()
|
||||
local Packages = script.Parent.Parent.Parent.Parent
|
||||
local Roact = require(Packages.Roact)
|
||||
local mockStyleComponent = require(Packages.UIBlox.Utility.mockStyleComponent)
|
||||
|
||||
local FullscreenTitleBar = require(script.Parent.FullscreenTitleBar)
|
||||
|
||||
describe("lifecycle", function()
|
||||
it("should mount and unmount without issue", function()
|
||||
local element = mockStyleComponent({
|
||||
TestTitleBar = Roact.createElement(FullscreenTitleBar, {
|
||||
title = "",
|
||||
})
|
||||
})
|
||||
local instance = Roact.mount(element, nil, "FullscreenTitleBar")
|
||||
Roact.unmount(instance)
|
||||
end)
|
||||
|
||||
it("should mount and unmount without issue with valid properties", function()
|
||||
local element = mockStyleComponent({
|
||||
TestTitleBar = Roact.createElement(FullscreenTitleBar, {
|
||||
title = "",
|
||||
onDisappear = function() end,
|
||||
isTriggered = false,
|
||||
exitFullscreen = function() end,
|
||||
closeRoblox = function() end,
|
||||
})
|
||||
})
|
||||
local instance = Roact.mount(element, nil, "FullscreenTitleBar")
|
||||
Roact.unmount(instance)
|
||||
end)
|
||||
end)
|
||||
end
|
||||
+123
@@ -0,0 +1,123 @@
|
||||
local Bar = script.Parent
|
||||
local App = Bar.Parent
|
||||
local UIBlox = App.Parent
|
||||
local Packages = UIBlox.Parent
|
||||
local Roact = require(Packages.Roact)
|
||||
local t = require(Packages.t)
|
||||
|
||||
local Images = require(App.ImageSet.Images)
|
||||
local IconSize = require(App.ImageSet.Enum.IconSize)
|
||||
local getPageMargin = require(App.Container.getPageMargin)
|
||||
local withStyle = require(UIBlox.Core.Style.withStyle)
|
||||
|
||||
local IconButton = require(UIBlox.App.Button.IconButton)
|
||||
local GenericTextLabel = require(UIBlox.Core.Text.GenericTextLabel.GenericTextLabel)
|
||||
local GetTextSize = require(UIBlox.Core.Text.GetTextSize)
|
||||
|
||||
local ThreeSectionBar = require(UIBlox.Core.Bar.ThreeSectionBar)
|
||||
local HeaderBar = Roact.PureComponent:extend("HeaderBar")
|
||||
HeaderBar.renderLeft = {
|
||||
backButton = function(onActivated)
|
||||
return function(_)
|
||||
return Roact.createElement(IconButton, {
|
||||
size = UDim2.fromOffset(0, 0),
|
||||
iconSize = IconSize.Medium,
|
||||
icon = Images["icons/navigation/pushBack"],
|
||||
onActivated = onActivated,
|
||||
})
|
||||
end
|
||||
end,
|
||||
}
|
||||
|
||||
HeaderBar.validateProps = t.strictInterface({
|
||||
-- The title of the screen
|
||||
title = t.string,
|
||||
|
||||
-- The function that is called when the back button is clicked
|
||||
onBack = t.optional(t.callback),
|
||||
|
||||
-- How tall the bar is
|
||||
barHeight = t.optional(t.number),
|
||||
|
||||
-- How much spacing between elements to allow on the right side of the bar
|
||||
contentPaddingRight = t.optional(t.UDim),
|
||||
|
||||
-- A function that returns a Roact Component, used for customizing buttons on the right side of the bar
|
||||
renderRight = t.optional(t.callback),
|
||||
renderLeft = t.optional(t.callback),
|
||||
|
||||
})
|
||||
|
||||
-- default values are taken from Abstract
|
||||
HeaderBar.defaultProps = {
|
||||
barHeight = 48,
|
||||
contentPaddingRight = UDim.new(0, 12),
|
||||
renderRight = function()
|
||||
return nil
|
||||
end,
|
||||
renderLeft = function()
|
||||
return nil
|
||||
end
|
||||
}
|
||||
|
||||
function HeaderBar:init()
|
||||
self.state = {
|
||||
margin = 0
|
||||
}
|
||||
|
||||
self.onResize = function(rbx)
|
||||
local margin = getPageMargin(rbx.AbsoluteSize.X)
|
||||
self:setState({
|
||||
margin = margin
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
function HeaderBar:render()
|
||||
return withStyle(function(style)
|
||||
local theme = style.Theme
|
||||
local font = style.Font
|
||||
|
||||
local centerTextFontStyle = font.Header1
|
||||
local centerTextSize = centerTextFontStyle.RelativeSize * font.BaseSize
|
||||
|
||||
local estimatedCenterWidth = GetTextSize(
|
||||
self.props.title,
|
||||
centerTextSize,
|
||||
centerTextFontStyle.Font,
|
||||
Vector2.new(1000, 1000)
|
||||
).X
|
||||
|
||||
return Roact.createElement("Frame", {
|
||||
BackgroundTransparency = 1,
|
||||
Size = UDim2.new(1, 0, 0, self.props.barHeight),
|
||||
[Roact.Change.AbsoluteSize] = self.onResize,
|
||||
}, {
|
||||
ThreeSectionBar = Roact.createElement(ThreeSectionBar, {
|
||||
BackgroundTransparency = theme.BackgroundDefault.Transparency,
|
||||
BackgroundColor3 = theme.BackgroundDefault.Color,
|
||||
|
||||
barHeight = self.props.barHeight,
|
||||
marginLeft = self.state.margin,
|
||||
renderLeft = self.props.renderLeft,
|
||||
renderCenter = function()
|
||||
return Roact.createElement(GenericTextLabel, {
|
||||
ClipsDescendants = true,
|
||||
Size = UDim2.new(1, 0, 0, centerTextSize),
|
||||
Text = self.props.title,
|
||||
TextTruncate = Enum.TextTruncate.AtEnd,
|
||||
TextWrapped = false,
|
||||
fontStyle = centerTextFontStyle,
|
||||
colorStyle = theme.TextEmphasis,
|
||||
})
|
||||
end,
|
||||
estimatedCenterWidth = estimatedCenterWidth,
|
||||
marginRight = self.state.margin,
|
||||
contentPaddingRight = self.props.contentPaddingRight,
|
||||
renderRight = self.props.renderRight,
|
||||
})
|
||||
})
|
||||
end)
|
||||
end
|
||||
|
||||
return HeaderBar
|
||||
+114
@@ -0,0 +1,114 @@
|
||||
return function()
|
||||
local Bar = script.Parent
|
||||
local App = Bar.Parent
|
||||
local UIBlox = App.Parent
|
||||
local Packages = UIBlox.Parent
|
||||
local Roact = require(Packages.Roact)
|
||||
local mockStyleComponent = require(UIBlox.Utility.mockStyleComponent)
|
||||
|
||||
local HeaderBar = require(UIBlox.App.Bar.HeaderBar)
|
||||
|
||||
local BARSIZE_SMALL = UDim2.new(0, 320, 0, 40)
|
||||
local BARSIZE_MEDIUM = UDim2.new(0, 480, 0, 40)
|
||||
local BARSIZE_LARGE = UDim2.new(0, 600, 0, 40)
|
||||
local MARGIN_SMALL = 12
|
||||
local MARGIN_MEDIUM = 24
|
||||
local MARGIN_LARGE = 48
|
||||
|
||||
describe("lifecycle", function()
|
||||
it("should mount and unmount without issues", function()
|
||||
local element = mockStyleComponent({
|
||||
bar = Roact.createElement(HeaderBar, {
|
||||
title = "Header Bar",
|
||||
onBack = function() end,
|
||||
}),
|
||||
})
|
||||
|
||||
local instance = Roact.mount(element)
|
||||
Roact.unmount(instance)
|
||||
end)
|
||||
end)
|
||||
|
||||
describe("margin logic", function()
|
||||
it("should have margin of 12 on small screens", function()
|
||||
local frame = Instance.new("Frame")
|
||||
local element = mockStyleComponent({
|
||||
barFrame = Roact.createElement("Frame", {
|
||||
Size = UDim2.new(0, 0, 0, 0),
|
||||
}, {
|
||||
bar = Roact.createElement(HeaderBar, {
|
||||
title = "Header Bar",
|
||||
onBack = function() end,
|
||||
}),
|
||||
})
|
||||
})
|
||||
|
||||
local instance = Roact.mount(element, frame, "Frame")
|
||||
local barFrame = frame:FindFirstChild("barFrame", true)
|
||||
local bar = barFrame:FindFirstChild("bar")
|
||||
local leftFrame = bar:FindFirstChild("leftFrame", true)
|
||||
local margin = leftFrame:FindFirstChild("$margin", true)
|
||||
expect(margin).to.be.ok()
|
||||
|
||||
barFrame.Size = BARSIZE_SMALL
|
||||
local _ = bar.AbsoluteSize -- need to reference AbsoluteSize to trigger [Roact.Change.AbsoluteSize]
|
||||
expect(margin.PaddingLeft.Offset).to.equal(MARGIN_SMALL)
|
||||
|
||||
Roact.unmount(instance)
|
||||
end)
|
||||
|
||||
it("should have margin of 24 on medium screens", function()
|
||||
local frame = Instance.new("Frame")
|
||||
local element = mockStyleComponent({
|
||||
barFrame = Roact.createElement("Frame", {
|
||||
Size = UDim2.new(0, 0, 0, 0),
|
||||
}, {
|
||||
bar = Roact.createElement(HeaderBar, {
|
||||
title = "Header Bar",
|
||||
onBack = function() end,
|
||||
}),
|
||||
})
|
||||
})
|
||||
|
||||
local instance = Roact.mount(element, frame, "Frame")
|
||||
local barFrame = frame:FindFirstChild("barFrame", true)
|
||||
local bar = barFrame:FindFirstChild("bar")
|
||||
local leftFrame = bar:FindFirstChild("leftFrame", true)
|
||||
local margin = leftFrame:FindFirstChild("$margin", true)
|
||||
expect(margin).to.be.ok()
|
||||
|
||||
barFrame.Size = BARSIZE_MEDIUM
|
||||
local _ = bar.AbsoluteSize -- need to reference AbsoluteSize to trigger [Roact.Change.AbsoluteSize]
|
||||
expect(margin.PaddingLeft.Offset).to.equal(MARGIN_MEDIUM)
|
||||
|
||||
Roact.unmount(instance)
|
||||
end)
|
||||
|
||||
it("should have margin of 48 on large screens", function()
|
||||
local frame = Instance.new("Frame")
|
||||
local element = mockStyleComponent({
|
||||
barFrame = Roact.createElement("Frame", {
|
||||
Size = UDim2.new(0, 0, 0, 0),
|
||||
}, {
|
||||
bar = Roact.createElement(HeaderBar, {
|
||||
title = "Header Bar",
|
||||
onBack = function() end,
|
||||
}),
|
||||
})
|
||||
})
|
||||
|
||||
local instance = Roact.mount(element, frame, "Frame")
|
||||
local barFrame = frame:FindFirstChild("barFrame", true)
|
||||
local bar = barFrame:FindFirstChild("bar")
|
||||
local leftFrame = bar:FindFirstChild("leftFrame", true)
|
||||
local margin = leftFrame:FindFirstChild("$margin", true)
|
||||
expect(margin).to.be.ok()
|
||||
|
||||
barFrame.Size = BARSIZE_LARGE
|
||||
local _ = bar.AbsoluteSize -- need to reference AbsoluteSize to trigger [Roact.Change.AbsoluteSize]
|
||||
expect(margin.PaddingLeft.Offset).to.equal(MARGIN_LARGE)
|
||||
|
||||
Roact.unmount(instance)
|
||||
end)
|
||||
end)
|
||||
end
|
||||
+86
@@ -0,0 +1,86 @@
|
||||
local Bar = script.Parent
|
||||
local App = Bar.Parent
|
||||
local UIBlox = App.Parent
|
||||
local Packages = UIBlox.Parent
|
||||
local Roact = require(Packages.Roact)
|
||||
local t = require(Packages.t)
|
||||
|
||||
local withStyle = require(UIBlox.Core.Style.withStyle)
|
||||
local getPageMargin = require(App.Container.getPageMargin)
|
||||
|
||||
local GenericTextLabel = require(UIBlox.Core.Text.GenericTextLabel.GenericTextLabel)
|
||||
|
||||
local ThreeSectionBar = require(UIBlox.Core.Bar.ThreeSectionBar)
|
||||
local RootHeaderBar = Roact.PureComponent:extend("HeaderBar")
|
||||
|
||||
RootHeaderBar.validateProps = t.strictInterface({
|
||||
-- The title of the screen
|
||||
title = t.string,
|
||||
|
||||
-- How tall the bar is
|
||||
barHeight = t.optional(t.number),
|
||||
|
||||
-- A function that returns a Roact Component, used for customizing buttons on the right side of the bar
|
||||
renderRight = t.optional(t.callback),
|
||||
backgroundTransparency = t.optional(t.number),
|
||||
})
|
||||
|
||||
RootHeaderBar.defaultProps = {
|
||||
barHeight = 64,
|
||||
renderRight = function()
|
||||
return nil
|
||||
end,
|
||||
}
|
||||
|
||||
function RootHeaderBar:init()
|
||||
self:setState({
|
||||
margin = 0,
|
||||
})
|
||||
|
||||
self.setPageMargin = function(rbx)
|
||||
local margin = getPageMargin(rbx.AbsoluteSize.X)
|
||||
self:setState({
|
||||
margin = margin
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
function RootHeaderBar:render()
|
||||
return withStyle(function(style)
|
||||
local theme = style.Theme
|
||||
local font = style.Font
|
||||
|
||||
return Roact.createElement("Frame", {
|
||||
BackgroundTransparency = 1,
|
||||
Size = UDim2.new(1, 0, 0, self.props.barHeight),
|
||||
[Roact.Change.AbsoluteSize] = self.setPageMargin,
|
||||
}, {
|
||||
ThreeSectionBar = Roact.createElement(ThreeSectionBar, {
|
||||
BackgroundTransparency = self.props.backgroundTransparency or theme.BackgroundDefault.Transparency,
|
||||
BackgroundColor3 = theme.BackgroundDefault.Color,
|
||||
|
||||
barHeight = self.props.barHeight,
|
||||
contentPaddingRight = UDim.new(0, 0),
|
||||
|
||||
marginLeft = self.state.margin,
|
||||
marginRight = self.state.margin,
|
||||
|
||||
renderRight = self.props.renderRight,
|
||||
renderLeft = function(props)
|
||||
return Roact.createFragment({
|
||||
Text = Roact.createElement(GenericTextLabel, {
|
||||
fluidSizing = true,
|
||||
Text = self.props.title,
|
||||
TextTruncate = Enum.TextTruncate.AtEnd,
|
||||
TextXAlignment = Enum.TextXAlignment.Left,
|
||||
fontStyle = font.Title,
|
||||
colorStyle = theme.TextEmphasis,
|
||||
}, props[Roact.Children])
|
||||
})
|
||||
end,
|
||||
})
|
||||
})
|
||||
end)
|
||||
end
|
||||
|
||||
return RootHeaderBar
|
||||
+110
@@ -0,0 +1,110 @@
|
||||
return function()
|
||||
local Bar = script.Parent
|
||||
local App = Bar.Parent
|
||||
local UIBlox = App.Parent
|
||||
local Packages = UIBlox.Parent
|
||||
local Roact = require(Packages.Roact)
|
||||
local mockStyleComponent = require(UIBlox.Utility.mockStyleComponent)
|
||||
|
||||
local RootHeaderBar = require(UIBlox.App.Bar.RootHeaderBar)
|
||||
|
||||
local BARSIZE_SMALL = UDim2.new(0, 320, 0, 40)
|
||||
local BARSIZE_MEDIUM = UDim2.new(0, 480, 0, 40)
|
||||
local BARSIZE_LARGE = UDim2.new(0, 600, 0, 40)
|
||||
local MARGIN_SMALL = 12
|
||||
local MARGIN_MEDIUM = 24
|
||||
local MARGIN_LARGE = 48
|
||||
|
||||
describe("lifecycle", function()
|
||||
it("should mount and unmount without issues", function()
|
||||
local element = mockStyleComponent({
|
||||
bar = Roact.createElement(RootHeaderBar, {
|
||||
title = "Root Header Bar",
|
||||
}),
|
||||
})
|
||||
|
||||
local instance = Roact.mount(element)
|
||||
Roact.unmount(instance)
|
||||
end)
|
||||
end)
|
||||
|
||||
describe("margin logic", function()
|
||||
it("should have margin of 12 on small screens", function()
|
||||
local frame = Instance.new("Frame")
|
||||
local element = mockStyleComponent({
|
||||
barFrame = Roact.createElement("Frame", {
|
||||
Size = UDim2.new(0, 0, 0, 0),
|
||||
}, {
|
||||
bar = Roact.createElement(RootHeaderBar, {
|
||||
title = "Root Header Bar",
|
||||
}),
|
||||
})
|
||||
})
|
||||
|
||||
local instance = Roact.mount(element, frame, "Frame")
|
||||
local barFrame = frame:FindFirstChild("barFrame", true)
|
||||
local bar = barFrame:FindFirstChild("bar")
|
||||
local leftFrame = bar:FindFirstChild("leftFrame", true)
|
||||
local margin = leftFrame:FindFirstChild("$margin", true)
|
||||
expect(margin).to.be.ok()
|
||||
|
||||
barFrame.Size = BARSIZE_SMALL
|
||||
local _ = bar.AbsoluteSize -- need to reference AbsoluteSize to trigger [Roact.Change.AbsoluteSize]
|
||||
expect(margin.PaddingLeft.Offset).to.equal(MARGIN_SMALL)
|
||||
|
||||
Roact.unmount(instance)
|
||||
end)
|
||||
|
||||
it("should have margin of 24 on medium screens", function()
|
||||
local frame = Instance.new("Frame")
|
||||
local element = mockStyleComponent({
|
||||
barFrame = Roact.createElement("Frame", {
|
||||
Size = UDim2.new(0, 0, 0, 0),
|
||||
}, {
|
||||
bar = Roact.createElement(RootHeaderBar, {
|
||||
title = "Root Header Bar",
|
||||
}),
|
||||
})
|
||||
})
|
||||
|
||||
local instance = Roact.mount(element, frame, "Frame")
|
||||
local barFrame = frame:FindFirstChild("barFrame", true)
|
||||
local bar = barFrame:FindFirstChild("bar")
|
||||
local leftFrame = bar:FindFirstChild("leftFrame", true)
|
||||
local margin = leftFrame:FindFirstChild("$margin", true)
|
||||
expect(margin).to.be.ok()
|
||||
|
||||
barFrame.Size = BARSIZE_MEDIUM
|
||||
local _ = bar.AbsoluteSize -- need to reference AbsoluteSize to trigger [Roact.Change.AbsoluteSize]
|
||||
expect(margin.PaddingLeft.Offset).to.equal(MARGIN_MEDIUM)
|
||||
|
||||
Roact.unmount(instance)
|
||||
end)
|
||||
|
||||
it("should have margin of 48 on large screens", function()
|
||||
local frame = Instance.new("Frame")
|
||||
local element = mockStyleComponent({
|
||||
barFrame = Roact.createElement("Frame", {
|
||||
Size = UDim2.new(0, 0, 0, 0),
|
||||
}, {
|
||||
bar = Roact.createElement(RootHeaderBar, {
|
||||
title = "Root Header Bar",
|
||||
}),
|
||||
})
|
||||
})
|
||||
|
||||
local instance = Roact.mount(element, frame, "Frame")
|
||||
local barFrame = frame:FindFirstChild("barFrame", true)
|
||||
local bar = barFrame:FindFirstChild("bar")
|
||||
local leftFrame = bar:FindFirstChild("leftFrame", true)
|
||||
local margin = leftFrame:FindFirstChild("$margin", true)
|
||||
expect(margin).to.be.ok()
|
||||
|
||||
barFrame.Size = BARSIZE_LARGE
|
||||
local _ = bar.AbsoluteSize -- need to reference AbsoluteSize to trigger [Roact.Change.AbsoluteSize]
|
||||
expect(margin.PaddingLeft.Offset).to.equal(MARGIN_LARGE)
|
||||
|
||||
Roact.unmount(instance)
|
||||
end)
|
||||
end)
|
||||
end
|
||||
+110
@@ -0,0 +1,110 @@
|
||||
local ReplicatedStorage = game:GetService("ReplicatedStorage")
|
||||
|
||||
local StoryView = require(ReplicatedStorage.Packages.StoryComponents.StoryView)
|
||||
local StoryItem = require(ReplicatedStorage.Packages.StoryComponents.StoryItem)
|
||||
|
||||
local Bar = script.Parent.Parent
|
||||
local App = Bar.Parent
|
||||
local UIBlox = App.Parent
|
||||
local Packages = UIBlox.Parent
|
||||
local Roact = require(Packages.Roact)
|
||||
|
||||
local FullscreenTitleBar = require(script.Parent.Parent.FullscreenTitleBar)
|
||||
|
||||
local DISAPPEAR_DELAY = 0.5
|
||||
|
||||
local TitleBarStory = Roact.PureComponent:extend("TitleBarStory")
|
||||
|
||||
function TitleBarStory:init()
|
||||
self:setState({
|
||||
isTriggered = false,
|
||||
})
|
||||
|
||||
self.triggerTitleBar = function()
|
||||
print("Mouse entering trigger area")
|
||||
if not self.state.isTriggered then
|
||||
self:setState({
|
||||
isTriggered = true,
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
self.hideTitleBar = function()
|
||||
print("Mouse leaving Title Bar area")
|
||||
if self.state.isTriggered then
|
||||
delay(DISAPPEAR_DELAY, function()
|
||||
self:setState({
|
||||
isTriggered = false,
|
||||
})
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
self.buttonControl = function()
|
||||
self:setState(function(prevState)
|
||||
return {
|
||||
isTriggered = not prevState.isTriggered,
|
||||
}
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
function TitleBarStory:render()
|
||||
return Roact.createElement("Frame", {
|
||||
Size = UDim2.new(1, 0, 1, 0),
|
||||
BackgroundTransparency = 1,
|
||||
}, {
|
||||
Layout = Roact.createElement("UIListLayout", {
|
||||
SortOrder = Enum.SortOrder.LayoutOrder,
|
||||
FillDirection = Enum.FillDirection.Vertical,
|
||||
}),
|
||||
ControlsFrame = Roact.createElement("Frame", {
|
||||
Size = UDim2.new(1, 0, 0, 50),
|
||||
LayoutOrder = 1,
|
||||
}, {
|
||||
TestButton = Roact.createElement("TextButton", {
|
||||
Text = self.state.isTriggered and "Dismiss" or "Activate",
|
||||
Size = UDim2.fromOffset(200, 50),
|
||||
[Roact.Event.Activated] = self.buttonControl,
|
||||
}),
|
||||
}),
|
||||
StoryItem = Roact.createElement(StoryItem, {
|
||||
size = UDim2.fromScale(1, 1),
|
||||
title = "FullscreenTitleBar",
|
||||
subTitle = "App.Bar.FullscreenTitleBar",
|
||||
layoutOrder = 2,
|
||||
showDivider = true,
|
||||
}, {
|
||||
Demo = Roact.createElement("Frame", {
|
||||
Size = UDim2.new(1, 0, 1, 0),
|
||||
}, {
|
||||
TriggerArea = Roact.createElement("Frame", {
|
||||
BackgroundColor3 = Color3.fromRGB(0, 255, 255),
|
||||
BorderSizePixel = 0,
|
||||
Size = UDim2.new(1, 0, 0, 1),
|
||||
[Roact.Event.MouseEnter] = self.triggerTitleBar,
|
||||
}),
|
||||
TitleBar = Roact.createElement(FullscreenTitleBar, {
|
||||
title = "Roblox",
|
||||
isTriggered = self.state.isTriggered,
|
||||
onDisappear = self.hideTitleBar,
|
||||
exitFullscreen = function()
|
||||
print "Exit Fullscreen"
|
||||
end,
|
||||
closeRoblox = function()
|
||||
print "Close Roblox"
|
||||
end,
|
||||
}),
|
||||
})
|
||||
}),
|
||||
})
|
||||
end
|
||||
|
||||
return function(target)
|
||||
local handle = Roact.mount(Roact.createElement(StoryView, {}, {
|
||||
Story = Roact.createElement(TitleBarStory),
|
||||
}), target, "FullscreenTitleBar")
|
||||
return function()
|
||||
Roact.unmount(handle)
|
||||
end
|
||||
end
|
||||
+136
@@ -0,0 +1,136 @@
|
||||
local ReplicatedStorage = game:GetService("ReplicatedStorage")
|
||||
|
||||
local StoryView = require(ReplicatedStorage.Packages.StoryComponents.StoryView)
|
||||
local StoryItem = require(ReplicatedStorage.Packages.StoryComponents.StoryItem)
|
||||
|
||||
local Bar = script.Parent.Parent
|
||||
local App = Bar.Parent
|
||||
local UIBlox = App.Parent
|
||||
local Packages = UIBlox.Parent
|
||||
local Roact = require(Packages.Roact)
|
||||
|
||||
local Images = require(App.ImageSet.Images)
|
||||
local IconSize = require(App.ImageSet.Enum.IconSize)
|
||||
local HeaderBar = require(Bar.HeaderBar)
|
||||
local IconButton = require(UIBlox.App.Button.IconButton)
|
||||
local TextButton = require(UIBlox.App.Button.TextButton)
|
||||
|
||||
local function BarDemo()
|
||||
return Roact.createElement(HeaderBar, {
|
||||
title = string.rep("Header Bar Story", 1),
|
||||
renderLeft = HeaderBar.renderLeft.backButton(function()
|
||||
print("navProps.navigation.pop()")
|
||||
end),
|
||||
renderRight = function()
|
||||
return Roact.createFragment({
|
||||
search = Roact.createElement(IconButton, {
|
||||
size = UDim2.fromOffset(0, 0),
|
||||
iconSize = IconSize.Medium,
|
||||
icon = Images["icons/common/search"],
|
||||
onActivated = function()
|
||||
print "Opening Search!"
|
||||
end,
|
||||
layoutOrder = 1,
|
||||
}),
|
||||
premium = Roact.createElement(IconButton, {
|
||||
size = UDim2.fromOffset(0, 0),
|
||||
iconSize = IconSize.Medium,
|
||||
icon = Images["icons/common/goldrobux"],
|
||||
onActivated = function()
|
||||
print "Oooh Shiny!"
|
||||
end,
|
||||
layoutOrder = 2,
|
||||
}),
|
||||
alert = Roact.createElement(IconButton, {
|
||||
size = UDim2.fromOffset(0, 0),
|
||||
iconSize = IconSize.Medium,
|
||||
icon = Images['icons/common/notificationOn'],
|
||||
onActivated = function()
|
||||
print "Alert!"
|
||||
end,
|
||||
layoutOrder = 3,
|
||||
}),
|
||||
})
|
||||
end,
|
||||
})
|
||||
end
|
||||
|
||||
local function BarWithTextButtonsDemo()
|
||||
return Roact.createElement(HeaderBar, {
|
||||
title = string.rep("Header Bar Story", 1),
|
||||
renderLeft = function()
|
||||
return Roact.createFragment({
|
||||
search = Roact.createElement(TextButton, {
|
||||
text = "Action 1",
|
||||
onActivated = function()
|
||||
print "Opening Search!"
|
||||
end,
|
||||
layoutOrder = 1,
|
||||
}),
|
||||
})
|
||||
end,
|
||||
renderRight = function()
|
||||
return Roact.createFragment({
|
||||
search = Roact.createElement(TextButton, {
|
||||
text = "Action 2",
|
||||
onActivated = function()
|
||||
print "Opening Search!"
|
||||
end,
|
||||
layoutOrder = 1,
|
||||
}),
|
||||
})
|
||||
end,
|
||||
})
|
||||
end
|
||||
|
||||
return function(target)
|
||||
local handle = Roact.mount(Roact.createElement(StoryView, {}, {
|
||||
Story = Roact.createElement(StoryItem, {
|
||||
size = UDim2.fromScale(1, 1),
|
||||
title = "HeaderBar",
|
||||
subTitle = "App.Bar.HeaderBar",
|
||||
}, {
|
||||
layout = Roact.createElement("UIListLayout"),
|
||||
frame = Roact.createElement("Frame", {
|
||||
BackgroundTransparency = 1,
|
||||
Size = UDim2.fromOffset(600, 45),
|
||||
}, {
|
||||
headerBar = Roact.createElement(BarDemo)
|
||||
}),
|
||||
frame2 = Roact.createElement("Frame", {
|
||||
BackgroundTransparency = 1,
|
||||
Size = UDim2.fromOffset(361, 45),
|
||||
}, {
|
||||
headerBar = Roact.createElement(BarDemo)
|
||||
}),
|
||||
frame3 = Roact.createElement("Frame", {
|
||||
BackgroundTransparency = 1,
|
||||
Size = UDim2.fromOffset(300, 45),
|
||||
}, {
|
||||
headerBar = Roact.createElement(BarDemo)
|
||||
}),
|
||||
|
||||
frame4 = Roact.createElement("Frame", {
|
||||
BackgroundTransparency = 1,
|
||||
Size = UDim2.fromOffset(600, 45),
|
||||
}, {
|
||||
headerBar = Roact.createElement(BarWithTextButtonsDemo)
|
||||
}),
|
||||
frame5 = Roact.createElement("Frame", {
|
||||
BackgroundTransparency = 1,
|
||||
Size = UDim2.fromOffset(361, 45),
|
||||
}, {
|
||||
headerBar = Roact.createElement(BarWithTextButtonsDemo)
|
||||
}),
|
||||
frame6 = Roact.createElement("Frame", {
|
||||
BackgroundTransparency = 1,
|
||||
Size = UDim2.fromOffset(300, 45),
|
||||
}, {
|
||||
headerBar = Roact.createElement(BarWithTextButtonsDemo)
|
||||
}),
|
||||
}),
|
||||
}), target, "HeaderBar")
|
||||
return function()
|
||||
Roact.unmount(handle)
|
||||
end
|
||||
end
|
||||
+61
@@ -0,0 +1,61 @@
|
||||
local ReplicatedStorage = game:GetService("ReplicatedStorage")
|
||||
|
||||
local StoryView = require(ReplicatedStorage.Packages.StoryComponents.StoryView)
|
||||
local StoryItem = require(ReplicatedStorage.Packages.StoryComponents.StoryItem)
|
||||
|
||||
local Bar = script.Parent.Parent
|
||||
local App = Bar.Parent
|
||||
local UIBlox = App.Parent
|
||||
local Packages = UIBlox.Parent
|
||||
local Roact = require(Packages.Roact)
|
||||
|
||||
local getIconSizeUDim2 = require(App.ImageSet.getIconSizeUDim2)
|
||||
local IconSize = require(App.ImageSet.Enum.IconSize)
|
||||
local Images = require(App.ImageSet.Images)
|
||||
local RootHeaderBar = require(Bar.RootHeaderBar)
|
||||
local IconButton = require(UIBlox.App.Button.IconButton)
|
||||
|
||||
return function(target)
|
||||
local handle = Roact.mount(Roact.createElement(StoryView, {}, {
|
||||
Story = Roact.createElement(StoryItem, {
|
||||
size = UDim2.new(1, 0, 1, 0),
|
||||
title = "RootHeaderBar",
|
||||
subTitle = "App.Bar.RootHeaderBar",
|
||||
}, {
|
||||
Roact.createElement(RootHeaderBar, {
|
||||
title = "Root Header Bar Story Long Text Example To Test Truncation",
|
||||
renderRight = function()
|
||||
return Roact.createFragment({
|
||||
search = Roact.createElement(IconButton, {
|
||||
size = getIconSizeUDim2(IconSize.Small),
|
||||
icon = Images['icons/common/search_small'],
|
||||
onActivated = function()
|
||||
print "Opening Search!"
|
||||
end,
|
||||
layoutOrder = 1,
|
||||
}),
|
||||
premium = Roact.createElement(IconButton, {
|
||||
size = getIconSizeUDim2(IconSize.Small),
|
||||
icon = Images['icons/common/goldrobux_small'],
|
||||
onActivated = function()
|
||||
print "Oooh Shiny!"
|
||||
end,
|
||||
layoutOrder = 2,
|
||||
}),
|
||||
alert = Roact.createElement(IconButton, {
|
||||
size = getIconSizeUDim2(IconSize.Small),
|
||||
icon = Images['icons/common/notificationOn'],
|
||||
onActivated = function()
|
||||
print "Alert!"
|
||||
end,
|
||||
layoutOrder = 3,
|
||||
}),
|
||||
})
|
||||
end,
|
||||
}),
|
||||
})
|
||||
}), target, "HeaderBar")
|
||||
return function()
|
||||
Roact.unmount(handle)
|
||||
end
|
||||
end
|
||||
+55
@@ -0,0 +1,55 @@
|
||||
local Button = script.Parent
|
||||
local App = Button.Parent
|
||||
local UIBlox = App.Parent
|
||||
local Packages = UIBlox.Parent
|
||||
|
||||
local Roact = require(Packages.Roact)
|
||||
|
||||
local Images = require(App.ImageSet.Images)
|
||||
local CursorKind = require(App.SelectionImage.CursorKind)
|
||||
local withSelectionCursorProvider = require(App.SelectionImage.withSelectionCursorProvider)
|
||||
|
||||
local validateButtonProps = require(Button.validateButtonProps)
|
||||
local GenericButton = require(UIBlox.Core.Button.GenericButton)
|
||||
local ControlState = require(UIBlox.Core.Control.Enum.ControlState)
|
||||
|
||||
local AlertButton = Roact.PureComponent:extend("AlertButton")
|
||||
|
||||
local BUTTON_STATE_COLOR = {
|
||||
[ControlState.Default] = "Alert",
|
||||
}
|
||||
|
||||
local CONTENT_STATE_COLOR = {
|
||||
[ControlState.Default] = "Alert",
|
||||
}
|
||||
|
||||
AlertButton.defaultProps = {
|
||||
isDisabled = false,
|
||||
isLoading = false,
|
||||
}
|
||||
|
||||
function AlertButton:render()
|
||||
assert(validateButtonProps(self.props))
|
||||
local image = Images["component_assets/circle_17_stroke_1"]
|
||||
return withSelectionCursorProvider(function(getSelectionCursor)
|
||||
return Roact.createElement(GenericButton, {
|
||||
Size = self.props.size,
|
||||
AnchorPoint = self.props.anchorPoint,
|
||||
Position = self.props.position,
|
||||
LayoutOrder = self.props.layoutOrder,
|
||||
SelectionImageObject = getSelectionCursor(CursorKind.RoundedRectNoInset),
|
||||
icon = self.props.icon,
|
||||
text = self.props.text,
|
||||
isDisabled = self.props.isDisabled,
|
||||
isLoading = self.props.isLoading,
|
||||
onActivated = self.props.onActivated,
|
||||
onStateChanged = self.props.onStateChanged,
|
||||
userInteractionEnabled = self.props.userInteractionEnabled,
|
||||
buttonImage = image,
|
||||
buttonStateColorMap = BUTTON_STATE_COLOR,
|
||||
contentStateColorMap = CONTENT_STATE_COLOR,
|
||||
})
|
||||
end)
|
||||
end
|
||||
|
||||
return AlertButton
|
||||
+62
@@ -0,0 +1,62 @@
|
||||
return function()
|
||||
local Button = script.Parent
|
||||
local App = Button.Parent
|
||||
local UIBlox = App.Parent
|
||||
local Packages = UIBlox.Parent
|
||||
|
||||
local Roact = require(Packages.Roact)
|
||||
local Images = require(App.ImageSet.Images)
|
||||
|
||||
local icon = Images["icons/common/robux_small"]
|
||||
local mockStyleComponent = require(UIBlox.Utility.mockStyleComponent)
|
||||
|
||||
local AlertButton = require(Button.AlertButton)
|
||||
|
||||
it("should create and destroy Alert Button with text without errors", function()
|
||||
local element = mockStyleComponent({
|
||||
button = Roact.createElement(AlertButton, {
|
||||
text = "Button",
|
||||
onActivated = function()end,
|
||||
}),
|
||||
})
|
||||
|
||||
local instance = Roact.mount(element)
|
||||
Roact.unmount(instance)
|
||||
end)
|
||||
|
||||
it("should create and destroy Alert Button with text icon only without errors", function()
|
||||
local element = mockStyleComponent({
|
||||
button = Roact.createElement(AlertButton, {
|
||||
icon = icon,
|
||||
onActivated = function()end,
|
||||
}),
|
||||
})
|
||||
|
||||
local instance = Roact.mount(element)
|
||||
Roact.unmount(instance)
|
||||
end)
|
||||
|
||||
it("should create and destroy Alert Button with text and text without errors", function()
|
||||
local element = mockStyleComponent({
|
||||
button = Roact.createElement(AlertButton, {
|
||||
text = "Button",
|
||||
icon = icon,
|
||||
onActivated = function()end,
|
||||
}),
|
||||
})
|
||||
|
||||
local instance = Roact.mount(element)
|
||||
Roact.unmount(instance)
|
||||
end)
|
||||
|
||||
it("should create and destroy a blank Alert Button without errors", function()
|
||||
local element = mockStyleComponent({
|
||||
button = Roact.createElement(AlertButton, {
|
||||
onActivated = function()end,
|
||||
}),
|
||||
})
|
||||
|
||||
local instance = Roact.mount(element)
|
||||
Roact.unmount(instance)
|
||||
end)
|
||||
end
|
||||
+149
@@ -0,0 +1,149 @@
|
||||
local ButtonRoot = script.Parent
|
||||
local AppRoot = ButtonRoot.Parent
|
||||
local UIBlox = AppRoot.Parent
|
||||
local Packages = UIBlox.Parent
|
||||
|
||||
local Roact = require(Packages.Roact)
|
||||
local Cryo = require(Packages.Cryo)
|
||||
local RoactGamepad = require(Packages.RoactGamepad)
|
||||
|
||||
local AlertButton = require(ButtonRoot.AlertButton)
|
||||
local PrimaryContextualButton = require(ButtonRoot.PrimaryContextualButton)
|
||||
local PrimarySystemButton = require(ButtonRoot.PrimarySystemButton)
|
||||
local SecondaryButton = require(ButtonRoot.SecondaryButton)
|
||||
local GetTextSize = require(UIBlox.Core.Text.GetTextSize)
|
||||
local withStyle = require(UIBlox.Core.Style.withStyle)
|
||||
|
||||
local FitFrame = require(Packages.FitFrame)
|
||||
local FitFrameOnAxis = FitFrame.FitFrameOnAxis
|
||||
|
||||
local ButtonType = require(ButtonRoot.Enum.ButtonType)
|
||||
|
||||
local validateButtonStack = require(AppRoot.Button.Validator.validateButtonStack)
|
||||
local UIBloxConfig = require(UIBlox.UIBloxConfig)
|
||||
|
||||
local BUTTON_HEIGHT = 36
|
||||
|
||||
local ButtonStack = Roact.PureComponent:extend("ButtonStack")
|
||||
|
||||
ButtonStack.defaultProps = {
|
||||
buttonHeight = BUTTON_HEIGHT,
|
||||
marginBetween = 12,
|
||||
minHorizontalButtonPadding = 8,
|
||||
}
|
||||
|
||||
function ButtonStack:init()
|
||||
self.buttonRefs = RoactGamepad.createRefCache()
|
||||
|
||||
self.state = {
|
||||
frameWidth = 0
|
||||
}
|
||||
|
||||
self.updateFrameSize = function(rbx)
|
||||
local frameWidth = rbx.AbsoluteSize.X
|
||||
if frameWidth ~= self.state.frameWidth then
|
||||
self:setState({
|
||||
frameWidth = frameWidth,
|
||||
})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function ButtonStack:render()
|
||||
assert(validateButtonStack(self.props))
|
||||
|
||||
return withStyle(function(stylePalette)
|
||||
local font = stylePalette.Font
|
||||
local textSize = font.Body.RelativeSize * font.BaseSize
|
||||
|
||||
local buttons = self.props.buttons
|
||||
local paddingBetween = #buttons > 1 and self.props.marginBetween or 0
|
||||
local nonStackedButtonWidth = (self.state.frameWidth / #buttons) - (paddingBetween * (#buttons - 1) / #buttons)
|
||||
|
||||
local isButtonStacked = false
|
||||
local fillDirection
|
||||
if self.props.forcedFillDirection then
|
||||
isButtonStacked = self.props.forcedFillDirection == Enum.FillDirection.Vertical
|
||||
fillDirection = self.props.forcedFillDirection
|
||||
else
|
||||
for _, button in ipairs(buttons) do
|
||||
local buttonTextWidth = GetTextSize(
|
||||
button.props.text or "",
|
||||
textSize,
|
||||
font.Body.Font,
|
||||
Vector2.new(self.state.frameWidth, self.props.buttonHeight)
|
||||
)
|
||||
if buttonTextWidth.X > (nonStackedButtonWidth - (2 * self.props.minHorizontalButtonPadding)) then
|
||||
isButtonStacked = true
|
||||
break
|
||||
end
|
||||
end
|
||||
fillDirection = isButtonStacked and Enum.FillDirection.Vertical or Enum.FillDirection.Horizontal
|
||||
end
|
||||
|
||||
local buttonSize = isButtonStacked and UDim2.new(1, 0, 0, self.props.buttonHeight)
|
||||
or UDim2.new(0, nonStackedButtonWidth, 0, self.props.buttonHeight)
|
||||
|
||||
local buttonTable = {}
|
||||
for colIndex, button in ipairs(buttons) do
|
||||
local newProps = {
|
||||
layoutOrder = isButtonStacked and (#buttons - colIndex) or colIndex,
|
||||
size = buttonSize,
|
||||
}
|
||||
local buttonProps = Cryo.Dictionary.join(newProps, button.props)
|
||||
|
||||
local buttonComponent
|
||||
if button.buttonType == ButtonType.PrimaryContextual then
|
||||
buttonComponent = PrimaryContextualButton
|
||||
elseif button.buttonType == ButtonType.PrimarySystem then
|
||||
buttonComponent = PrimarySystemButton
|
||||
elseif button.buttonType == ButtonType.Alert then
|
||||
buttonComponent = AlertButton
|
||||
else
|
||||
buttonComponent = SecondaryButton
|
||||
end
|
||||
|
||||
if UIBloxConfig.enableExperimentalGamepadSupport then
|
||||
local gamepadFrameProps = {
|
||||
Size = buttonSize,
|
||||
BackgroundTransparency = 1,
|
||||
[Roact.Ref] = self.buttonRefs[colIndex],
|
||||
NextSelectionUp = (isButtonStacked and colIndex > 1) and self.buttonRefs[colIndex - 1] or nil,
|
||||
NextSelectionDown = (isButtonStacked and colIndex < #buttons) and self.buttonRefs[colIndex + 1] or nil,
|
||||
NextSelectionLeft = (not isButtonStacked and colIndex > 1) and self.buttonRefs[colIndex - 1] or nil,
|
||||
NextSelectionRight = (not isButtonStacked and colIndex < #buttons) and self.buttonRefs[colIndex + 1] or nil,
|
||||
inputBindings = {
|
||||
Activated = RoactGamepad.Input.onBegin(Enum.KeyCode.ButtonA, button.props.onActivated),
|
||||
},
|
||||
}
|
||||
|
||||
table.insert(buttonTable, Roact.createElement(RoactGamepad.Focusable.Frame, gamepadFrameProps, {
|
||||
Roact.createElement(buttonComponent, buttonProps)
|
||||
}))
|
||||
else
|
||||
table.insert(buttonTable, Roact.createElement(buttonComponent, buttonProps))
|
||||
end
|
||||
end
|
||||
|
||||
return Roact.createElement(UIBloxConfig.enableExperimentalGamepadSupport and
|
||||
RoactGamepad.Focusable[FitFrameOnAxis] or FitFrameOnAxis, {
|
||||
BackgroundTransparency = 1,
|
||||
contentPadding = UDim.new(0, paddingBetween),
|
||||
FillDirection = fillDirection,
|
||||
HorizontalAlignment = Enum.HorizontalAlignment.Center,
|
||||
LayoutOrder = 3,
|
||||
minimumSize = UDim2.new(1, 0, 0, self.props.buttonHeight),
|
||||
[Roact.Ref] = self.props[Roact.Ref],
|
||||
[Roact.Change.AbsoluteSize] = self.updateFrameSize,
|
||||
|
||||
NextSelectionLeft = self.props.NextSelectionLeft,
|
||||
NextSelectionRight = self.props.NextSelectionRight,
|
||||
NextSelectionUp = self.props.NextSelectionUp,
|
||||
NextSelectionDown = self.props.NextSelectionDown,
|
||||
},
|
||||
buttonTable
|
||||
)
|
||||
end)
|
||||
end
|
||||
|
||||
return ButtonStack
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
local ButtonRoot = script.Parent
|
||||
local AppRoot = ButtonRoot.Parent
|
||||
local UIBlox = AppRoot.Parent
|
||||
local Packages = UIBlox.Parent
|
||||
|
||||
local Roact = require(Packages.Roact)
|
||||
|
||||
local mockStyleComponent = require(UIBlox.Utility.mockStyleComponent)
|
||||
|
||||
local ButtonStack = require(script.Parent.ButtonStack)
|
||||
|
||||
local DEFAULT_REQUIRED_PROPS = {
|
||||
buttons = {
|
||||
{
|
||||
props = {
|
||||
text = "test",
|
||||
onActivated = function() end,
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
return function()
|
||||
describe("lifecycle", function()
|
||||
it("should mount and unmount button stacks without issue", function()
|
||||
local tree = mockStyleComponent(
|
||||
Roact.createElement(ButtonStack, DEFAULT_REQUIRED_PROPS)
|
||||
)
|
||||
local handle = Roact.mount(tree)
|
||||
Roact.unmount(handle)
|
||||
end)
|
||||
end)
|
||||
end
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
local ButtonRoot = script.Parent.Parent
|
||||
local AppRoot = ButtonRoot.Parent
|
||||
local UIBlox = AppRoot.Parent
|
||||
local Packages = UIBlox.Parent
|
||||
|
||||
local enumerate = require(Packages.enumerate)
|
||||
|
||||
return enumerate("ButtonType", {
|
||||
"Alert",
|
||||
"PrimaryContextual",
|
||||
"PrimarySystem",
|
||||
"Secondary",
|
||||
})
|
||||
+153
@@ -0,0 +1,153 @@
|
||||
local App = script:FindFirstAncestor("App")
|
||||
local UIBlox = App.Parent
|
||||
local Core = UIBlox.Core
|
||||
local Packages = UIBlox.Parent
|
||||
|
||||
local t = require(Packages.t)
|
||||
local Roact = require(Packages.Roact)
|
||||
local enumerate = require(Packages.enumerate)
|
||||
|
||||
local Interactable = require(Core.Control.Interactable)
|
||||
|
||||
local ControlState = require(Core.Control.Enum.ControlState)
|
||||
local getContentStyle = require(Core.Button.getContentStyle)
|
||||
local getIconSize = require(App.ImageSet.getIconSize)
|
||||
local enumerateValidator = require(UIBlox.Utility.enumerateValidator)
|
||||
local bindingValidator = require(Core.Utility.bindingValidator)
|
||||
local validateImage = require(Core.ImageSet.Validator.validateImage)
|
||||
|
||||
local withStyle = require(Core.Style.withStyle)
|
||||
local HoverButtonBackground = require(Core.Button.HoverButtonBackground)
|
||||
local ImageSetComponent = require(Core.ImageSet.ImageSetComponent)
|
||||
local IconSize = require(App.ImageSet.Enum.IconSize)
|
||||
|
||||
local IconButton = Roact.PureComponent:extend("IconButton")
|
||||
IconButton.debugProps = enumerate("debugProps", {
|
||||
"controlState",
|
||||
})
|
||||
|
||||
IconButton.validateProps = t.strictInterface({
|
||||
-- The state change callback for the button
|
||||
onStateChanged = t.optional(t.callback),
|
||||
|
||||
-- Is the button visually disabled
|
||||
isDisabled = t.optional(t.boolean),
|
||||
|
||||
colorStyleDefault = t.optional(t.string),
|
||||
colorStyleHover = t.optional(t.string),
|
||||
|
||||
--A Boolean value that determines whether user events are ignored and sink input
|
||||
userInteractionEnabled = t.optional(t.boolean),
|
||||
|
||||
-- The activated callback for the button
|
||||
onActivated = t.optional(t.callback),
|
||||
|
||||
anchorPoint = t.optional(t.Vector2),
|
||||
layoutOrder = t.optional(t.number),
|
||||
position = t.optional(t.UDim2),
|
||||
size = t.optional(t.UDim2),
|
||||
icon = t.optional(validateImage),
|
||||
iconSize = t.optional(enumerateValidator(IconSize)),
|
||||
iconColor3 = t.optional(t.Color3),
|
||||
iconTransparency = t.optional(t.union(t.number, bindingValidator(t.number))),
|
||||
|
||||
-- Override the default controlState
|
||||
[IconButton.debugProps.controlState] = t.optional(enumerateValidator(ControlState)),
|
||||
})
|
||||
|
||||
IconButton.defaultProps = {
|
||||
anchorPoint = Vector2.new(0, 0),
|
||||
layoutOrder = 0,
|
||||
position = UDim2.new(0, 0, 0, 0),
|
||||
size = nil,
|
||||
icon = "",
|
||||
iconSize = IconSize.Medium,
|
||||
|
||||
colorStyleDefault = "SystemPrimaryDefault",
|
||||
colorStyleHover = "SystemPrimaryDefault",
|
||||
iconColor3 = nil,
|
||||
iconTransparency = nil,
|
||||
|
||||
isDisabled = false,
|
||||
userInteractionEnabled = true,
|
||||
|
||||
[IconButton.debugProps.controlState] = nil,
|
||||
}
|
||||
|
||||
function IconButton:init()
|
||||
self:setState({
|
||||
controlState = ControlState.Initialize
|
||||
})
|
||||
|
||||
self.onStateChanged = function(oldState, newState)
|
||||
self:setState({
|
||||
controlState = newState,
|
||||
})
|
||||
if self.props.onStateChanged then
|
||||
self.props.onStateChanged(oldState, newState)
|
||||
end
|
||||
end
|
||||
|
||||
local iconSizeToSizeScale = {
|
||||
[IconSize.Small] = 1,
|
||||
[IconSize.Medium] = 2,
|
||||
[IconSize.Large] = 3,
|
||||
[IconSize.XLarge] = 4,
|
||||
[IconSize.XXLarge] = 5,
|
||||
}
|
||||
self.getSize = function(iconSizeMeasurement)
|
||||
if self.props.size then
|
||||
return self.props.size
|
||||
end
|
||||
|
||||
local iconSize = self.props.iconSize
|
||||
local extents = iconSizeMeasurement + 4 * iconSizeToSizeScale[iconSize]
|
||||
return UDim2.fromOffset(extents, extents)
|
||||
end
|
||||
end
|
||||
|
||||
function IconButton:render()
|
||||
return withStyle(function(style)
|
||||
local iconSizeMeasurement = getIconSize(self.props.iconSize)
|
||||
local size = self.getSize(iconSizeMeasurement)
|
||||
local currentState = self.props[IconButton.debugProps.controlState] or self.state.controlState
|
||||
|
||||
local iconStateColorMap = {
|
||||
[ControlState.Default] = self.props.colorStyleDefault,
|
||||
[ControlState.Hover] = self.props.colorStyleHover,
|
||||
}
|
||||
|
||||
local iconStyle = getContentStyle(iconStateColorMap, currentState, style)
|
||||
|
||||
return Roact.createElement(Interactable, {
|
||||
AnchorPoint = self.props.anchorPoint,
|
||||
LayoutOrder = self.props.layoutOrder,
|
||||
Position = self.props.position,
|
||||
Size = size,
|
||||
|
||||
isDisabled = self.props.isDisabled,
|
||||
onStateChanged = self.onStateChanged,
|
||||
userInteractionEnabled = self.props.userInteractionEnabled,
|
||||
BackgroundTransparency = 1,
|
||||
AutoButtonColor = false,
|
||||
|
||||
[Roact.Event.Activated] = self.props.onActivated,
|
||||
}, {
|
||||
sizeConstraint = Roact.createElement("UISizeConstraint", {
|
||||
MinSize = Vector2.new(iconSizeMeasurement, iconSizeMeasurement),
|
||||
}),
|
||||
imageLabel = Roact.createElement(ImageSetComponent.Label, {
|
||||
AnchorPoint = Vector2.new(0.5, 0.5),
|
||||
Position = UDim2.fromScale(0.5, 0.5),
|
||||
Size = UDim2.fromOffset(iconSizeMeasurement, iconSizeMeasurement),
|
||||
BackgroundTransparency = 1,
|
||||
Image = self.props.icon,
|
||||
ImageColor3 = self.props.iconColor3 or iconStyle.Color,
|
||||
ImageTransparency = self.props.iconTransparency or iconStyle.Transparency,
|
||||
}),
|
||||
background = currentState == ControlState.Hover and Roact.createElement(HoverButtonBackground),
|
||||
})
|
||||
end)
|
||||
end
|
||||
|
||||
return IconButton
|
||||
+268
@@ -0,0 +1,268 @@
|
||||
return function()
|
||||
local IconButton = require(script.Parent.IconButton)
|
||||
|
||||
local App = script:FindFirstAncestor("App")
|
||||
local UIBlox = App.Parent
|
||||
local Core = UIBlox.Core
|
||||
local Packages = UIBlox.Parent
|
||||
|
||||
local Roact = require(Packages.Roact)
|
||||
local mockStyleComponent = require(UIBlox.Utility.mockStyleComponent)
|
||||
local ControlState = require(Core.Control.Enum.ControlState)
|
||||
local IconSize = require(App.ImageSet.Enum.IconSize)
|
||||
|
||||
describe("props", function()
|
||||
local BUTTON_NAME = "test:" .. tostring(math.random(0, 999))
|
||||
local runTest = function(props)
|
||||
local folder = Instance.new("Folder")
|
||||
local element = mockStyleComponent({
|
||||
[BUTTON_NAME] = Roact.createElement(IconButton, props),
|
||||
})
|
||||
|
||||
local instance = Roact.mount(element, folder)
|
||||
|
||||
return folder, function()
|
||||
Roact.unmount(instance)
|
||||
folder:Destroy()
|
||||
end
|
||||
end
|
||||
|
||||
local function getImageLabel(folder)
|
||||
return folder:FindFirstChild("imageLabel", true)
|
||||
end
|
||||
|
||||
local function getGuiObjectRoot(folder)
|
||||
return folder:FindFirstChild(BUTTON_NAME, true)
|
||||
end
|
||||
|
||||
local function getIconColor3(folder)
|
||||
return getImageLabel(folder).ImageColor3
|
||||
end
|
||||
|
||||
local function getIconTransparency(folder)
|
||||
return getImageLabel(folder).ImageTransparency
|
||||
end
|
||||
|
||||
local function getGuiObjectRootAbsoluteSize(folder)
|
||||
return getGuiObjectRoot(folder).AbsoluteSize
|
||||
end
|
||||
|
||||
local function getGuiObjectRootSize(folder)
|
||||
return getGuiObjectRoot(folder).Size
|
||||
end
|
||||
|
||||
describe("iconSize", function()
|
||||
it("SHOULD resize gui object root AbsoluteSize", function()
|
||||
local smallFolder, smallCleanup = runTest({
|
||||
iconSize = IconSize.Small,
|
||||
})
|
||||
|
||||
local mediumFolder, mediumCleanup = runTest({
|
||||
iconSize = IconSize.Medium,
|
||||
})
|
||||
|
||||
expect(getGuiObjectRootAbsoluteSize(smallFolder)).to.never.equal(getGuiObjectRootAbsoluteSize(mediumFolder))
|
||||
|
||||
smallCleanup()
|
||||
mediumCleanup()
|
||||
end)
|
||||
end)
|
||||
|
||||
describe("appearance override props", function()
|
||||
it("SHOULD override ImageLabel.ImageColor3 with iconColor3", function()
|
||||
for _ = 1, 50 do
|
||||
local randomColor = BrickColor.random().Color
|
||||
local folder, cleanup = runTest({
|
||||
iconColor3 = randomColor,
|
||||
})
|
||||
|
||||
expect(getIconColor3(folder)).to.equal(randomColor)
|
||||
|
||||
cleanup()
|
||||
end
|
||||
end)
|
||||
|
||||
it("SHOULD override ImageLabel.ImageTransparency with iconTransparency", function()
|
||||
for transparency = 0, 1, 0.1 do
|
||||
local folder, cleanup = runTest({
|
||||
iconTransparency = transparency,
|
||||
})
|
||||
|
||||
expect(getIconTransparency(folder)).to.be.near(transparency, 0.001)
|
||||
|
||||
cleanup()
|
||||
end
|
||||
end)
|
||||
|
||||
it("SHOULD override ImageLabel.ImageTransparency with iconTransparency from RoactBinding value", function()
|
||||
for transparency = 0, 1, 0.1 do
|
||||
local folder, cleanup = runTest({
|
||||
iconTransparency = Roact.createBinding(transparency),
|
||||
})
|
||||
|
||||
expect(getIconTransparency(folder)).to.be.near(transparency, 0.001)
|
||||
|
||||
cleanup()
|
||||
end
|
||||
end)
|
||||
|
||||
it("SHOULD override root guiObject.AbsoluteSize with size", function()
|
||||
local testSizes = {
|
||||
UDim2.fromScale(0.5, 0.5),
|
||||
UDim2.fromScale(1, 1),
|
||||
UDim2.fromOffset(1000, 10),
|
||||
UDim2.fromOffset(0, 100),
|
||||
}
|
||||
for _, size in ipairs(testSizes) do
|
||||
local controlGroupFolder, cleanupControlGroup = runTest({
|
||||
size = nil,
|
||||
})
|
||||
|
||||
local variableGroupFolder, cleanupVariableGroup = runTest({
|
||||
size = size,
|
||||
})
|
||||
|
||||
local controlSize = getGuiObjectRootAbsoluteSize(controlGroupFolder)
|
||||
local variableSize = getGuiObjectRootAbsoluteSize(variableGroupFolder)
|
||||
expect(controlSize).to.never.equal(variableSize)
|
||||
|
||||
expect(getGuiObjectRootSize(variableGroupFolder)).to.equal(size)
|
||||
|
||||
cleanupControlGroup()
|
||||
cleanupVariableGroup()
|
||||
end
|
||||
end)
|
||||
end)
|
||||
|
||||
describe("positional props", function()
|
||||
it("SHOULD respect AnchorPoint", function()
|
||||
local function testAnchorPoint(anchorPoint)
|
||||
local folder, cleanup = runTest({
|
||||
anchorPoint = anchorPoint,
|
||||
})
|
||||
|
||||
local guiObject = folder:FindFirstChild(BUTTON_NAME, true)
|
||||
expect(guiObject.AnchorPoint).to.equal(anchorPoint)
|
||||
|
||||
cleanup()
|
||||
end
|
||||
|
||||
testAnchorPoint(Vector2.new(0, 0))
|
||||
testAnchorPoint(Vector2.new(0, 1))
|
||||
testAnchorPoint(Vector2.new(1, 0))
|
||||
testAnchorPoint(Vector2.new(1, 1))
|
||||
testAnchorPoint(Vector2.new(0.5, 0.5))
|
||||
end)
|
||||
|
||||
it("SHOULD respect Position", function()
|
||||
local function testPosition(position)
|
||||
local folder, cleanup = runTest({
|
||||
position = position,
|
||||
})
|
||||
|
||||
local guiObject = folder:FindFirstChild(BUTTON_NAME, true)
|
||||
expect(guiObject.Position).to.equal(position)
|
||||
|
||||
cleanup()
|
||||
end
|
||||
|
||||
testPosition(UDim2.new(0, 0, 0, 0))
|
||||
testPosition(UDim2.new(0.5, 10, 1, 20))
|
||||
testPosition(UDim2.fromScale(1, 1))
|
||||
testPosition(UDim2.fromOffset(100, 000))
|
||||
end)
|
||||
|
||||
it("SHOULD respect LayoutOrder", function()
|
||||
local function testLayoutOrder(layoutOrder)
|
||||
local folder, cleanup = runTest({
|
||||
layoutOrder = layoutOrder,
|
||||
})
|
||||
|
||||
local guiObject = folder:FindFirstChild(BUTTON_NAME, true)
|
||||
expect(guiObject.LayoutOrder).to.equal(layoutOrder)
|
||||
|
||||
cleanup()
|
||||
end
|
||||
|
||||
testLayoutOrder(0)
|
||||
testLayoutOrder(1)
|
||||
testLayoutOrder(2)
|
||||
end)
|
||||
|
||||
it("SHOULD respect Size", function()
|
||||
local function testSize(size)
|
||||
local folder, cleanup = runTest({
|
||||
size = size,
|
||||
})
|
||||
|
||||
local guiObject = folder:FindFirstChild(BUTTON_NAME, true)
|
||||
expect(guiObject.Size).to.equal(size)
|
||||
|
||||
cleanup()
|
||||
end
|
||||
|
||||
testSize(UDim2.new(0, 0, 0, 0))
|
||||
testSize(UDim2.new(0.5, 10, 1, 20))
|
||||
testSize(UDim2.fromScale(1, 1))
|
||||
testSize(UDim2.fromOffset(100, 000))
|
||||
end)
|
||||
end)
|
||||
|
||||
describe("debugProps.controlState", function()
|
||||
local function isShowingBackground(folder)
|
||||
return folder:FindFirstChild("background", true) ~= nil
|
||||
end
|
||||
|
||||
local function isImageTransparent(folder)
|
||||
local imageLabel = folder:FindFirstChild("imageLabel", true)
|
||||
assert(imageLabel, "imageLabel never mounted")
|
||||
return imageLabel.ImageTransparency > 0
|
||||
end
|
||||
|
||||
it("SHOULD render ControlState.Default with no issues", function()
|
||||
local folder, cleanup = runTest({
|
||||
[IconButton.debugProps.controlState] = ControlState.Default,
|
||||
})
|
||||
|
||||
expect(isShowingBackground(folder)).to.equal(false)
|
||||
expect(isImageTransparent(folder)).to.equal(false)
|
||||
|
||||
cleanup()
|
||||
end)
|
||||
|
||||
it("SHOULD render ControlState.Hover with no issues", function()
|
||||
local folder, cleanup = runTest({
|
||||
[IconButton.debugProps.controlState] = ControlState.Hover,
|
||||
})
|
||||
|
||||
expect(isShowingBackground(folder)).to.equal(true)
|
||||
expect(isImageTransparent(folder)).to.equal(false)
|
||||
|
||||
cleanup()
|
||||
end)
|
||||
|
||||
it("SHOULD render ControlState.Pressed with no issues", function()
|
||||
local folder, cleanup = runTest({
|
||||
[IconButton.debugProps.controlState] = ControlState.Pressed,
|
||||
})
|
||||
|
||||
expect(isShowingBackground(folder)).to.equal(false)
|
||||
expect(isImageTransparent(folder)).to.equal(true)
|
||||
|
||||
cleanup()
|
||||
end)
|
||||
|
||||
it("SHOULD render ControlState.Disabled with no issues", function()
|
||||
local folder, cleanup = runTest({
|
||||
[IconButton.debugProps.controlState] = ControlState.Disabled,
|
||||
})
|
||||
|
||||
expect(isShowingBackground(folder)).to.equal(false)
|
||||
expect(isImageTransparent(folder)).to.equal(true)
|
||||
|
||||
cleanup()
|
||||
end)
|
||||
end)
|
||||
end)
|
||||
|
||||
end
|
||||
+55
@@ -0,0 +1,55 @@
|
||||
local Button = script.Parent
|
||||
local App = Button.Parent
|
||||
local UIBlox = App.Parent
|
||||
local Packages = UIBlox.Parent
|
||||
|
||||
local Roact = require(Packages.Roact)
|
||||
|
||||
local Images = require(App.ImageSet.Images)
|
||||
local CursorKind = require(App.SelectionImage.CursorKind)
|
||||
local withSelectionCursorProvider = require(App.SelectionImage.withSelectionCursorProvider)
|
||||
local validateButtonProps = require(Button.validateButtonProps)
|
||||
local GenericButton = require(UIBlox.Core.Button.GenericButton)
|
||||
local ControlState = require(UIBlox.Core.Control.Enum.ControlState)
|
||||
|
||||
local PrimaryContextualButton = Roact.PureComponent:extend("PrimaryContextualButton")
|
||||
|
||||
local BUTTON_STATE_COLOR = {
|
||||
[ControlState.Default] = "ContextualPrimaryDefault",
|
||||
[ControlState.Hover] = "ContextualPrimaryOnHover",
|
||||
}
|
||||
|
||||
local CONTENT_STATE_COLOR = {
|
||||
[ControlState.Default] = "ContextualPrimaryContent",
|
||||
}
|
||||
|
||||
PrimaryContextualButton.defaultProps = {
|
||||
isDisabled = false,
|
||||
isLoading = false,
|
||||
}
|
||||
|
||||
function PrimaryContextualButton:render()
|
||||
assert(validateButtonProps(self.props))
|
||||
local image = Images["component_assets/circle_17"]
|
||||
return withSelectionCursorProvider(function(getSelectionCursor)
|
||||
return Roact.createElement(GenericButton, {
|
||||
Size = self.props.size,
|
||||
AnchorPoint = self.props.anchorPoint,
|
||||
Position = self.props.position,
|
||||
LayoutOrder = self.props.layoutOrder,
|
||||
SelectionImageObject = getSelectionCursor(CursorKind.RoundedRectNoInset),
|
||||
icon = self.props.icon,
|
||||
text = self.props.text,
|
||||
isDisabled = self.props.isDisabled,
|
||||
isLoading = self.props.isLoading,
|
||||
onActivated = self.props.onActivated,
|
||||
onStateChanged = self.props.onStateChanged,
|
||||
userInteractionEnabled = self.props.userInteractionEnabled,
|
||||
buttonImage = image,
|
||||
buttonStateColorMap = BUTTON_STATE_COLOR,
|
||||
contentStateColorMap = CONTENT_STATE_COLOR,
|
||||
})
|
||||
end)
|
||||
end
|
||||
|
||||
return PrimaryContextualButton
|
||||
+62
@@ -0,0 +1,62 @@
|
||||
return function()
|
||||
local Button = script.Parent
|
||||
local App = Button.Parent
|
||||
local UIBlox = App.Parent
|
||||
local Packages = UIBlox.Parent
|
||||
|
||||
local Roact = require(Packages.Roact)
|
||||
local Images = require(App.ImageSet.Images)
|
||||
|
||||
local icon = Images["icons/common/robux_small"]
|
||||
local mockStyleComponent = require(UIBlox.Utility.mockStyleComponent)
|
||||
|
||||
local PrimaryContextualButton = require(Button.PrimaryContextualButton)
|
||||
|
||||
it("should create and destroy Primary Contextual Button with text without errors", function()
|
||||
local element = mockStyleComponent({
|
||||
button = Roact.createElement(PrimaryContextualButton, {
|
||||
text = "Button",
|
||||
onActivated = function()end,
|
||||
}),
|
||||
})
|
||||
|
||||
local instance = Roact.mount(element)
|
||||
Roact.unmount(instance)
|
||||
end)
|
||||
|
||||
it("should create and destroy Primary Contextual Button with text icon only without errors", function()
|
||||
local element = mockStyleComponent({
|
||||
button = Roact.createElement(PrimaryContextualButton, {
|
||||
icon = icon,
|
||||
onActivated = function()end,
|
||||
}),
|
||||
})
|
||||
|
||||
local instance = Roact.mount(element)
|
||||
Roact.unmount(instance)
|
||||
end)
|
||||
|
||||
it("should create and destroy Primary Contextual Button with text and text without errors", function()
|
||||
local element = mockStyleComponent({
|
||||
button = Roact.createElement(PrimaryContextualButton, {
|
||||
text = "Button",
|
||||
icon = icon,
|
||||
onActivated = function()end,
|
||||
}),
|
||||
})
|
||||
|
||||
local instance = Roact.mount(element)
|
||||
Roact.unmount(instance)
|
||||
end)
|
||||
|
||||
it("should create and destroy a blank Primary Contextual Button without errors", function()
|
||||
local element = mockStyleComponent({
|
||||
button = Roact.createElement(PrimaryContextualButton, {
|
||||
onActivated = function()end,
|
||||
}),
|
||||
})
|
||||
|
||||
local instance = Roact.mount(element)
|
||||
Roact.unmount(instance)
|
||||
end)
|
||||
end
|
||||
+56
@@ -0,0 +1,56 @@
|
||||
local Button = script.Parent
|
||||
local App = Button.Parent
|
||||
local UIBlox = App.Parent
|
||||
local Packages = UIBlox.Parent
|
||||
|
||||
local Roact = require(Packages.Roact)
|
||||
|
||||
local Images = require(App.ImageSet.Images)
|
||||
local CursorKind = require(App.SelectionImage.CursorKind)
|
||||
local withSelectionCursorProvider = require(App.SelectionImage.withSelectionCursorProvider)
|
||||
local validateButtonProps = require(Button.validateButtonProps)
|
||||
local GenericButton = require(UIBlox.Core.Button.GenericButton)
|
||||
local ControlState = require(UIBlox.Core.Control.Enum.ControlState)
|
||||
|
||||
local PrimarySystemButton = Roact.PureComponent:extend("PrimarySystemButton")
|
||||
|
||||
local BUTTON_STATE_COLOR = {
|
||||
[ControlState.Default] = "SystemPrimaryDefault",
|
||||
[ControlState.Hover] = "SystemPrimaryOnHover",
|
||||
}
|
||||
|
||||
local CONTENT_STATE_COLOR = {
|
||||
[ControlState.Default] = "SystemPrimaryContent",
|
||||
}
|
||||
|
||||
|
||||
PrimarySystemButton.defaultProps = {
|
||||
isDisabled = false,
|
||||
isLoading = false,
|
||||
}
|
||||
|
||||
function PrimarySystemButton:render()
|
||||
assert(validateButtonProps(self.props))
|
||||
local image = Images["component_assets/circle_17"]
|
||||
return withSelectionCursorProvider(function(getSelectionCursor)
|
||||
return Roact.createElement(GenericButton, {
|
||||
Size = self.props.size,
|
||||
AnchorPoint = self.props.anchorPoint,
|
||||
Position = self.props.position,
|
||||
LayoutOrder = self.props.layoutOrder,
|
||||
SelectionImageObject = getSelectionCursor(CursorKind.RoundedRectNoInset),
|
||||
icon = self.props.icon,
|
||||
text = self.props.text,
|
||||
isDisabled = self.props.isDisabled,
|
||||
isLoading = self.props.isLoading,
|
||||
onActivated = self.props.onActivated,
|
||||
onStateChanged = self.props.onStateChanged,
|
||||
userInteractionEnabled = self.props.userInteractionEnabled,
|
||||
buttonImage = image,
|
||||
buttonStateColorMap = BUTTON_STATE_COLOR,
|
||||
contentStateColorMap = CONTENT_STATE_COLOR,
|
||||
})
|
||||
end)
|
||||
end
|
||||
|
||||
return PrimarySystemButton
|
||||
+62
@@ -0,0 +1,62 @@
|
||||
return function()
|
||||
local Button = script.Parent
|
||||
local App = Button.Parent
|
||||
local UIBlox = App.Parent
|
||||
local Packages = UIBlox.Parent
|
||||
|
||||
local Roact = require(Packages.Roact)
|
||||
local Images = require(App.ImageSet.Images)
|
||||
|
||||
local icon = Images["icons/common/robux_small"]
|
||||
local mockStyleComponent = require(UIBlox.Utility.mockStyleComponent)
|
||||
|
||||
local PrimarySystemButton = require(Button.PrimarySystemButton)
|
||||
|
||||
it("should create and destroy Primary System Button with text without errors", function()
|
||||
local element = mockStyleComponent({
|
||||
button = Roact.createElement(PrimarySystemButton, {
|
||||
text = "Button",
|
||||
onActivated = function()end,
|
||||
}),
|
||||
})
|
||||
|
||||
local instance = Roact.mount(element)
|
||||
Roact.unmount(instance)
|
||||
end)
|
||||
|
||||
it("should create and destroy Primary System Button with text icon only without errors", function()
|
||||
local element = mockStyleComponent({
|
||||
button = Roact.createElement(PrimarySystemButton, {
|
||||
icon = icon,
|
||||
onActivated = function()end,
|
||||
}),
|
||||
})
|
||||
|
||||
local instance = Roact.mount(element)
|
||||
Roact.unmount(instance)
|
||||
end)
|
||||
|
||||
it("should create and destroy Primary System Button with text and text without errors", function()
|
||||
local element = mockStyleComponent({
|
||||
button = Roact.createElement(PrimarySystemButton, {
|
||||
text = "Button",
|
||||
icon = icon,
|
||||
onActivated = function()end,
|
||||
}),
|
||||
})
|
||||
|
||||
local instance = Roact.mount(element)
|
||||
Roact.unmount(instance)
|
||||
end)
|
||||
|
||||
it("should create and destroy a blank Primary System Button without errors", function()
|
||||
local element = mockStyleComponent({
|
||||
button = Roact.createElement(PrimarySystemButton, {
|
||||
onActivated = function()end,
|
||||
}),
|
||||
})
|
||||
|
||||
local instance = Roact.mount(element)
|
||||
Roact.unmount(instance)
|
||||
end)
|
||||
end
|
||||
+56
@@ -0,0 +1,56 @@
|
||||
local Button = script.Parent
|
||||
local App = Button.Parent
|
||||
local UIBlox = App.Parent
|
||||
local Packages = UIBlox.Parent
|
||||
|
||||
local Roact = require(Packages.Roact)
|
||||
|
||||
local Images = require(App.ImageSet.Images)
|
||||
local CursorKind = require(App.SelectionImage.CursorKind)
|
||||
local withSelectionCursorProvider = require(App.SelectionImage.withSelectionCursorProvider)
|
||||
local validateButtonProps = require(Button.validateButtonProps)
|
||||
local GenericButton = require(UIBlox.Core.Button.GenericButton)
|
||||
local ControlState = require(UIBlox.Core.Control.Enum.ControlState)
|
||||
|
||||
local SecondaryButton = Roact.PureComponent:extend("SecondaryButton")
|
||||
|
||||
local BUTTON_STATE_COLOR = {
|
||||
[ControlState.Default] = "SecondaryDefault",
|
||||
[ControlState.Hover] = "SecondaryOnHover",
|
||||
}
|
||||
|
||||
local CONTENT_STATE_COLOR = {
|
||||
[ControlState.Default] = "SecondaryContent",
|
||||
[ControlState.Hover] = "SecondaryOnHover",
|
||||
}
|
||||
|
||||
SecondaryButton.defaultProps = {
|
||||
isDisabled = false,
|
||||
isLoading = false,
|
||||
}
|
||||
|
||||
function SecondaryButton:render()
|
||||
assert(validateButtonProps(self.props))
|
||||
local image = Images["component_assets/circle_17_stroke_1"]
|
||||
return withSelectionCursorProvider(function(getSelectionCursor)
|
||||
return Roact.createElement(GenericButton, {
|
||||
Size = self.props.size,
|
||||
AnchorPoint = self.props.anchorPoint,
|
||||
Position = self.props.position,
|
||||
LayoutOrder = self.props.layoutOrder,
|
||||
SelectionImageObject = getSelectionCursor(CursorKind.RoundedRectNoInset),
|
||||
icon = self.props.icon,
|
||||
text = self.props.text,
|
||||
isDisabled = self.props.isDisabled,
|
||||
isLoading = self.props.isLoading,
|
||||
onActivated = self.props.onActivated,
|
||||
onStateChanged = self.props.onStateChanged,
|
||||
userInteractionEnabled = self.props.userInteractionEnabled,
|
||||
buttonImage = image,
|
||||
buttonStateColorMap = BUTTON_STATE_COLOR,
|
||||
contentStateColorMap = CONTENT_STATE_COLOR,
|
||||
})
|
||||
end)
|
||||
end
|
||||
|
||||
return SecondaryButton
|
||||
+62
@@ -0,0 +1,62 @@
|
||||
return function()
|
||||
local Button = script.Parent
|
||||
local App = Button.Parent
|
||||
local UIBlox = App.Parent
|
||||
local Packages = UIBlox.Parent
|
||||
|
||||
local Roact = require(Packages.Roact)
|
||||
local Images = require(App.ImageSet.Images)
|
||||
|
||||
local icon = Images["icons/common/robux_small"]
|
||||
local mockStyleComponent = require(UIBlox.Utility.mockStyleComponent)
|
||||
|
||||
local SecondaryButton = require(Button.SecondaryButton)
|
||||
|
||||
it("should create and destroy Secondary Button with text without errors", function()
|
||||
local element = mockStyleComponent({
|
||||
button = Roact.createElement(SecondaryButton, {
|
||||
text = "Button",
|
||||
onActivated = function()end,
|
||||
}),
|
||||
})
|
||||
|
||||
local instance = Roact.mount(element)
|
||||
Roact.unmount(instance)
|
||||
end)
|
||||
|
||||
it("should create and destroy Secondary Button with text icon only without errors", function()
|
||||
local element = mockStyleComponent({
|
||||
button = Roact.createElement(SecondaryButton, {
|
||||
icon = icon,
|
||||
onActivated = function()end,
|
||||
}),
|
||||
})
|
||||
|
||||
local instance = Roact.mount(element)
|
||||
Roact.unmount(instance)
|
||||
end)
|
||||
|
||||
it("should create and destroy Secondary Button with text and text without errors", function()
|
||||
local element = mockStyleComponent({
|
||||
button = Roact.createElement(SecondaryButton, {
|
||||
text = "Button",
|
||||
icon = icon,
|
||||
onActivated = function()end,
|
||||
}),
|
||||
})
|
||||
|
||||
local instance = Roact.mount(element)
|
||||
Roact.unmount(instance)
|
||||
end)
|
||||
|
||||
it("should create and destroy a blank Secondary Button without errors", function()
|
||||
local element = mockStyleComponent({
|
||||
button = Roact.createElement(SecondaryButton, {
|
||||
onActivated = function()end,
|
||||
}),
|
||||
})
|
||||
|
||||
local instance = Roact.mount(element)
|
||||
Roact.unmount(instance)
|
||||
end)
|
||||
end
|
||||
+139
@@ -0,0 +1,139 @@
|
||||
local App = script:FindFirstAncestor("App")
|
||||
local UIBlox = App.Parent
|
||||
local Core = UIBlox.Core
|
||||
local Packages = UIBlox.Parent
|
||||
|
||||
local t = require(Packages.t)
|
||||
local Roact = require(Packages.Roact)
|
||||
local enumerate = require(Packages.enumerate)
|
||||
|
||||
local Interactable = require(Core.Control.Interactable)
|
||||
|
||||
local ControlState = require(Core.Control.Enum.ControlState)
|
||||
local getContentStyle = require(Core.Button.getContentStyle)
|
||||
local GetTextSize = require(Core.Text.GetTextSize)
|
||||
local enumerateValidator = require(UIBlox.Utility.enumerateValidator)
|
||||
|
||||
local withStyle = require(Core.Style.withStyle)
|
||||
local GenericTextLabel = require(Core.Text.GenericTextLabel.GenericTextLabel)
|
||||
local HoverButtonBackground = require(Core.Button.HoverButtonBackground)
|
||||
|
||||
local VERTICAL_PADDING = 8
|
||||
local HORIZONTAL_PADDING = 11
|
||||
|
||||
local TextButton = Roact.PureComponent:extend("TextButton")
|
||||
TextButton.debugProps = enumerate("debugProps", {
|
||||
"getTextSize",
|
||||
"controlState",
|
||||
})
|
||||
|
||||
TextButton.validateProps = t.strictInterface({
|
||||
-- The state change callback for the button
|
||||
onStateChanged = t.optional(t.callback),
|
||||
|
||||
-- Is the button visually disabled
|
||||
isDisabled = t.optional(t.boolean),
|
||||
|
||||
fontStyle = t.optional(t.string),
|
||||
colorStyleDefault = t.optional(t.string),
|
||||
colorStyleHover = t.optional(t.string),
|
||||
|
||||
--A Boolean value that determines whether user events are ignored and sink input
|
||||
userInteractionEnabled = t.optional(t.boolean),
|
||||
|
||||
-- The activated callback for the button
|
||||
onActivated = t.optional(t.callback),
|
||||
|
||||
anchorPoint = t.optional(t.Vector2),
|
||||
layoutOrder = t.optional(t.number),
|
||||
position= t.optional(t.UDim2),
|
||||
size = t.optional(t.UDim2),
|
||||
text = t.optional(t.string),
|
||||
|
||||
-- A callback that replaces getTextSize implementation
|
||||
[TextButton.debugProps.getTextSize] = t.optional(t.callback),
|
||||
|
||||
-- Override the default controlState
|
||||
[TextButton.debugProps.controlState] = t.optional(enumerateValidator(ControlState)),
|
||||
})
|
||||
|
||||
TextButton.defaultProps = {
|
||||
anchorPoint = Vector2.new(0, 0),
|
||||
layoutOrder = 0,
|
||||
position = UDim2.new(0, 0, 0, 0),
|
||||
size = UDim2.fromScale(0, 0),
|
||||
text = "",
|
||||
|
||||
fontStyle = "Header2",
|
||||
colorStyleDefault = "SystemPrimaryDefault",
|
||||
colorStyleHover = "SystemPrimaryDefault",
|
||||
|
||||
isDisabled = false,
|
||||
userInteractionEnabled = true,
|
||||
|
||||
[TextButton.debugProps.getTextSize] = GetTextSize,
|
||||
[TextButton.debugProps.controlState] = nil,
|
||||
}
|
||||
|
||||
function TextButton:init()
|
||||
self:setState({
|
||||
controlState = ControlState.Initialize
|
||||
})
|
||||
|
||||
self.onStateChanged = function(oldState, newState)
|
||||
self:setState({
|
||||
controlState = newState,
|
||||
})
|
||||
if self.props.onStateChanged then
|
||||
self.props.onStateChanged(oldState, newState)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function TextButton:render()
|
||||
return withStyle(function(style)
|
||||
local currentState = self.props[TextButton.debugProps.controlState] or self.state.controlState
|
||||
|
||||
local textStateColorMap = {
|
||||
[ControlState.Default] = self.props.colorStyleDefault,
|
||||
[ControlState.Hover] = self.props.colorStyleHover,
|
||||
}
|
||||
|
||||
local textStyle = getContentStyle(textStateColorMap, currentState, style)
|
||||
local fontStyle = style.Font[self.props.fontStyle]
|
||||
|
||||
local fontSize = fontStyle.RelativeSize * style.Font.BaseSize
|
||||
local getTextSize = self.props[TextButton.debugProps.getTextSize]
|
||||
local textWidth = getTextSize(self.props.text, fontSize, fontStyle.Font, Vector2.new(10000, 0)).X
|
||||
|
||||
return Roact.createElement(Interactable, {
|
||||
AnchorPoint = self.props.anchorPoint,
|
||||
LayoutOrder = self.props.layoutOrder,
|
||||
Position = self.props.position,
|
||||
Size = self.props.size,
|
||||
|
||||
isDisabled = self.props.isDisabled,
|
||||
onStateChanged = self.onStateChanged,
|
||||
userInteractionEnabled = self.props.userInteractionEnabled,
|
||||
BackgroundTransparency = 1,
|
||||
AutoButtonColor = false,
|
||||
|
||||
[Roact.Event.Activated] = self.props.onActivated,
|
||||
}, {
|
||||
sizeConstraint = Roact.createElement("UISizeConstraint", {
|
||||
MinSize = Vector2.new(textWidth + VERTICAL_PADDING*2, fontSize + HORIZONTAL_PADDING*2),
|
||||
}),
|
||||
textLabel = Roact.createElement(GenericTextLabel, {
|
||||
AnchorPoint = Vector2.new(0.5, 0.5),
|
||||
Position = UDim2.fromScale(0.5, 0.5),
|
||||
BackgroundTransparency = 1,
|
||||
Text = self.props.text,
|
||||
fontStyle = fontStyle,
|
||||
colorStyle = textStyle,
|
||||
}),
|
||||
background = currentState == ControlState.Hover and Roact.createElement(HoverButtonBackground)
|
||||
})
|
||||
end)
|
||||
end
|
||||
|
||||
return TextButton
|
||||
+276
@@ -0,0 +1,276 @@
|
||||
return function()
|
||||
local TextButton = require(script.Parent.TextButton)
|
||||
|
||||
local App = script:FindFirstAncestor("App")
|
||||
local UIBlox = App.Parent
|
||||
local Core = UIBlox.Core
|
||||
local Packages = UIBlox.Parent
|
||||
|
||||
local Roact = require(Packages.Roact)
|
||||
local mockStyleComponent = require(UIBlox.Utility.mockStyleComponent)
|
||||
local ControlState = require(Core.Control.Enum.ControlState)
|
||||
|
||||
local noOpt = function()
|
||||
end
|
||||
local text = "Button"
|
||||
|
||||
it("should create and destroy a button without errors", function()
|
||||
local folder = Instance.new("Folder")
|
||||
local element = mockStyleComponent({
|
||||
button = Roact.createElement(TextButton, {
|
||||
text = text,
|
||||
onActivated = noOpt,
|
||||
fontStyle = "Body",
|
||||
colorStyleDefault = "UIDefault",
|
||||
colorStyleHover = "UIDefault",
|
||||
}),
|
||||
})
|
||||
|
||||
local instance = Roact.mount(element, folder)
|
||||
local label = folder:FindFirstChildWhichIsA("TextLabel", true)
|
||||
expect(label.Text).to.equal(text)
|
||||
|
||||
Roact.unmount(instance)
|
||||
end)
|
||||
|
||||
it("should create and destroy a button that is disabled without errors", function()
|
||||
local element = mockStyleComponent({
|
||||
button = Roact.createElement(TextButton, {
|
||||
text = text,
|
||||
onActivated = noOpt,
|
||||
isDisabled = true,
|
||||
}),
|
||||
})
|
||||
|
||||
local instance = Roact.mount(element)
|
||||
Roact.unmount(instance)
|
||||
end)
|
||||
|
||||
it("should create and destroy a button without text without errors", function()
|
||||
local element = mockStyleComponent({
|
||||
button = Roact.createElement(TextButton, {
|
||||
onActivated = noOpt,
|
||||
}),
|
||||
})
|
||||
|
||||
local instance = Roact.mount(element)
|
||||
Roact.unmount(instance)
|
||||
end)
|
||||
|
||||
it("should be created as a disabled button", function()
|
||||
local buttonState = nil
|
||||
local element = mockStyleComponent({
|
||||
button = Roact.createElement(TextButton, {
|
||||
onActivated = noOpt,
|
||||
onStateChanged = function(_, newState)
|
||||
buttonState = newState
|
||||
end,
|
||||
isDisabled = true,
|
||||
}),
|
||||
})
|
||||
|
||||
local instance = Roact.mount(element)
|
||||
expect(buttonState).to.equal(ControlState.Disabled)
|
||||
Roact.unmount(instance)
|
||||
end)
|
||||
|
||||
describe("text prop", function()
|
||||
local BUTTON_NAME = "test:" .. tostring(math.random(0, 999))
|
||||
local runTest = function(props)
|
||||
local folder = Instance.new("Folder")
|
||||
local element = mockStyleComponent({
|
||||
[BUTTON_NAME] = Roact.createElement(TextButton, props),
|
||||
})
|
||||
|
||||
local instance = Roact.mount(element, folder)
|
||||
|
||||
return folder, function()
|
||||
Roact.unmount(instance)
|
||||
folder:Destroy()
|
||||
end
|
||||
end
|
||||
|
||||
it("SHOULD resize to text when not given size property", function()
|
||||
local folder1, cleanup1 = runTest({
|
||||
text = string.rep("!", 1),
|
||||
[TextButton.debugProps.getTextSize] = function()
|
||||
return Vector2.new(1, 1)
|
||||
end,
|
||||
})
|
||||
local folder2, cleanup2 = runTest({
|
||||
text = string.rep("!", 10),
|
||||
[TextButton.debugProps.getTextSize] = function()
|
||||
return Vector2.new(10, 1)
|
||||
end,
|
||||
})
|
||||
|
||||
local firstSize = folder1:FindFirstChild(BUTTON_NAME, true).AbsoluteSize
|
||||
local secondSize = folder2:FindFirstChild(BUTTON_NAME, true).AbsoluteSize
|
||||
|
||||
expect(firstSize).to.never.equal(secondSize)
|
||||
|
||||
cleanup1()
|
||||
cleanup2()
|
||||
end)
|
||||
end)
|
||||
|
||||
describe("positional props", function()
|
||||
local BUTTON_NAME = "test:" .. tostring(math.random(0, 999))
|
||||
local runTest = function(props)
|
||||
local folder = Instance.new("Folder")
|
||||
local element = mockStyleComponent({
|
||||
[BUTTON_NAME] = Roact.createElement(TextButton, props),
|
||||
})
|
||||
|
||||
local instance = Roact.mount(element, folder)
|
||||
|
||||
return folder, function()
|
||||
Roact.unmount(instance)
|
||||
folder:Destroy()
|
||||
end
|
||||
end
|
||||
|
||||
it("SHOULD respect AnchorPoint", function()
|
||||
local function testAnchorPoint(anchorPoint)
|
||||
local folder, cleanup = runTest({
|
||||
anchorPoint = anchorPoint,
|
||||
})
|
||||
|
||||
local guiObject = folder:FindFirstChild(BUTTON_NAME, true)
|
||||
expect(guiObject.AnchorPoint).to.equal(anchorPoint)
|
||||
|
||||
cleanup()
|
||||
end
|
||||
|
||||
testAnchorPoint(Vector2.new(0, 0))
|
||||
testAnchorPoint(Vector2.new(0, 1))
|
||||
testAnchorPoint(Vector2.new(1, 0))
|
||||
testAnchorPoint(Vector2.new(1, 1))
|
||||
testAnchorPoint(Vector2.new(0.5, 0.5))
|
||||
end)
|
||||
|
||||
it("SHOULD respect Position", function()
|
||||
local function testPosition(position)
|
||||
local folder, cleanup = runTest({
|
||||
position = position,
|
||||
})
|
||||
|
||||
local guiObject = folder:FindFirstChild(BUTTON_NAME, true)
|
||||
expect(guiObject.Position).to.equal(position)
|
||||
|
||||
cleanup()
|
||||
end
|
||||
|
||||
testPosition(UDim2.new(0, 0, 0, 0))
|
||||
testPosition(UDim2.new(0.5, 10, 1, 20))
|
||||
testPosition(UDim2.fromScale(1, 1))
|
||||
testPosition(UDim2.fromOffset(100, 000))
|
||||
end)
|
||||
|
||||
it("SHOULD respect LayoutOrder", function()
|
||||
local function testLayoutOrder(layoutOrder)
|
||||
local folder, cleanup = runTest({
|
||||
layoutOrder = layoutOrder,
|
||||
})
|
||||
|
||||
local guiObject = folder:FindFirstChild(BUTTON_NAME, true)
|
||||
expect(guiObject.LayoutOrder).to.equal(layoutOrder)
|
||||
|
||||
cleanup()
|
||||
end
|
||||
|
||||
testLayoutOrder(0)
|
||||
testLayoutOrder(1)
|
||||
testLayoutOrder(2)
|
||||
end)
|
||||
|
||||
it("SHOULD respect Size", function()
|
||||
local function testSize(size)
|
||||
local folder, cleanup = runTest({
|
||||
size = size,
|
||||
})
|
||||
|
||||
local guiObject = folder:FindFirstChild(BUTTON_NAME, true)
|
||||
expect(guiObject.Size).to.equal(size)
|
||||
|
||||
cleanup()
|
||||
end
|
||||
|
||||
testSize(UDim2.new(0, 0, 0, 0))
|
||||
testSize(UDim2.new(0.5, 10, 1, 20))
|
||||
testSize(UDim2.fromScale(1, 1))
|
||||
testSize(UDim2.fromOffset(100, 000))
|
||||
end)
|
||||
end)
|
||||
|
||||
describe("debugProps.controlState", function()
|
||||
local BUTTON_NAME = "test:" .. tostring(math.random(0, 999))
|
||||
local runTest = function(props)
|
||||
local folder = Instance.new("Folder")
|
||||
local element = mockStyleComponent({
|
||||
[BUTTON_NAME] = Roact.createElement(TextButton, props),
|
||||
})
|
||||
|
||||
local instance = Roact.mount(element, folder)
|
||||
|
||||
return folder, function()
|
||||
Roact.unmount(instance)
|
||||
folder:Destroy()
|
||||
end
|
||||
end
|
||||
|
||||
local function isShowingBackground(folder)
|
||||
return folder:FindFirstChild("background", true) ~= nil
|
||||
end
|
||||
|
||||
local function isTextTransparent(folder)
|
||||
local textLabel = folder:FindFirstChild("textLabel", true)
|
||||
assert(textLabel, "textLabel never mounted")
|
||||
return textLabel.TextTransparency > 0
|
||||
end
|
||||
|
||||
it("SHOULD render ControlState.Default with no issues", function()
|
||||
local folder, cleanup = runTest({
|
||||
[TextButton.debugProps.controlState] = ControlState.Default,
|
||||
})
|
||||
|
||||
expect(isShowingBackground(folder)).to.equal(false)
|
||||
expect(isTextTransparent(folder)).to.equal(false)
|
||||
|
||||
cleanup()
|
||||
end)
|
||||
|
||||
it("SHOULD render ControlState.Hover with no issues", function()
|
||||
local folder, cleanup = runTest({
|
||||
[TextButton.debugProps.controlState] = ControlState.Hover,
|
||||
})
|
||||
|
||||
expect(isShowingBackground(folder)).to.equal(true)
|
||||
expect(isTextTransparent(folder)).to.equal(false)
|
||||
|
||||
cleanup()
|
||||
end)
|
||||
|
||||
it("SHOULD render ControlState.Pressed with no issues", function()
|
||||
local folder, cleanup = runTest({
|
||||
[TextButton.debugProps.controlState] = ControlState.Pressed,
|
||||
})
|
||||
|
||||
expect(isShowingBackground(folder)).to.equal(false)
|
||||
expect(isTextTransparent(folder)).to.equal(true)
|
||||
|
||||
cleanup()
|
||||
end)
|
||||
|
||||
it("SHOULD render ControlState.Disabled with no issues", function()
|
||||
local folder, cleanup = runTest({
|
||||
[TextButton.debugProps.controlState] = ControlState.Disabled,
|
||||
})
|
||||
|
||||
expect(isShowingBackground(folder)).to.equal(false)
|
||||
expect(isTextTransparent(folder)).to.equal(true)
|
||||
|
||||
cleanup()
|
||||
end)
|
||||
end)
|
||||
end
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
local validatorRoot = script.Parent
|
||||
local ButtonRoot = validatorRoot.Parent
|
||||
local AppRoot = ButtonRoot.Parent
|
||||
local UIBlox = AppRoot.Parent
|
||||
local Packages = UIBlox.Parent
|
||||
|
||||
local t = require(Packages.t)
|
||||
local Roact = require(Packages.Roact)
|
||||
|
||||
local enumerateValidator = require(UIBlox.Utility.enumerateValidator)
|
||||
local validateButtonProps = require(ButtonRoot.validateButtonProps)
|
||||
|
||||
local ButtonType = require(ButtonRoot.Enum.ButtonType)
|
||||
|
||||
return t.strictInterface({
|
||||
-- buttons: A table of button tables that contain props that PrimaryContextualButton,
|
||||
-- AlertButton, PrimarySystemButton, or SecondaryButton allow. Also contains a prop "buttonType"
|
||||
-- to determine which of these button types to use.
|
||||
buttons = t.array(t.strictInterface({
|
||||
buttonType = t.optional(enumerateValidator(ButtonType)),
|
||||
props = validateButtonProps,
|
||||
})),
|
||||
|
||||
buttonHeight = t.optional(t.numberMin(0)),
|
||||
|
||||
-- forceFillDirection: What fill direction to force into. If nil, then the fillDirection
|
||||
-- will be Vertical and automatically change to Horizontal if any button's text is
|
||||
-- too long.
|
||||
forcedFillDirection = t.optional(t.enum(Enum.FillDirection)),
|
||||
|
||||
-- marginBetween: the margin between each button.
|
||||
marginBetween = t.optional(t.numberMin(0)),
|
||||
|
||||
-- minHorizontalButtonPadding: The minimum left and right padding used to calculate
|
||||
-- the when the button text overflows and automatically changes fillDirection.
|
||||
-- The overflow calculation will be if the length of the button text is over
|
||||
-- the button size - (2 * minHorizontalButtonPadding).
|
||||
minHorizontalButtonPadding = t.optional(t.numberMin(0)),
|
||||
|
||||
-- optional parameters for RoactGamepad
|
||||
NextSelectionLeft = t.optional(t.table),
|
||||
NextSelectionRight = t.optional(t.table),
|
||||
NextSelectionUp = t.optional(t.table),
|
||||
NextSelectionDown = t.optional(t.table),
|
||||
[Roact.Ref] = t.optional(t.table),
|
||||
})
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
local Button = script.Parent
|
||||
local App = Button.Parent
|
||||
local UIBlox = App.Parent
|
||||
local Packages = UIBlox.Parent
|
||||
local Core = UIBlox.Core
|
||||
|
||||
local t = require(Packages.t)
|
||||
|
||||
local validateImage = require(Core.ImageSet.Validator.validateImage)
|
||||
|
||||
return t.strictInterface({
|
||||
--The size of the button
|
||||
size = t.optional(t.UDim2),
|
||||
|
||||
--The anchor point of the button
|
||||
anchorPoint = t.optional(t.Vector2),
|
||||
|
||||
--The position of the button
|
||||
position = t.optional(t.UDim2),
|
||||
|
||||
--The layout order of the button
|
||||
layoutOrder = t.optional(t.number),
|
||||
|
||||
--The icon of the button
|
||||
icon = t.optional(validateImage),
|
||||
|
||||
--The text of the button
|
||||
text = t.optional(t.string),
|
||||
|
||||
--Is the button disabled
|
||||
isDisabled = t.optional(t.boolean),
|
||||
|
||||
--Is the button loading
|
||||
isLoading = t.optional(t.boolean),
|
||||
|
||||
--The activated callback for the button
|
||||
onActivated = t.callback,
|
||||
|
||||
--A Boolean value that determines whether user events are ignored and sink input
|
||||
userInteractionEnabled = t.optional(t.boolean),
|
||||
})
|
||||
+88
@@ -0,0 +1,88 @@
|
||||
local SelectionGroup = script.Parent
|
||||
local Small = SelectionGroup.Parent
|
||||
local Cell = Small.Parent
|
||||
local App = Cell.Parent
|
||||
local UIBlox = App.Parent
|
||||
local Packages = UIBlox.Parent
|
||||
|
||||
local Roact = require(Packages.Roact)
|
||||
local t = require(Packages.t)
|
||||
local Images = require(Packages.UIBlox.App.ImageSet.Images)
|
||||
|
||||
local GenericSelectionCell = require(Packages.UIBlox.Core.Cell.GenericSelectionCell)
|
||||
|
||||
local DEFAULT_IMAGE = Images["component_assets/circle_24_stroke_1"]
|
||||
local SELECTED_IMAGE = Images["component_assets/circle_16"]
|
||||
local DEFAULT_IMAGE_SIZE = 24
|
||||
local SELECTED_IMAGE_SIZE = 16
|
||||
local CELL_SIZE = 56
|
||||
|
||||
local SmallRadioButtonCell = Roact.PureComponent:extend("SmallRadioButtonCell")
|
||||
|
||||
SmallRadioButtonCell.validateProps = t.strictInterface({
|
||||
-- Unique key to identify this selection.
|
||||
key = t.string,
|
||||
|
||||
-- Text to display
|
||||
text = t.optional(t.string),
|
||||
|
||||
-- Callback for when this selection is activated.
|
||||
onActivated = t.optional(t.callback),
|
||||
|
||||
-- Whether this selection is selected or not.
|
||||
isSelected = t.optional(t.boolean),
|
||||
|
||||
-- If this cell is disabled
|
||||
isDisabled = t.optional(t.boolean),
|
||||
|
||||
-- The LayoutOrder.
|
||||
layoutOrder = t.optional(t.number),
|
||||
|
||||
-- optional parameters for RoactGamepad
|
||||
[Roact.Ref] = t.optional(t.table),
|
||||
NextSelectionLeft = t.optional(t.table),
|
||||
NextSelectionRight = t.optional(t.table),
|
||||
NextSelectionUp = t.optional(t.table),
|
||||
NextSelectionDown = t.optional(t.table),
|
||||
})
|
||||
|
||||
SmallRadioButtonCell.defaultProps = {
|
||||
text = "",
|
||||
isSelected = false,
|
||||
}
|
||||
|
||||
function SmallRadioButtonCell:init()
|
||||
self.onSetValue = function()
|
||||
self.props.onActivated(self.props.key)
|
||||
end
|
||||
end
|
||||
|
||||
function SmallRadioButtonCell:render()
|
||||
assert(self.validateProps(self.props))
|
||||
|
||||
return Roact.createElement("Frame", {
|
||||
Size = UDim2.new(1, 0, 0, CELL_SIZE),
|
||||
BorderSizePixel = 0,
|
||||
BackgroundTransparency = 1,
|
||||
LayoutOrder = self.props.layoutOrder,
|
||||
}, {
|
||||
GenericSelectionCell = Roact.createElement(GenericSelectionCell, {
|
||||
isSelected = self.props.isSelected,
|
||||
isDisabled = self.props.isDisabled,
|
||||
defaultImage = DEFAULT_IMAGE,
|
||||
selectedImage = SELECTED_IMAGE,
|
||||
defaultImageSize = DEFAULT_IMAGE_SIZE,
|
||||
selectedImageSize = SELECTED_IMAGE_SIZE,
|
||||
text = self.props.text,
|
||||
onActivated = self.onSetValue,
|
||||
|
||||
[Roact.Ref] = self.props[Roact.Ref],
|
||||
NextSelectionUp = self.props.NextSelectionUp,
|
||||
NextSelectionDown = self.props.NextSelectionDown,
|
||||
NextSelectionLeft = self.props.NextSelectionLeft,
|
||||
NextSelectionRight = self.props.NextSelectionRight,
|
||||
}),
|
||||
})
|
||||
end
|
||||
|
||||
return SmallRadioButtonCell
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
return function()
|
||||
local SelectionGroup = script.Parent
|
||||
local Small = SelectionGroup.Parent
|
||||
local Cell = Small.Parent
|
||||
local App = Cell.Parent
|
||||
local UIBlox = App.Parent
|
||||
local Packages = UIBlox.Parent
|
||||
|
||||
local Roact = require(Packages.Roact)
|
||||
|
||||
local mockStyleComponent = require(UIBlox.Utility.mockStyleComponent)
|
||||
|
||||
local SmallRadioButtonCell = require(script.Parent.SmallRadioButtonCell)
|
||||
|
||||
it("should create and destroy SmallRadioButtonCell without errors", function()
|
||||
local element = mockStyleComponent({
|
||||
smallRadioButtonCell = Roact.createElement(SmallRadioButtonCell, {
|
||||
key = "1",
|
||||
})
|
||||
})
|
||||
|
||||
local instance = Roact.mount(element)
|
||||
Roact.unmount(instance)
|
||||
end)
|
||||
end
|
||||
+103
@@ -0,0 +1,103 @@
|
||||
local SelectionGroup = script.Parent
|
||||
local Small = SelectionGroup.Parent
|
||||
local Cell = Small.Parent
|
||||
local App = Cell.Parent
|
||||
local UIBlox = App.Parent
|
||||
local Packages = UIBlox.Parent
|
||||
|
||||
local Roact = require(Packages.Roact)
|
||||
local RoactGamepad = require(Packages.RoactGamepad)
|
||||
local t = require(Packages.t)
|
||||
|
||||
local UIBloxConfig = require(UIBlox.UIBloxConfig)
|
||||
|
||||
local SmallRadioButtonCell = require(UIBlox.App.Cell.Small.SelectionGroup.SmallRadioButtonCell)
|
||||
|
||||
local SmallRadioButtonGroup = Roact.PureComponent:extend("SmallRadioButtonGroup")
|
||||
|
||||
local buttonInterface = t.strictInterface({
|
||||
text = t.string,
|
||||
key = t.string,
|
||||
isDisabled = t.optional(t.boolean),
|
||||
})
|
||||
|
||||
SmallRadioButtonGroup.validateProps = t.strictInterface({
|
||||
-- List of text, key pairs that will be used for each radio button.
|
||||
items = t.optional(t.array(t.tuple(buttonInterface))),
|
||||
|
||||
-- Which key is currently selected.
|
||||
selectedValue = t.optional(t.string),
|
||||
|
||||
-- Callback for when a cell is activated.
|
||||
onActivated = t.callback,
|
||||
|
||||
-- Layout order for this component.
|
||||
layoutOrder = t.optional(t.number),
|
||||
|
||||
-- optional parameters for RoactGamepad
|
||||
NextSelectionLeft = t.optional(t.table),
|
||||
NextSelectionRight = t.optional(t.table),
|
||||
NextSelectionUp = t.optional(t.table),
|
||||
NextSelectionDown = t.optional(t.table),
|
||||
[Roact.Ref] = t.optional(t.table),
|
||||
})
|
||||
|
||||
SmallRadioButtonGroup.defaultProps = {
|
||||
selectedValue = nil,
|
||||
}
|
||||
|
||||
function SmallRadioButtonGroup:init()
|
||||
self.gamepadRefs = RoactGamepad.createRefCache()
|
||||
end
|
||||
|
||||
function SmallRadioButtonGroup:render()
|
||||
assert(self.validateProps(self.props))
|
||||
|
||||
local smallRadioButtonCellGroup = {}
|
||||
smallRadioButtonCellGroup.layout = Roact.createElement("UIListLayout", {
|
||||
SortOrder = Enum.SortOrder.LayoutOrder,
|
||||
Padding = UDim.new(0, 1),
|
||||
})
|
||||
for index, button in ipairs(self.props.items) do
|
||||
if UIBloxConfig.enableExperimentalGamepadSupport then
|
||||
smallRadioButtonCellGroup["smallRadioButtonCell"..button.key] =
|
||||
Roact.createElement(RoactGamepad.Focusable[SmallRadioButtonCell], {
|
||||
key = button.key,
|
||||
text = button.text,
|
||||
onActivated = self.props.onActivated,
|
||||
isSelected = self.props.selectedValue == button.key,
|
||||
isDisabled = button.isDisabled,
|
||||
layoutOrder = index,
|
||||
|
||||
[Roact.Ref] = self.gamepadRefs[index],
|
||||
NextSelectionUp = index > 1 and self.gamepadRefs[index - 1] or nil,
|
||||
NextSelectionDown = index < #self.props.items and self.gamepadRefs[index + 1] or nil,
|
||||
})
|
||||
else
|
||||
smallRadioButtonCellGroup["smallRadioButtonCell"..button.key] = Roact.createElement(SmallRadioButtonCell, {
|
||||
key = button.key,
|
||||
text = button.text,
|
||||
onActivated = self.props.onActivated,
|
||||
isSelected = self.props.selectedValue == button.key,
|
||||
isDisabled = button.isDisabled,
|
||||
layoutOrder = index,
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
local gamepadEnabled = (UIBloxConfig.enableExperimentalGamepadSupport and self.props.items and #self.props.items > 0)
|
||||
|
||||
return Roact.createElement(gamepadEnabled and RoactGamepad.Focusable.Frame or "Frame", {
|
||||
defaultChild = gamepadEnabled and self.gamepadRefs[1] or nil,
|
||||
Size = UDim2.new(1, 0, 1, 0),
|
||||
BackgroundTransparency = 1,
|
||||
LayoutOrder = self.props.layoutOrder,
|
||||
NextSelectionLeft = self.props.NextSelectionLeft,
|
||||
NextSelectionRight = self.props.NextSelectionRight,
|
||||
NextSelectionDown = self.props.NextSelectionDown,
|
||||
NextSelectionUp = self.props.NextSelectionUp,
|
||||
[Roact.Ref] = self.props[Roact.Ref],
|
||||
}, smallRadioButtonCellGroup)
|
||||
end
|
||||
|
||||
return SmallRadioButtonGroup
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
return function()
|
||||
local SelectionGroup = script.Parent
|
||||
local Small = SelectionGroup.Parent
|
||||
local Cell = Small.Parent
|
||||
local App = Cell.Parent
|
||||
local UIBlox = App.Parent
|
||||
local Packages = UIBlox.Parent
|
||||
|
||||
local Roact = require(Packages.Roact)
|
||||
|
||||
local mockStyleComponent = require(UIBlox.Utility.mockStyleComponent)
|
||||
|
||||
local SmallRadioButtonGroup = require(script.Parent.SmallRadioButtonGroup)
|
||||
|
||||
local ITEMS = {
|
||||
{ text = "Selection 1", key = "1" },
|
||||
{ text = "Selection 3", key = "3" },
|
||||
{ text = "Selection 2", key = "2" },
|
||||
{ text = "Disabled Cell", key = "4", isDisabled = true }
|
||||
}
|
||||
|
||||
it("should create and destroy SmallRadioButtonGroup without errors", function()
|
||||
local element = mockStyleComponent({
|
||||
smallRadioButtonGroup = Roact.createElement(SmallRadioButtonGroup, {
|
||||
onActivated = function() end,
|
||||
items = ITEMS,
|
||||
}),
|
||||
})
|
||||
|
||||
local instance = Roact.mount(element)
|
||||
Roact.unmount(instance)
|
||||
end)
|
||||
|
||||
it("should create and destroy SmallRadioButtonGroup without errors with all optional props used", function()
|
||||
local element = mockStyleComponent({
|
||||
smallRadioButtonGroup = Roact.createElement(SmallRadioButtonGroup, {
|
||||
onActivated = function() end,
|
||||
items = ITEMS,
|
||||
selectedValue = "1",
|
||||
layoutOrder = 1,
|
||||
}),
|
||||
})
|
||||
|
||||
local instance = Roact.mount(element)
|
||||
Roact.unmount(instance)
|
||||
end)
|
||||
end
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
return {
|
||||
Small = 16,
|
||||
Regular = 36,
|
||||
Large = 48,
|
||||
XLarge = 96,
|
||||
XXLarge = 192,
|
||||
}
|
||||
+106
@@ -0,0 +1,106 @@
|
||||
local Carousel = script.Parent
|
||||
local Container = Carousel.Parent
|
||||
local App = Container.Parent
|
||||
local UIBlox = App.Parent
|
||||
local Packages = UIBlox.Parent
|
||||
|
||||
local Roact = require(Packages.Roact)
|
||||
local t = require(Packages.t)
|
||||
local withStyle = require(UIBlox.Style.withStyle)
|
||||
|
||||
local GetTextSize = require(UIBlox.Core.Text.GetTextSize)
|
||||
|
||||
local IconSize = require(App.ImageSet.Enum.IconSize)
|
||||
local getIconSize = require(App.ImageSet.getIconSize)
|
||||
local Images = require(App.ImageSet.Images)
|
||||
|
||||
local Core = UIBlox.Core
|
||||
local Interactable = require(Core.Control.Interactable)
|
||||
local GenericTextLabel = require(Core.Text.GenericTextLabel.GenericTextLabel)
|
||||
local ImageSetComponent = require(Core.ImageSet.ImageSetComponent)
|
||||
|
||||
local MAX_BOUND = 10000
|
||||
local SEE_ALL_ARROW = Images["icons/navigation/pushRight_small"]
|
||||
local TEXT_ICON_PADDING = 4
|
||||
|
||||
local CarouselHeader = Roact.PureComponent:extend("CarouselHeader")
|
||||
|
||||
CarouselHeader.validateProps = t.strictInterface({
|
||||
-- The header text for the carousel
|
||||
headerText = t.optional(t.string),
|
||||
|
||||
-- The callback for the see all arrow. if nil, the arrow won't be shown
|
||||
onSeeAll = t.optional(t.callback),
|
||||
|
||||
-- The carousel left margin
|
||||
carouselMargin = t.optional(t.number),
|
||||
|
||||
-- The layout order
|
||||
layoutOrder = t.optional(t.number),
|
||||
})
|
||||
|
||||
CarouselHeader.defaultProps = {
|
||||
headerText = "",
|
||||
carouselMargin = 0,
|
||||
}
|
||||
|
||||
function CarouselHeader:render()
|
||||
local headerText = self.props.headerText
|
||||
local onSeeAll = self.props.onSeeAll
|
||||
|
||||
local layoutOrder = self.props.layoutOrder
|
||||
local carouselMargin = self.props.carouselMargin
|
||||
|
||||
return withStyle(function(style)
|
||||
local fontStyle = style.Font.Header1
|
||||
local baseSize = style.Font.BaseSize
|
||||
local fontSize = fontStyle.RelativeSize * baseSize
|
||||
local textFont = fontStyle.Font
|
||||
|
||||
local textboxBounds = GetTextSize(headerText, fontSize, textFont, Vector2.new(MAX_BOUND, MAX_BOUND))
|
||||
local textboxSize = UDim2.fromOffset(textboxBounds.X + TEXT_ICON_PADDING + getIconSize(IconSize.Small),
|
||||
textboxBounds.Y)
|
||||
|
||||
return Roact.createElement("Frame", {
|
||||
Size = UDim2.new(1, 0, 0, textboxBounds.Y),
|
||||
BackgroundTransparency = 1,
|
||||
LayoutOrder = layoutOrder,
|
||||
}, {
|
||||
CarouselHeaderButton = Roact.createElement(Interactable, {
|
||||
Position = UDim2.fromOffset(carouselMargin, 0),
|
||||
Size = textboxSize,
|
||||
AutoButtonColor = false,
|
||||
BackgroundTransparency = 1,
|
||||
[Roact.Event.Activated] = onSeeAll,
|
||||
--Note State change is not being used right now.
|
||||
onStateChanged = function()end,
|
||||
}, {
|
||||
Layout = Roact.createElement("UIListLayout", {
|
||||
FillDirection = Enum.FillDirection.Horizontal,
|
||||
HorizontalAlignment = Enum.HorizontalAlignment.Left,
|
||||
VerticalAlignment = Enum.VerticalAlignment.Center,
|
||||
SortOrder = Enum.SortOrder.LayoutOrder,
|
||||
Padding = UDim.new(0, TEXT_ICON_PADDING),
|
||||
}),
|
||||
HeaderText = Roact.createElement(GenericTextLabel, {
|
||||
Text = headerText,
|
||||
TextXAlignment = Enum.TextXAlignment.Left,
|
||||
TextYAlignment = Enum.TextYAlignment.Center,
|
||||
LayoutOrder = 1,
|
||||
fontStyle = fontStyle,
|
||||
colorStyle = style.Theme.TextEmphasis,
|
||||
}),
|
||||
SeeAllArrow = onSeeAll and Roact.createElement(ImageSetComponent.Label, {
|
||||
Size = UDim2.fromOffset(getIconSize(IconSize.Small), getIconSize(IconSize.Small)),
|
||||
BackgroundTransparency = 1,
|
||||
Image = SEE_ALL_ARROW,
|
||||
ImageColor3 = style.Theme.TextEmphasis.Color,
|
||||
ImageTransparency = style.Theme.TextEmphasis.Transparency,
|
||||
LayoutOrder = 2,
|
||||
}) or nil,
|
||||
})
|
||||
})
|
||||
end)
|
||||
end
|
||||
|
||||
return CarouselHeader
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
return function()
|
||||
local Carousel = script.Parent
|
||||
local Container = Carousel.Parent
|
||||
local App = Container.Parent
|
||||
local UIBlox = App.Parent
|
||||
local Packages = UIBlox.Parent
|
||||
|
||||
local Roact = require(Packages.Roact)
|
||||
|
||||
local mockStyleComponent = require(UIBlox.Utility.mockStyleComponent)
|
||||
|
||||
local CarouselHeader = require(script.Parent.CarouselHeader)
|
||||
|
||||
describe("should create and destroy CarouselHeader with default props without errors", function()
|
||||
it("should mount and unmount without issue", function()
|
||||
local element = mockStyleComponent({
|
||||
Item = Roact.createElement(CarouselHeader)
|
||||
})
|
||||
|
||||
local instance = Roact.mount(element)
|
||||
Roact.unmount(instance)
|
||||
end)
|
||||
end)
|
||||
|
||||
describe("should create and destroy CarouselHeader without errors", function()
|
||||
it("should mount and unmount without issue", function()
|
||||
local element = mockStyleComponent({
|
||||
Item = Roact.createElement(CarouselHeader, {
|
||||
headerText = "test header",
|
||||
onSeeAll = function() end,
|
||||
carouselMargin = 12,
|
||||
layoutOrder = 1,
|
||||
})
|
||||
})
|
||||
|
||||
local instance = Roact.mount(element)
|
||||
Roact.unmount(instance)
|
||||
end)
|
||||
end)
|
||||
end
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user