@rbxts-ui/components 2.0.0 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/Accordion.d.ts +16 -0
- package/dist/Accordion.luau +105 -0
- package/dist/Button.d.ts +15 -0
- package/dist/Button.luau +66 -0
- package/dist/Checkbox.d.ts +13 -0
- package/dist/Checkbox.luau +113 -0
- package/dist/CheckboxRow.d.ts +14 -0
- package/dist/CheckboxRow.luau +52 -0
- package/dist/ClickOutsideOverlay.d.ts +11 -0
- package/dist/ClickOutsideOverlay.luau +35 -0
- package/dist/Dropdown.d.ts +18 -0
- package/dist/Dropdown.luau +160 -0
- package/dist/DropdownButton.d.ts +22 -0
- package/dist/DropdownButton.luau +111 -0
- package/dist/DropdownOptionButton.d.ts +13 -0
- package/dist/DropdownOptionButton.luau +70 -0
- package/dist/FormRow.d.ts +11 -0
- package/dist/FormRow.luau +39 -0
- package/dist/IconRoundButton.d.ts +23 -0
- package/dist/IconRoundButton.luau +149 -0
- package/dist/IconTileButton.d.ts +14 -0
- package/dist/IconTileButton.luau +89 -0
- package/dist/Legend.d.ts +11 -0
- package/dist/Legend.luau +54 -0
- package/dist/Outline.d.ts +16 -0
- package/dist/Outline.luau +102 -0
- package/dist/PillText.d.ts +8 -0
- package/dist/PillText.luau +69 -0
- package/dist/PrimaryButton.d.ts +25 -0
- package/dist/PrimaryButton.luau +89 -0
- package/dist/Radio.d.ts +13 -0
- package/dist/Radio.luau +110 -0
- package/dist/RadioRow.d.ts +10 -0
- package/dist/RadioRow.luau +50 -0
- package/dist/ReactiveButton.d.ts +34 -0
- package/dist/ReactiveButton.luau +168 -0
- package/dist/Section.d.ts +12 -0
- package/dist/Section.luau +54 -0
- package/dist/SegmentedToggle.d.ts +19 -0
- package/dist/SegmentedToggle.luau +120 -0
- package/dist/TextButton.d.ts +32 -0
- package/dist/TextButton.luau +125 -0
- package/dist/TimeAgo.d.ts +8 -0
- package/dist/TimeAgo.luau +48 -0
- package/dist/index.d.ts +26 -0
- package/dist/init.luau +37 -0
- package/dist/theme.d.ts +41 -0
- package/dist/theme.luau +58 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/use-button-animation.d.ts +38 -0
- package/dist/use-button-animation.luau +83 -0
- package/dist/use-button-state.d.ts +13 -0
- package/dist/use-button-state.luau +81 -0
- package/dist/use-input-device.d.ts +7 -0
- package/dist/use-input-device.luau +38 -0
- package/package.json +13 -3
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import React from "@rbxts/react";
|
|
2
|
+
import { type Theme } from "./theme";
|
|
3
|
+
interface AccordionProps {
|
|
4
|
+
title: string;
|
|
5
|
+
children: React.ReactNode;
|
|
6
|
+
isExpanded: boolean;
|
|
7
|
+
onExpandedChange: (expanded: boolean) => void;
|
|
8
|
+
backgroundColor?: Color3;
|
|
9
|
+
backgroundTransparency?: number;
|
|
10
|
+
cornerRadius?: number;
|
|
11
|
+
sortOrder?: Enum.SortOrder;
|
|
12
|
+
theme?: Theme;
|
|
13
|
+
}
|
|
14
|
+
export declare function Accordion({ title, children, backgroundColor, backgroundTransparency, cornerRadius, sortOrder, isExpanded, onExpandedChange, theme, }: AccordionProps): JSX.Element;
|
|
15
|
+
export type { AccordionProps };
|
|
16
|
+
//# sourceMappingURL=Accordion.d.ts.map
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
-- Compiled with roblox-ts v3.0.0
|
|
2
|
+
local TS = _G[script]
|
|
3
|
+
local VStack = TS.import(script, TS.getModule(script, "@rbxts-ui", "layout").dist).VStack
|
|
4
|
+
local Text = TS.import(script, TS.getModule(script, "@rbxts-ui", "primitives").dist).Text
|
|
5
|
+
local useRem = TS.import(script, TS.getModule(script, "@rbxts-ui", "rem").dist).useRem
|
|
6
|
+
local useMotion = TS.import(script, TS.getModule(script, "@rbxts", "pretty-react-hooks").out).useMotion
|
|
7
|
+
local _react = TS.import(script, TS.getModule(script, "@rbxts", "react"))
|
|
8
|
+
local React = _react
|
|
9
|
+
local useEffect = _react.useEffect
|
|
10
|
+
local useState = _react.useState
|
|
11
|
+
local ReactiveButton = TS.import(script, script.Parent, "ReactiveButton").ReactiveButton
|
|
12
|
+
local defaultTheme = TS.import(script, script.Parent, "theme").defaultTheme
|
|
13
|
+
local DEFAULT_EXPANDED = true
|
|
14
|
+
local function Accordion(_param)
|
|
15
|
+
local title = _param.title
|
|
16
|
+
local children = _param.children
|
|
17
|
+
local backgroundColor = _param.backgroundColor
|
|
18
|
+
local backgroundTransparency = _param.backgroundTransparency
|
|
19
|
+
if backgroundTransparency == nil then
|
|
20
|
+
backgroundTransparency = 0.8
|
|
21
|
+
end
|
|
22
|
+
local cornerRadius = _param.cornerRadius
|
|
23
|
+
if cornerRadius == nil then
|
|
24
|
+
cornerRadius = 2
|
|
25
|
+
end
|
|
26
|
+
local sortOrder = _param.sortOrder
|
|
27
|
+
if sortOrder == nil then
|
|
28
|
+
sortOrder = Enum.SortOrder.Name
|
|
29
|
+
end
|
|
30
|
+
local isExpanded = _param.isExpanded
|
|
31
|
+
local onExpandedChange = _param.onExpandedChange
|
|
32
|
+
local theme = _param.theme
|
|
33
|
+
if theme == nil then
|
|
34
|
+
theme = defaultTheme
|
|
35
|
+
end
|
|
36
|
+
local rem = useRem()
|
|
37
|
+
local contentHeight, setContentHeight = useState(0)
|
|
38
|
+
-- Header visual height must match the header button height below (rem(5))
|
|
39
|
+
local headerHeight = rem(5)
|
|
40
|
+
local size, sizeMotion = useMotion(UDim2.new(1, 0, 0, headerHeight))
|
|
41
|
+
local contentSize, contentSizeMotion = useMotion(UDim2.new(1, 0, 0, if isExpanded then contentHeight else 0))
|
|
42
|
+
local textSize = rem(3.5)
|
|
43
|
+
local defaultBgColor = backgroundColor or theme.palette.blueishColor
|
|
44
|
+
useEffect(function()
|
|
45
|
+
local target = if isExpanded then contentHeight else 0
|
|
46
|
+
contentSizeMotion:spring(UDim2.new(1, 0, 0, target), theme.springs.gentle)
|
|
47
|
+
-- Keep outer size equal to header + animated content height for clipping
|
|
48
|
+
sizeMotion:spring(UDim2.new(1, 0, 0, headerHeight + target), theme.springs.gentle)
|
|
49
|
+
end, { isExpanded, contentHeight, headerHeight })
|
|
50
|
+
local handleToggle = function()
|
|
51
|
+
local nextExpanded = not isExpanded
|
|
52
|
+
onExpandedChange(nextExpanded)
|
|
53
|
+
end
|
|
54
|
+
return React.createElement(VStack, {
|
|
55
|
+
size = size,
|
|
56
|
+
backgroundTransparency = backgroundTransparency,
|
|
57
|
+
backgroundColor = defaultBgColor,
|
|
58
|
+
verticalAlignment = Enum.VerticalAlignment.Center,
|
|
59
|
+
clipsDescendants = true,
|
|
60
|
+
}, React.createElement("uicorner", {
|
|
61
|
+
CornerRadius = UDim.new(0, rem(cornerRadius)),
|
|
62
|
+
}), React.createElement(ReactiveButton, {
|
|
63
|
+
onClick = handleToggle,
|
|
64
|
+
backgroundTransparency = 1,
|
|
65
|
+
size = UDim2.new(1, 0, 0, rem(5)),
|
|
66
|
+
theme = theme,
|
|
67
|
+
}, React.createElement(Text, {
|
|
68
|
+
text = title,
|
|
69
|
+
textSize = textSize,
|
|
70
|
+
font = theme.fonts.roboto.light,
|
|
71
|
+
textScaled = true,
|
|
72
|
+
textColor = theme.palette.crust,
|
|
73
|
+
size = UDim2.new(1, 0, 1, 0),
|
|
74
|
+
textYAlignment = "Center",
|
|
75
|
+
}, React.createElement("uiflexitem", {
|
|
76
|
+
FlexMode = Enum.UIFlexMode.Fill,
|
|
77
|
+
})), React.createElement(Text, {
|
|
78
|
+
text = if isExpanded then "×" else "+",
|
|
79
|
+
textSize = rem(4),
|
|
80
|
+
textScaled = true,
|
|
81
|
+
textColor = theme.palette.crust,
|
|
82
|
+
size = UDim2.new(0, rem(5), 1, 0),
|
|
83
|
+
textYAlignment = "Center",
|
|
84
|
+
position = UDim2.new(1, 0, 0, 0),
|
|
85
|
+
anchorPoint = Vector2.new(1, 0),
|
|
86
|
+
})), React.createElement("frame", {
|
|
87
|
+
Size = contentSize,
|
|
88
|
+
BackgroundTransparency = 1,
|
|
89
|
+
ClipsDescendants = true,
|
|
90
|
+
}, React.createElement(VStack, {
|
|
91
|
+
padding = rem(2),
|
|
92
|
+
spacing = rem(2),
|
|
93
|
+
size = UDim2.new(1, 0, 0, 0),
|
|
94
|
+
automaticSize = Enum.AutomaticSize.Y,
|
|
95
|
+
change = {
|
|
96
|
+
AbsoluteSize = function(rbx)
|
|
97
|
+
setContentHeight(rbx.AbsoluteSize.Y)
|
|
98
|
+
end,
|
|
99
|
+
},
|
|
100
|
+
sortOrder = sortOrder,
|
|
101
|
+
}, children)))
|
|
102
|
+
end
|
|
103
|
+
return {
|
|
104
|
+
Accordion = Accordion,
|
|
105
|
+
}
|
package/dist/Button.d.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import React from "@rbxts/react";
|
|
2
|
+
import { FrameProps } from "@rbxts-ui/primitives";
|
|
3
|
+
export interface ButtonProps extends FrameProps<TextButton> {
|
|
4
|
+
active?: boolean | React.Binding<boolean>;
|
|
5
|
+
onClick?: () => void;
|
|
6
|
+
onMouseDown?: () => void;
|
|
7
|
+
onMouseUp?: () => void;
|
|
8
|
+
onMouseEnter?: () => void;
|
|
9
|
+
onMouseLeave?: () => void;
|
|
10
|
+
onMouseClick?: () => void;
|
|
11
|
+
automaticSize?: Enum.AutomaticSize;
|
|
12
|
+
selectable?: boolean | React.Binding<boolean>;
|
|
13
|
+
}
|
|
14
|
+
export declare const Button: React.ForwardRefExoticComponent<Omit<ButtonProps, "ref"> & React.RefAttributes<TextButton>>;
|
|
15
|
+
//# sourceMappingURL=Button.d.ts.map
|
package/dist/Button.luau
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
-- Compiled with roblox-ts v3.0.0
|
|
2
|
+
local TS = _G[script]
|
|
3
|
+
local _react = TS.import(script, TS.getModule(script, "@rbxts", "react"))
|
|
4
|
+
local React = _react
|
|
5
|
+
local forwardRef = _react.forwardRef
|
|
6
|
+
local Button = forwardRef(function(props, ref)
|
|
7
|
+
local _binding = props
|
|
8
|
+
local onClick = _binding.onClick
|
|
9
|
+
local onMouseDown = _binding.onMouseDown
|
|
10
|
+
local onMouseEnter = _binding.onMouseEnter
|
|
11
|
+
local onMouseLeave = _binding.onMouseLeave
|
|
12
|
+
local onMouseUp = _binding.onMouseUp
|
|
13
|
+
local onMouseClick = _binding.onMouseClick
|
|
14
|
+
local _object = {
|
|
15
|
+
Activated = onClick and (function()
|
|
16
|
+
return onClick()
|
|
17
|
+
end),
|
|
18
|
+
MouseButton1Down = onMouseDown and (function()
|
|
19
|
+
return onMouseDown()
|
|
20
|
+
end),
|
|
21
|
+
MouseButton1Click = onMouseClick and (function()
|
|
22
|
+
return onMouseClick()
|
|
23
|
+
end),
|
|
24
|
+
MouseButton1Up = onMouseUp and (function()
|
|
25
|
+
return onMouseUp()
|
|
26
|
+
end),
|
|
27
|
+
MouseEnter = onMouseEnter and (function()
|
|
28
|
+
return onMouseEnter()
|
|
29
|
+
end),
|
|
30
|
+
MouseLeave = onMouseLeave and (function()
|
|
31
|
+
return onMouseLeave()
|
|
32
|
+
end),
|
|
33
|
+
}
|
|
34
|
+
local _spread = props.event
|
|
35
|
+
if _spread then
|
|
36
|
+
for _k, _v in _spread do
|
|
37
|
+
_object[_k] = _v
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
local event = _object
|
|
41
|
+
return React.createElement("textbutton", {
|
|
42
|
+
ref = ref,
|
|
43
|
+
Active = props.active,
|
|
44
|
+
Text = "",
|
|
45
|
+
AutoButtonColor = false,
|
|
46
|
+
Size = props.size,
|
|
47
|
+
Position = props.position,
|
|
48
|
+
AnchorPoint = props.anchorPoint,
|
|
49
|
+
BackgroundColor3 = props.backgroundColor,
|
|
50
|
+
BackgroundTransparency = props.backgroundTransparency,
|
|
51
|
+
ClipsDescendants = props.clipsDescendants,
|
|
52
|
+
Visible = props.visible,
|
|
53
|
+
ZIndex = props.zIndex,
|
|
54
|
+
LayoutOrder = props.layoutOrder,
|
|
55
|
+
BorderSizePixel = 0,
|
|
56
|
+
Selectable = props.selectable,
|
|
57
|
+
Event = event,
|
|
58
|
+
Change = props.change,
|
|
59
|
+
AutomaticSize = props.automaticSize,
|
|
60
|
+
}, props.children, props.cornerRadius and React.createElement("uicorner", {
|
|
61
|
+
CornerRadius = props.cornerRadius,
|
|
62
|
+
}))
|
|
63
|
+
end)
|
|
64
|
+
return {
|
|
65
|
+
Button = Button,
|
|
66
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { type Theme } from "./theme";
|
|
2
|
+
interface CheckboxProps {
|
|
3
|
+
checked: boolean;
|
|
4
|
+
onChecked: (checked: boolean) => void;
|
|
5
|
+
text?: string;
|
|
6
|
+
variant?: "default" | "large" | "small";
|
|
7
|
+
position?: UDim2;
|
|
8
|
+
disabled?: boolean;
|
|
9
|
+
theme?: Theme;
|
|
10
|
+
}
|
|
11
|
+
export declare function Checkbox({ checked, onChecked, text, variant, position, disabled, theme, }: CheckboxProps): JSX.Element;
|
|
12
|
+
export type { CheckboxProps };
|
|
13
|
+
//# sourceMappingURL=Checkbox.d.ts.map
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
-- Compiled with roblox-ts v3.0.0
|
|
2
|
+
local TS = _G[script]
|
|
3
|
+
local _pretty_react_hooks = TS.import(script, TS.getModule(script, "@rbxts", "pretty-react-hooks").out)
|
|
4
|
+
local lerpBinding = _pretty_react_hooks.lerpBinding
|
|
5
|
+
local useMotion = _pretty_react_hooks.useMotion
|
|
6
|
+
local _react = TS.import(script, TS.getModule(script, "@rbxts", "react"))
|
|
7
|
+
local React = _react
|
|
8
|
+
local useMemo = _react.useMemo
|
|
9
|
+
local useRem = TS.import(script, TS.getModule(script, "@rbxts-ui", "rem").dist).useRem
|
|
10
|
+
local Frame = TS.import(script, TS.getModule(script, "@rbxts-ui", "primitives").dist).Frame
|
|
11
|
+
local Outline = TS.import(script, script.Parent, "Outline").Outline
|
|
12
|
+
local ReactiveButton = TS.import(script, script.Parent, "ReactiveButton").ReactiveButton
|
|
13
|
+
local Text = TS.import(script, TS.getModule(script, "@rbxts-ui", "primitives").dist).Text
|
|
14
|
+
local defaultTheme = TS.import(script, script.Parent, "theme").defaultTheme
|
|
15
|
+
local function Checkbox(_param)
|
|
16
|
+
local checked = _param.checked
|
|
17
|
+
local onChecked = _param.onChecked
|
|
18
|
+
local text = _param.text
|
|
19
|
+
local variant = _param.variant
|
|
20
|
+
if variant == nil then
|
|
21
|
+
variant = "default"
|
|
22
|
+
end
|
|
23
|
+
local position = _param.position
|
|
24
|
+
local disabled = _param.disabled
|
|
25
|
+
if disabled == nil then
|
|
26
|
+
disabled = false
|
|
27
|
+
end
|
|
28
|
+
local theme = _param.theme
|
|
29
|
+
if theme == nil then
|
|
30
|
+
theme = defaultTheme
|
|
31
|
+
end
|
|
32
|
+
local rem = useRem()
|
|
33
|
+
local hover, hoverMotion = useMotion(0)
|
|
34
|
+
local checkboxSize = if variant == "large" then 4 elseif variant == "small" then 1.7 else 3
|
|
35
|
+
local buttonSize = UDim2.new(0, rem(checkboxSize), 0, rem(checkboxSize))
|
|
36
|
+
local textWidth, textWidthMotion = useMotion({
|
|
37
|
+
label = 0,
|
|
38
|
+
value = 0,
|
|
39
|
+
})
|
|
40
|
+
local size = useMemo(function()
|
|
41
|
+
return textWidth:map(function(_param_1)
|
|
42
|
+
local label = _param_1.label
|
|
43
|
+
local value = _param_1.value
|
|
44
|
+
local content = math.max(label, value)
|
|
45
|
+
local width = checkboxSize
|
|
46
|
+
return UDim2.new(0, rem(width) + content, 0, rem(checkboxSize))
|
|
47
|
+
end)
|
|
48
|
+
end, { rem })
|
|
49
|
+
local cornerRadius = UDim.new(0, rem(1))
|
|
50
|
+
local mainColor = if disabled then theme.palette.overlay0 else theme.palette.black
|
|
51
|
+
local textColor = if disabled then theme.palette.overlay0 else theme.palette.black
|
|
52
|
+
return React.createElement(ReactiveButton, {
|
|
53
|
+
backgroundTransparency = 1,
|
|
54
|
+
size = size,
|
|
55
|
+
position = position,
|
|
56
|
+
onClick = function()
|
|
57
|
+
return not disabled and onChecked(not checked)
|
|
58
|
+
end,
|
|
59
|
+
onHover = function(hovered)
|
|
60
|
+
return hoverMotion:spring(if hovered then 1 else 0)
|
|
61
|
+
end,
|
|
62
|
+
theme = theme,
|
|
63
|
+
}, React.createElement("uilistlayout", {
|
|
64
|
+
FillDirection = "Horizontal",
|
|
65
|
+
VerticalAlignment = "Center",
|
|
66
|
+
Padding = UDim.new(0, 8),
|
|
67
|
+
}), React.createElement(Frame, {
|
|
68
|
+
backgroundTransparency = 1,
|
|
69
|
+
size = buttonSize,
|
|
70
|
+
}, React.createElement(Frame, {
|
|
71
|
+
backgroundColor = theme.palette.white,
|
|
72
|
+
cornerRadius = cornerRadius,
|
|
73
|
+
size = UDim2.new(1, 0, 1, 0),
|
|
74
|
+
}, React.createElement("uigradient", {
|
|
75
|
+
Offset = lerpBinding(hover, Vector2.new(), Vector2.new(0, 1)),
|
|
76
|
+
Rotation = 90,
|
|
77
|
+
Transparency = NumberSequence.new(0, 0.1),
|
|
78
|
+
})), React.createElement(Outline, {
|
|
79
|
+
outerColor = mainColor,
|
|
80
|
+
innerColor = mainColor,
|
|
81
|
+
cornerRadius = cornerRadius,
|
|
82
|
+
innerTransparency = 0,
|
|
83
|
+
outerTransparency = 1,
|
|
84
|
+
innerThickness = 2,
|
|
85
|
+
theme = theme,
|
|
86
|
+
}), React.createElement(Text, {
|
|
87
|
+
text = if checked then "✔" else "",
|
|
88
|
+
textColor = mainColor,
|
|
89
|
+
textScaled = true,
|
|
90
|
+
size = UDim2.new(1, 0, 1, 0),
|
|
91
|
+
position = UDim2.new(0.5, 0, 0.5, 0),
|
|
92
|
+
anchorPoint = Vector2.new(0.5, 0.5),
|
|
93
|
+
textXAlignment = "Center",
|
|
94
|
+
textYAlignment = "Center",
|
|
95
|
+
padding = 0.9,
|
|
96
|
+
rem = rem,
|
|
97
|
+
})), if text ~= "" and text then (React.createElement(Text, {
|
|
98
|
+
text = text,
|
|
99
|
+
size = UDim2.new(0, rem(2), 0, rem(2)),
|
|
100
|
+
textColor = textColor,
|
|
101
|
+
textXAlignment = "Left",
|
|
102
|
+
change = {
|
|
103
|
+
TextBounds = function(rbx)
|
|
104
|
+
textWidthMotion:spring({
|
|
105
|
+
value = rbx.TextBounds.X,
|
|
106
|
+
})
|
|
107
|
+
end,
|
|
108
|
+
},
|
|
109
|
+
})) else nil)
|
|
110
|
+
end
|
|
111
|
+
return {
|
|
112
|
+
Checkbox = Checkbox,
|
|
113
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import React from "@rbxts/react";
|
|
2
|
+
import { type Theme } from "./theme";
|
|
3
|
+
interface CheckboxRowProps {
|
|
4
|
+
label: string;
|
|
5
|
+
checked: boolean;
|
|
6
|
+
onChecked: () => void;
|
|
7
|
+
disabled?: boolean;
|
|
8
|
+
name?: string;
|
|
9
|
+
children?: React.ReactNode;
|
|
10
|
+
theme?: Theme;
|
|
11
|
+
}
|
|
12
|
+
export declare function CheckboxRow({ label, checked, onChecked, disabled, name, children, theme, }: CheckboxRowProps): JSX.Element;
|
|
13
|
+
export type { CheckboxRowProps };
|
|
14
|
+
//# sourceMappingURL=CheckboxRow.d.ts.map
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
-- Compiled with roblox-ts v3.0.0
|
|
2
|
+
local TS = _G[script]
|
|
3
|
+
local React = TS.import(script, TS.getModule(script, "@rbxts", "react"))
|
|
4
|
+
local useRem = TS.import(script, TS.getModule(script, "@rbxts-ui", "rem").dist).useRem
|
|
5
|
+
local Checkbox = TS.import(script, script.Parent, "Checkbox").Checkbox
|
|
6
|
+
local Button = TS.import(script, script.Parent, "Button").Button
|
|
7
|
+
local HStack = TS.import(script, TS.getModule(script, "@rbxts-ui", "layout").dist).HStack
|
|
8
|
+
local Text = TS.import(script, TS.getModule(script, "@rbxts-ui", "primitives").dist).Text
|
|
9
|
+
local defaultTheme = TS.import(script, script.Parent, "theme").defaultTheme
|
|
10
|
+
local function CheckboxRow(_param)
|
|
11
|
+
local label = _param.label
|
|
12
|
+
local checked = _param.checked
|
|
13
|
+
local onChecked = _param.onChecked
|
|
14
|
+
local disabled = _param.disabled
|
|
15
|
+
if disabled == nil then
|
|
16
|
+
disabled = false
|
|
17
|
+
end
|
|
18
|
+
local name = _param.name
|
|
19
|
+
local children = _param.children
|
|
20
|
+
local theme = _param.theme
|
|
21
|
+
if theme == nil then
|
|
22
|
+
theme = defaultTheme
|
|
23
|
+
end
|
|
24
|
+
local rem = useRem()
|
|
25
|
+
local textSize = rem(3)
|
|
26
|
+
return React.createElement(HStack, {
|
|
27
|
+
size = UDim2.new(1, 0, 0, 0),
|
|
28
|
+
automaticSize = Enum.AutomaticSize.Y,
|
|
29
|
+
spacing = rem(2),
|
|
30
|
+
name = name,
|
|
31
|
+
}, React.createElement(Checkbox, {
|
|
32
|
+
checked = checked,
|
|
33
|
+
variant = "large",
|
|
34
|
+
onChecked = onChecked,
|
|
35
|
+
disabled = disabled,
|
|
36
|
+
theme = theme,
|
|
37
|
+
}), React.createElement(Button, {
|
|
38
|
+
backgroundTransparency = 1,
|
|
39
|
+
size = UDim2.new(1, 0, 0, rem(4)),
|
|
40
|
+
onClick = if disabled then function() end else onChecked,
|
|
41
|
+
}, React.createElement(Text, {
|
|
42
|
+
text = label,
|
|
43
|
+
textSize = textSize,
|
|
44
|
+
textScaled = true,
|
|
45
|
+
textColor = if disabled then theme.palette.overlay0 else theme.palette.crust,
|
|
46
|
+
size = UDim2.new(1, 0, 1, 0),
|
|
47
|
+
textXAlignment = "Left",
|
|
48
|
+
})), children)
|
|
49
|
+
end
|
|
50
|
+
return {
|
|
51
|
+
CheckboxRow = CheckboxRow,
|
|
52
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import React from "@rbxts/react";
|
|
2
|
+
interface ClickOutsideOverlayProps {
|
|
3
|
+
readonly onClickOutside: () => void;
|
|
4
|
+
}
|
|
5
|
+
export declare function ClickOutsideOverlay({ onClickOutside }: ClickOutsideOverlayProps): JSX.Element;
|
|
6
|
+
interface ClickOutsideLayerProps extends React.PropsWithChildren {
|
|
7
|
+
readonly onClickOutside: () => void;
|
|
8
|
+
}
|
|
9
|
+
export declare function ClickOutsideLayer({ onClickOutside, children }: ClickOutsideLayerProps): JSX.Element;
|
|
10
|
+
export type { ClickOutsideOverlayProps, ClickOutsideLayerProps };
|
|
11
|
+
//# sourceMappingURL=ClickOutsideOverlay.d.ts.map
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
-- Compiled with roblox-ts v3.0.0
|
|
2
|
+
local TS = _G[script]
|
|
3
|
+
local React = TS.import(script, TS.getModule(script, "@rbxts", "react"))
|
|
4
|
+
local Frame = TS.import(script, TS.getModule(script, "@rbxts-ui", "primitives").dist).Frame
|
|
5
|
+
local function ClickOutsideOverlay(_param)
|
|
6
|
+
local onClickOutside = _param.onClickOutside
|
|
7
|
+
return React.createElement(Frame, {
|
|
8
|
+
size = UDim2.new(1, 0, 1, 0),
|
|
9
|
+
backgroundTransparency = 1,
|
|
10
|
+
active = true,
|
|
11
|
+
event = {
|
|
12
|
+
InputBegan = function(_, input)
|
|
13
|
+
if input.UserInputType ~= Enum.UserInputType.MouseButton1 and input.UserInputType ~= Enum.UserInputType.Touch then
|
|
14
|
+
return nil
|
|
15
|
+
end
|
|
16
|
+
onClickOutside()
|
|
17
|
+
end,
|
|
18
|
+
},
|
|
19
|
+
})
|
|
20
|
+
end
|
|
21
|
+
local function ClickOutsideLayer(_param)
|
|
22
|
+
local onClickOutside = _param.onClickOutside
|
|
23
|
+
local children = _param.children
|
|
24
|
+
return React.createElement(Frame, {
|
|
25
|
+
size = UDim2.new(1, 0, 1, 0),
|
|
26
|
+
backgroundTransparency = 1,
|
|
27
|
+
active = true,
|
|
28
|
+
}, React.createElement(ClickOutsideOverlay, {
|
|
29
|
+
onClickOutside = onClickOutside,
|
|
30
|
+
}), children)
|
|
31
|
+
end
|
|
32
|
+
return {
|
|
33
|
+
ClickOutsideOverlay = ClickOutsideOverlay,
|
|
34
|
+
ClickOutsideLayer = ClickOutsideLayer,
|
|
35
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import React from "@rbxts/react";
|
|
2
|
+
import { type Theme } from "./theme";
|
|
3
|
+
interface DropdownOption<T> {
|
|
4
|
+
label: string;
|
|
5
|
+
value: T;
|
|
6
|
+
}
|
|
7
|
+
interface DropdownProps<T> {
|
|
8
|
+
options: Array<DropdownOption<T>>;
|
|
9
|
+
value?: T;
|
|
10
|
+
onChange: (value: T) => void;
|
|
11
|
+
size?: UDim2;
|
|
12
|
+
renderOption?: (option: DropdownOption<T>) => React.ReactNode;
|
|
13
|
+
portalRef?: React.RefObject<GuiObject>;
|
|
14
|
+
theme?: Theme;
|
|
15
|
+
}
|
|
16
|
+
export declare function Dropdown<T>(props: DropdownProps<T>): JSX.Element;
|
|
17
|
+
export type { DropdownOption, DropdownProps };
|
|
18
|
+
//# sourceMappingURL=Dropdown.d.ts.map
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
-- Compiled with roblox-ts v3.0.0
|
|
2
|
+
local TS = _G[script]
|
|
3
|
+
local VStackScrolling = TS.import(script, TS.getModule(script, "@rbxts-ui", "layout").dist).VStackScrolling
|
|
4
|
+
local Frame = TS.import(script, TS.getModule(script, "@rbxts-ui", "primitives").dist).Frame
|
|
5
|
+
local useRem = TS.import(script, TS.getModule(script, "@rbxts-ui", "rem").dist).useRem
|
|
6
|
+
local _react = TS.import(script, TS.getModule(script, "@rbxts", "react"))
|
|
7
|
+
local React = _react
|
|
8
|
+
local useEffect = _react.useEffect
|
|
9
|
+
local useRef = _react.useRef
|
|
10
|
+
local useState = _react.useState
|
|
11
|
+
local createPortal = TS.import(script, TS.getModule(script, "@rbxts", "react-roblox")).createPortal
|
|
12
|
+
local ClickOutsideLayer = TS.import(script, script.Parent, "ClickOutsideOverlay").ClickOutsideLayer
|
|
13
|
+
local DropdownButton = TS.import(script, script.Parent, "DropdownButton").DropdownButton
|
|
14
|
+
local DropdownOptionButton = TS.import(script, script.Parent, "DropdownOptionButton").DropdownOptionButton
|
|
15
|
+
local defaultTheme = TS.import(script, script.Parent, "theme").defaultTheme
|
|
16
|
+
local function Dropdown(props)
|
|
17
|
+
local _binding = props
|
|
18
|
+
local options = _binding.options
|
|
19
|
+
local value = _binding.value
|
|
20
|
+
local onChange = _binding.onChange
|
|
21
|
+
local size = _binding.size
|
|
22
|
+
local renderOption = _binding.renderOption
|
|
23
|
+
local portalRef = _binding.portalRef
|
|
24
|
+
local theme = _binding.theme
|
|
25
|
+
if theme == nil then
|
|
26
|
+
theme = defaultTheme
|
|
27
|
+
end
|
|
28
|
+
local isOpen, setIsOpen = useState(false)
|
|
29
|
+
local dropdownBounds, setDropdownBounds = useState()
|
|
30
|
+
local dropdownRef = useRef()
|
|
31
|
+
local rem = useRem()
|
|
32
|
+
local frameSize = size or UDim2.new(0.4, 0, 0, rem(5))
|
|
33
|
+
local optionHeight = rem(5)
|
|
34
|
+
-- ▼ ReadonlyArray.find ▼
|
|
35
|
+
local _callback = function(option)
|
|
36
|
+
return option.value == value
|
|
37
|
+
end
|
|
38
|
+
local _result
|
|
39
|
+
for _i, _v in options do
|
|
40
|
+
if _callback(_v, _i - 1, options) == true then
|
|
41
|
+
_result = _v
|
|
42
|
+
break
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
-- ▲ ReadonlyArray.find ▲
|
|
46
|
+
local selectedOption = _result
|
|
47
|
+
local cornerRadius = UDim.new(0, rem(1.7))
|
|
48
|
+
local dropdownHeight = #options * optionHeight
|
|
49
|
+
useEffect(function()
|
|
50
|
+
if not isOpen then
|
|
51
|
+
setDropdownBounds(nil)
|
|
52
|
+
return nil
|
|
53
|
+
end
|
|
54
|
+
local frame = dropdownRef.current
|
|
55
|
+
if not frame then
|
|
56
|
+
return nil
|
|
57
|
+
end
|
|
58
|
+
local updateBounds = function()
|
|
59
|
+
setDropdownBounds({
|
|
60
|
+
position = frame.AbsolutePosition,
|
|
61
|
+
size = frame.AbsoluteSize,
|
|
62
|
+
})
|
|
63
|
+
end
|
|
64
|
+
updateBounds()
|
|
65
|
+
local positionConnection = frame:GetPropertyChangedSignal("AbsolutePosition"):Connect(updateBounds)
|
|
66
|
+
local sizeConnection = frame:GetPropertyChangedSignal("AbsoluteSize"):Connect(updateBounds)
|
|
67
|
+
return function()
|
|
68
|
+
positionConnection:Disconnect()
|
|
69
|
+
sizeConnection:Disconnect()
|
|
70
|
+
end
|
|
71
|
+
end, { isOpen })
|
|
72
|
+
local renderOptions = function()
|
|
73
|
+
local _exp = React.createElement("uicorner", {
|
|
74
|
+
CornerRadius = cornerRadius,
|
|
75
|
+
})
|
|
76
|
+
local _exp_1 = React.createElement("uistroke", {
|
|
77
|
+
Color = theme.palette.crust,
|
|
78
|
+
Transparency = 0.5,
|
|
79
|
+
Thickness = 1,
|
|
80
|
+
})
|
|
81
|
+
-- ▼ ReadonlyArray.map ▼
|
|
82
|
+
local _newValue = table.create(#options)
|
|
83
|
+
local _callback_1 = function(option)
|
|
84
|
+
return React.createElement(DropdownOptionButton, {
|
|
85
|
+
key = tostring(option.value),
|
|
86
|
+
text = option.label,
|
|
87
|
+
size = UDim2.new(1, 0, 0, optionHeight),
|
|
88
|
+
onClick = function()
|
|
89
|
+
onChange(option.value)
|
|
90
|
+
setIsOpen(false)
|
|
91
|
+
end,
|
|
92
|
+
theme = theme,
|
|
93
|
+
}, if renderOption then renderOption(option) else nil)
|
|
94
|
+
end
|
|
95
|
+
for _k, _v in options do
|
|
96
|
+
_newValue[_k] = _callback_1(_v, _k - 1, options)
|
|
97
|
+
end
|
|
98
|
+
-- ▲ ReadonlyArray.map ▲
|
|
99
|
+
return React.createElement(React.Fragment, nil, _exp, _exp_1, _newValue)
|
|
100
|
+
end
|
|
101
|
+
local dropdownOverlay = (function()
|
|
102
|
+
if not isOpen then
|
|
103
|
+
return nil
|
|
104
|
+
end
|
|
105
|
+
-- Use provided portalRef or fallback to Players.LocalPlayer.PlayerGui
|
|
106
|
+
local _container = portalRef
|
|
107
|
+
if _container ~= nil then
|
|
108
|
+
_container = _container.current
|
|
109
|
+
end
|
|
110
|
+
local container = _container
|
|
111
|
+
if not container then
|
|
112
|
+
error("Dropdown requires a portalRef prop or a PortalProvider with an active portalRef")
|
|
113
|
+
end
|
|
114
|
+
if not dropdownBounds then
|
|
115
|
+
return nil
|
|
116
|
+
end
|
|
117
|
+
local containerPosition = container.AbsolutePosition
|
|
118
|
+
local relativePosition = dropdownBounds.position - containerPosition
|
|
119
|
+
local dropdownY = relativePosition.Y + dropdownBounds.size.Y
|
|
120
|
+
return createPortal(React.createElement(ClickOutsideLayer, {
|
|
121
|
+
onClickOutside = function()
|
|
122
|
+
return setIsOpen(false)
|
|
123
|
+
end,
|
|
124
|
+
}, React.createElement(VStackScrolling, {
|
|
125
|
+
Position = UDim2.new(0, relativePosition.X, 0, dropdownY),
|
|
126
|
+
Size = UDim2.new(0, dropdownBounds.size.X, 0, dropdownHeight),
|
|
127
|
+
BackgroundColor3 = theme.palette.white,
|
|
128
|
+
BackgroundTransparency = 0,
|
|
129
|
+
ClipsDescendants = true,
|
|
130
|
+
BorderColor3 = theme.palette.crust,
|
|
131
|
+
ZIndex = 2000,
|
|
132
|
+
paddingBottom = rem(1),
|
|
133
|
+
}, renderOptions())), container)
|
|
134
|
+
end)()
|
|
135
|
+
local _attributes = {}
|
|
136
|
+
local _result_1 = selectedOption
|
|
137
|
+
if _result_1 ~= nil then
|
|
138
|
+
_result_1 = _result_1.label
|
|
139
|
+
end
|
|
140
|
+
local _condition = _result_1
|
|
141
|
+
if not (_condition ~= "" and _condition) then
|
|
142
|
+
_condition = "Select..."
|
|
143
|
+
end
|
|
144
|
+
_attributes.text = _condition
|
|
145
|
+
_attributes.size = UDim2.new(1, 0, 1, 0)
|
|
146
|
+
_attributes.onClick = function()
|
|
147
|
+
return setIsOpen(not isOpen)
|
|
148
|
+
end
|
|
149
|
+
_attributes.theme = theme
|
|
150
|
+
return React.createElement(Frame, {
|
|
151
|
+
backgroundTransparency = 1,
|
|
152
|
+
size = frameSize,
|
|
153
|
+
ref = dropdownRef,
|
|
154
|
+
}, React.createElement(DropdownButton, _attributes), dropdownOverlay, React.createElement("uiflexitem", {
|
|
155
|
+
FlexMode = Enum.UIFlexMode.Fill,
|
|
156
|
+
}))
|
|
157
|
+
end
|
|
158
|
+
return {
|
|
159
|
+
Dropdown = Dropdown,
|
|
160
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import React from "@rbxts/react";
|
|
2
|
+
import { type Theme } from "./theme";
|
|
3
|
+
interface DropdownButtonProps extends React.PropsWithChildren {
|
|
4
|
+
readonly text: string;
|
|
5
|
+
readonly onClick?: () => void;
|
|
6
|
+
readonly onHover?: (hovered: boolean) => void;
|
|
7
|
+
readonly size?: UDim2 | React.Binding<UDim2>;
|
|
8
|
+
readonly position?: UDim2 | React.Binding<UDim2>;
|
|
9
|
+
readonly anchorPoint?: Vector2 | React.Binding<Vector2>;
|
|
10
|
+
readonly overlayGradient?: ColorSequence | React.Binding<ColorSequence>;
|
|
11
|
+
readonly overlayTransparency?: number | React.Binding<number>;
|
|
12
|
+
readonly overlayRotation?: number | React.Binding<number>;
|
|
13
|
+
readonly layoutOrder?: number | React.Binding<number>;
|
|
14
|
+
readonly isDisabled?: boolean;
|
|
15
|
+
readonly hasShadow?: boolean;
|
|
16
|
+
readonly padding?: number;
|
|
17
|
+
readonly radius?: number;
|
|
18
|
+
readonly theme?: Theme;
|
|
19
|
+
}
|
|
20
|
+
export declare function DropdownButton({ text, onClick, onHover, position, anchorPoint, layoutOrder, isDisabled, size, padding, radius, theme, }: DropdownButtonProps): JSX.Element;
|
|
21
|
+
export type { DropdownButtonProps };
|
|
22
|
+
//# sourceMappingURL=DropdownButton.d.ts.map
|