@rbxts/react-clean-ui 1.1.0 → 1.2.2
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/out/Components/Chart/BarChart.d.ts +1 -0
- package/out/Components/Chart/BarChart.luau +149 -112
- package/out/Components/Chart/Pie.d.ts +1 -0
- package/out/Components/Chart/Pie.luau +21 -5
- package/out/Components/Decorator/BoxShadow.d.ts +1 -0
- package/out/Components/Decorator/BoxShadow.luau +12 -5
- package/out/Components/Decorator/Corners.d.ts +1 -0
- package/out/Components/Decorator/Corners.luau +8 -3
- package/out/Components/Decorator/Padding.d.ts +3 -1
- package/out/Components/Decorator/Padding.luau +11 -6
- package/out/Components/Input/Button.d.ts +1 -0
- package/out/Components/Input/Button.luau +44 -33
- package/out/Components/Input/Checkbox.d.ts +1 -0
- package/out/Components/Input/Checkbox.luau +22 -16
- package/out/Components/Input/HoverButton.d.ts +1 -0
- package/out/Components/Input/HoverButton.luau +44 -40
- package/out/Components/Input/Increment.d.ts +1 -0
- package/out/Components/Input/Increment.luau +10 -3
- package/out/Components/Input/Input.d.ts +3 -1
- package/out/Components/Input/Input.luau +85 -66
- package/out/Components/Input/Select.d.ts +9 -0
- package/out/Components/Input/Select.luau +311 -34
- package/out/Components/Input/Slider.luau +44 -29
- package/out/Components/Input/Switch.d.ts +9 -0
- package/out/Components/Input/Switch.luau +147 -0
- package/out/Components/Input/index.d.ts +1 -0
- package/out/Components/Input/init.luau +3 -0
- package/out/Components/Interaction/Modal.d.ts +14 -0
- package/out/Components/Interaction/Modal.luau +276 -0
- package/out/Components/Interaction/Toast.d.ts +2 -1
- package/out/Components/Interaction/Toast.luau +53 -28
- package/out/Components/Interaction/Tooltip.luau +36 -24
- package/out/Components/Interaction/index.d.ts +1 -0
- package/out/Components/Interaction/init.luau +3 -0
- package/out/Components/Layout/Accordion.d.ts +1 -0
- package/out/Components/Layout/Accordion.luau +51 -55
- package/out/Components/Layout/Column.d.ts +1 -0
- package/out/Components/Layout/Column.luau +11 -6
- package/out/Components/Layout/Container.d.ts +1 -0
- package/out/Components/Layout/Container.luau +22 -16
- package/out/Components/Layout/Draggable.luau +25 -3
- package/out/Components/Layout/Fieldset.d.ts +1 -0
- package/out/Components/Layout/Fieldset.luau +14 -42
- package/out/Components/Layout/FlexItem.luau +7 -0
- package/out/Components/Layout/Group.d.ts +1 -0
- package/out/Components/Layout/Group.luau +16 -33
- package/out/Components/Layout/HStack.d.ts +4 -0
- package/out/Components/Layout/HStack.luau +17 -10
- package/out/Components/Layout/Pagination.d.ts +32 -0
- package/out/Components/Layout/Pagination.luau +405 -0
- package/out/Components/Layout/Row.d.ts +1 -0
- package/out/Components/Layout/Row.luau +20 -48
- package/out/Components/Layout/Scroller.d.ts +1 -0
- package/out/Components/Layout/Scroller.luau +26 -34
- package/out/Components/Layout/Table.d.ts +31 -0
- package/out/Components/Layout/Table.luau +342 -0
- package/out/Components/Layout/Tabs.d.ts +18 -9
- package/out/Components/Layout/Tabs.luau +134 -119
- package/out/Components/Layout/VStack.d.ts +3 -0
- package/out/Components/Layout/VStack.luau +17 -10
- package/out/Components/Layout/index.d.ts +2 -0
- package/out/Components/Layout/init.luau +6 -0
- package/out/Components/Navigation/Menu.d.ts +1 -0
- package/out/Components/Navigation/Menu.luau +12 -3
- package/out/Components/Surface/Box.d.ts +1 -0
- package/out/Components/Surface/Box.luau +12 -4
- package/out/Components/Surface/Card.d.ts +1 -0
- package/out/Components/Surface/Card.luau +54 -51
- package/out/Components/Surface/Icon.d.ts +1 -0
- package/out/Components/Surface/Icon.luau +25 -16
- package/out/Components/Typography/Text.d.ts +1 -0
- package/out/Components/Typography/Text.luau +57 -47
- package/out/Contexts/index.d.ts +1 -0
- package/out/Contexts/init.luau +3 -0
- package/out/Contexts/modal.context.d.ts +15 -0
- package/out/Contexts/modal.context.luau +26 -0
- package/out/Contexts/toast.context.d.ts +1 -0
- package/out/Providers/app.provider.luau +2 -1
- package/out/Providers/index.d.ts +1 -0
- package/out/Providers/init.luau +3 -0
- package/out/Providers/modal.provider.d.ts +6 -0
- package/out/Providers/modal.provider.luau +86 -0
- package/out/Providers/overlay.provider.luau +1 -0
- package/out/Theme/theme.template.d.ts +85 -0
- package/out/Theme/themes/dark.theme.luau +103 -0
- package/out/Theme/themes/default.theme.luau +130 -0
- package/out/Theme/themes/sandstone.theme.luau +103 -0
- package/out/Theme/themes/wooden.theme.luau +122 -0
- package/package.json +1 -1
|
@@ -0,0 +1,147 @@
|
|
|
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 useTween = TS.import(script, TS.getModule(script, "@rbxts", "react-ripple").src).useTween
|
|
5
|
+
local CleanThemeContext = TS.import(script, script.Parent.Parent.Parent, "Contexts").CleanThemeContext
|
|
6
|
+
local FieldsetContext = TS.import(script, script.Parent.Parent, "Layout").FieldsetContext
|
|
7
|
+
local _Decorator = TS.import(script, script.Parent.Parent, "Decorator")
|
|
8
|
+
local Corners = _Decorator.Corners
|
|
9
|
+
local BoxShadow = _Decorator.BoxShadow
|
|
10
|
+
local _Helpers = TS.import(script, script.Parent.Parent.Parent, "Helpers")
|
|
11
|
+
local ColorHelper = _Helpers.ColorHelper
|
|
12
|
+
local SizeHelper = _Helpers.SizeHelper
|
|
13
|
+
-- Linearly interpolates between two UDim values by treating Scale and Offset
|
|
14
|
+
-- as independent components, since UDim itself has no Lerp method.
|
|
15
|
+
local function lerpUDim(from, to, alpha)
|
|
16
|
+
return UDim.new(from.Scale + (to.Scale - from.Scale) * alpha, from.Offset + (to.Offset - from.Offset) * alpha)
|
|
17
|
+
end
|
|
18
|
+
local function Switch(props)
|
|
19
|
+
local theme = React.useContext(CleanThemeContext)
|
|
20
|
+
local fieldset = React.useContext(FieldsetContext)
|
|
21
|
+
local switchTheme = theme.components.switch
|
|
22
|
+
local _condition = props.checked
|
|
23
|
+
if _condition == nil then
|
|
24
|
+
_condition = false
|
|
25
|
+
end
|
|
26
|
+
local checked, setChecked = React.useState(_condition)
|
|
27
|
+
React.useEffect(function()
|
|
28
|
+
if not fieldset then
|
|
29
|
+
return nil
|
|
30
|
+
end
|
|
31
|
+
local _connection = fieldset.labelActivated
|
|
32
|
+
if _connection ~= nil then
|
|
33
|
+
_connection = _connection.Event:Connect(function()
|
|
34
|
+
if props.disabled then
|
|
35
|
+
return nil
|
|
36
|
+
end
|
|
37
|
+
setChecked(function(current)
|
|
38
|
+
return not current
|
|
39
|
+
end)
|
|
40
|
+
end)
|
|
41
|
+
end
|
|
42
|
+
local connection = _connection
|
|
43
|
+
return function()
|
|
44
|
+
local _result = connection
|
|
45
|
+
if _result ~= nil then
|
|
46
|
+
_result:Disconnect()
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end, { fieldset, props.disabled })
|
|
50
|
+
React.useEffect(function()
|
|
51
|
+
local _result = props.onChange
|
|
52
|
+
if _result ~= nil then
|
|
53
|
+
_result(checked)
|
|
54
|
+
end
|
|
55
|
+
end, { checked })
|
|
56
|
+
local duration = switchTheme.animation.duration
|
|
57
|
+
local progress, progressTween = useTween(if checked then 1 else 0, {
|
|
58
|
+
duration = duration,
|
|
59
|
+
})
|
|
60
|
+
React.useEffect(function()
|
|
61
|
+
local goal = if checked then 1 else 0
|
|
62
|
+
progressTween:setGoal(goal, {
|
|
63
|
+
duration = duration,
|
|
64
|
+
})
|
|
65
|
+
if duration == 0 then
|
|
66
|
+
progressTween:setPosition(goal)
|
|
67
|
+
end
|
|
68
|
+
progressTween:start()
|
|
69
|
+
end, { checked, duration, progressTween })
|
|
70
|
+
local onColors = ColorHelper:getIntentColors(theme, props.intent, if props.disabled then "disabled" else "default", switchTheme.track.intents)
|
|
71
|
+
local offBackgroundColor = switchTheme.track.backgroundColor
|
|
72
|
+
local offBorderColor = switchTheme.track.borderColor
|
|
73
|
+
local trackBackgroundColor = progress:map(function(value)
|
|
74
|
+
return offBackgroundColor:Lerp(onColors.backgroundColor, value)
|
|
75
|
+
end)
|
|
76
|
+
local trackBorderColor = progress:map(function(value)
|
|
77
|
+
return offBorderColor:Lerp(onColors.borderColor, value)
|
|
78
|
+
end)
|
|
79
|
+
local trackWidth = SizeHelper:toUDim(switchTheme.width)
|
|
80
|
+
local trackHeight = SizeHelper:toUDim(switchTheme.height)
|
|
81
|
+
local inset = SizeHelper:toUDim(switchTheme.thumb.inset)
|
|
82
|
+
local insetDoubled = inset + inset
|
|
83
|
+
local thumbDiameter = trackHeight - insetDoubled
|
|
84
|
+
local thumbOffX = inset
|
|
85
|
+
local thumbOnX = trackWidth - inset - thumbDiameter
|
|
86
|
+
local thumbPosition = progress:map(function(value)
|
|
87
|
+
return UDim2.new(lerpUDim(thumbOffX, thumbOnX, value), UDim.new(0.5, 0))
|
|
88
|
+
end)
|
|
89
|
+
local _attributes = {}
|
|
90
|
+
local _condition_1 = props.name
|
|
91
|
+
if _condition_1 == nil then
|
|
92
|
+
_condition_1 = "Switch"
|
|
93
|
+
end
|
|
94
|
+
_attributes.key = _condition_1
|
|
95
|
+
_attributes.Active = not props.disabled
|
|
96
|
+
_attributes.Selectable = not props.disabled
|
|
97
|
+
_attributes.AutoButtonColor = false
|
|
98
|
+
_attributes.Size = UDim2.new(trackWidth, trackHeight)
|
|
99
|
+
_attributes.ZIndex = props.ZIndex
|
|
100
|
+
_attributes.BackgroundColor3 = trackBackgroundColor
|
|
101
|
+
local _result
|
|
102
|
+
if props.disabled then
|
|
103
|
+
_result = switchTheme.disabledTransparency
|
|
104
|
+
else
|
|
105
|
+
local _condition_2 = props.BackgroundTransparency
|
|
106
|
+
if _condition_2 == nil then
|
|
107
|
+
_condition_2 = switchTheme.track.backgroundTransparency
|
|
108
|
+
end
|
|
109
|
+
_result = _condition_2
|
|
110
|
+
end
|
|
111
|
+
_attributes.BackgroundTransparency = _result
|
|
112
|
+
_attributes.Event = {
|
|
113
|
+
Activated = function()
|
|
114
|
+
if props.disabled then
|
|
115
|
+
return nil
|
|
116
|
+
end
|
|
117
|
+
setChecked(not checked)
|
|
118
|
+
end,
|
|
119
|
+
}
|
|
120
|
+
return React.createElement("imagebutton", _attributes, React.createElement(Corners, {
|
|
121
|
+
radius = switchTheme.cornerRadius,
|
|
122
|
+
}), React.createElement("uistroke", {
|
|
123
|
+
key = "TrackStroke",
|
|
124
|
+
Thickness = switchTheme.borderThickness,
|
|
125
|
+
BorderStrokePosition = Enum.BorderStrokePosition.Inner,
|
|
126
|
+
Color = trackBorderColor,
|
|
127
|
+
}), React.createElement("frame", {
|
|
128
|
+
key = "Thumb",
|
|
129
|
+
Position = thumbPosition,
|
|
130
|
+
AnchorPoint = Vector2.new(0, 0.5),
|
|
131
|
+
Size = UDim2.new(thumbDiameter, thumbDiameter),
|
|
132
|
+
BackgroundColor3 = switchTheme.thumb.backgroundColor,
|
|
133
|
+
BackgroundTransparency = if props.disabled then switchTheme.disabledTransparency else switchTheme.thumb.backgroundTransparency,
|
|
134
|
+
BorderSizePixel = 0,
|
|
135
|
+
}, React.createElement("uistroke", {
|
|
136
|
+
key = "ThumbStroke",
|
|
137
|
+
Thickness = switchTheme.thumb.borderThickness,
|
|
138
|
+
Color = switchTheme.thumb.borderColor,
|
|
139
|
+
}), React.createElement(Corners, {
|
|
140
|
+
radius = switchTheme.thumb.cornerRadius,
|
|
141
|
+
}), React.createElement(BoxShadow, {
|
|
142
|
+
["box-shadow"] = switchTheme.thumb.boxShadow,
|
|
143
|
+
})))
|
|
144
|
+
end
|
|
145
|
+
return {
|
|
146
|
+
Switch = Switch,
|
|
147
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import React from "@rbxts/react";
|
|
2
|
+
import { IntentElementProps } from "../../Interfaces";
|
|
3
|
+
import { BoxProps } from "../Surface";
|
|
4
|
+
export interface ModalProps extends BoxProps, IntentElementProps {
|
|
5
|
+
open?: boolean;
|
|
6
|
+
defaultOpen?: boolean;
|
|
7
|
+
onOpenChange?: (open: boolean) => void;
|
|
8
|
+
closeOnBackdropClick?: boolean;
|
|
9
|
+
closeOnEscape?: boolean;
|
|
10
|
+
draggable?: boolean;
|
|
11
|
+
initialFocus?: React.RefObject<GuiObject>;
|
|
12
|
+
children?: React.ReactNode;
|
|
13
|
+
}
|
|
14
|
+
export declare function Modal(props: ModalProps): React.JSX.Element | undefined;
|
|
@@ -0,0 +1,276 @@
|
|
|
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 ReactRoblox = TS.import(script, TS.getModule(script, "@rbxts", "react-roblox"))
|
|
5
|
+
local GuiService = TS.import(script, TS.getModule(script, "@rbxts", "services")).GuiService
|
|
6
|
+
local useTween = TS.import(script, TS.getModule(script, "@rbxts", "react-ripple").src).useTween
|
|
7
|
+
local _Contexts = TS.import(script, script.Parent.Parent.Parent, "Contexts")
|
|
8
|
+
local CleanThemeContext = _Contexts.CleanThemeContext
|
|
9
|
+
local OverlayConsumer = _Contexts.OverlayConsumer
|
|
10
|
+
local _modal_context = TS.import(script, script.Parent.Parent.Parent, "Contexts", "modal.context")
|
|
11
|
+
local ModalCloseContext = _modal_context.ModalCloseContext
|
|
12
|
+
local useModalStack = _modal_context.useModalStack
|
|
13
|
+
local SizeHelper = TS.import(script, script.Parent.Parent.Parent, "Helpers").SizeHelper
|
|
14
|
+
local Draggable = TS.import(script, script.Parent.Parent, "Layout").Draggable
|
|
15
|
+
local Card = TS.import(script, script.Parent.Parent, "Surface").Card
|
|
16
|
+
local nextModalId = 0
|
|
17
|
+
local function generateModalId()
|
|
18
|
+
nextModalId += 1
|
|
19
|
+
return `modal-{nextModalId}`
|
|
20
|
+
end
|
|
21
|
+
-- GuiService.SelectedObject can only be set to a descendant of a PlayerGui —
|
|
22
|
+
-- it throws otherwise (e.g. a ui-labs Studio plugin preview, or any other
|
|
23
|
+
-- non-PlayerGui host). Focus is a non-essential enhancement, so failures here
|
|
24
|
+
-- are swallowed rather than crashing the whole render.
|
|
25
|
+
local function trySetSelectedObject(target)
|
|
26
|
+
pcall(function()
|
|
27
|
+
GuiService.SelectedObject = target
|
|
28
|
+
end)
|
|
29
|
+
end
|
|
30
|
+
local function getPanelContentSize(automaticSize)
|
|
31
|
+
local autoWidth = automaticSize == Enum.AutomaticSize.X or automaticSize == Enum.AutomaticSize.XY or automaticSize == "X" or automaticSize == "XY"
|
|
32
|
+
local autoHeight = automaticSize == Enum.AutomaticSize.Y or automaticSize == Enum.AutomaticSize.XY or automaticSize == "Y" or automaticSize == "XY"
|
|
33
|
+
return UDim2.fromScale(if autoWidth then 0 else 1, if autoHeight then 0 else 1)
|
|
34
|
+
end
|
|
35
|
+
local function Modal(props)
|
|
36
|
+
local theme = React.useContext(CleanThemeContext)
|
|
37
|
+
local stack = useModalStack()
|
|
38
|
+
local idRef = React.useRef()
|
|
39
|
+
if idRef.current == nil then
|
|
40
|
+
idRef.current = generateModalId()
|
|
41
|
+
end
|
|
42
|
+
local id = idRef.current
|
|
43
|
+
local _condition = props.closeOnBackdropClick
|
|
44
|
+
if _condition == nil then
|
|
45
|
+
_condition = true
|
|
46
|
+
end
|
|
47
|
+
local closeOnBackdropClick = _condition
|
|
48
|
+
local _condition_1 = props.closeOnEscape
|
|
49
|
+
if _condition_1 == nil then
|
|
50
|
+
_condition_1 = true
|
|
51
|
+
end
|
|
52
|
+
local closeOnEscape = _condition_1
|
|
53
|
+
local isControlled = props.open ~= nil
|
|
54
|
+
local _condition_2 = props.defaultOpen
|
|
55
|
+
if _condition_2 == nil then
|
|
56
|
+
_condition_2 = false
|
|
57
|
+
end
|
|
58
|
+
local uncontrolledOpen, setUncontrolledOpen = React.useState(_condition_2)
|
|
59
|
+
local _condition_3 = props.open
|
|
60
|
+
if _condition_3 == nil then
|
|
61
|
+
_condition_3 = uncontrolledOpen
|
|
62
|
+
end
|
|
63
|
+
local open = _condition_3
|
|
64
|
+
local shouldRender, setShouldRender = React.useState(open)
|
|
65
|
+
local dismissingRef = React.useRef(false)
|
|
66
|
+
local fadeThreadRef = React.useRef()
|
|
67
|
+
local panelRef = React.useRef()
|
|
68
|
+
local previousSelectionRef = React.useRef()
|
|
69
|
+
local onOpenChangeRef = React.useRef(props.onOpenChange)
|
|
70
|
+
React.useEffect(function()
|
|
71
|
+
onOpenChangeRef.current = props.onOpenChange
|
|
72
|
+
end, { props.onOpenChange })
|
|
73
|
+
local requestClose = React.useCallback(function()
|
|
74
|
+
if not isControlled then
|
|
75
|
+
setUncontrolledOpen(false)
|
|
76
|
+
end
|
|
77
|
+
local _result = onOpenChangeRef.current
|
|
78
|
+
if _result ~= nil then
|
|
79
|
+
_result(false)
|
|
80
|
+
end
|
|
81
|
+
end, { isControlled })
|
|
82
|
+
local requestCloseRef = React.useRef(requestClose)
|
|
83
|
+
React.useEffect(function()
|
|
84
|
+
requestCloseRef.current = requestClose
|
|
85
|
+
end, { requestClose })
|
|
86
|
+
local closeOnEscapeRef = React.useRef(closeOnEscape)
|
|
87
|
+
React.useEffect(function()
|
|
88
|
+
closeOnEscapeRef.current = closeOnEscape
|
|
89
|
+
end, { closeOnEscape })
|
|
90
|
+
local fadeDuration = theme.components.modal.fadeDuration
|
|
91
|
+
local backdropGoalTransparency = theme.components.modal.backdrop.backgroundTransparency
|
|
92
|
+
local backdropTransparency, backdropTween = useTween(1, {
|
|
93
|
+
duration = fadeDuration,
|
|
94
|
+
easing = "quadOut",
|
|
95
|
+
})
|
|
96
|
+
local panelTransparency, panelTween = useTween(1, {
|
|
97
|
+
duration = fadeDuration,
|
|
98
|
+
easing = "quadOut",
|
|
99
|
+
})
|
|
100
|
+
local beginExit = React.useCallback(function()
|
|
101
|
+
if dismissingRef.current then
|
|
102
|
+
return nil
|
|
103
|
+
end
|
|
104
|
+
dismissingRef.current = true
|
|
105
|
+
if fadeDuration <= 0 then
|
|
106
|
+
setShouldRender(false)
|
|
107
|
+
return nil
|
|
108
|
+
end
|
|
109
|
+
fadeThreadRef.current = task.delay(fadeDuration, function()
|
|
110
|
+
fadeThreadRef.current = nil
|
|
111
|
+
setShouldRender(false)
|
|
112
|
+
end)
|
|
113
|
+
end, { fadeDuration })
|
|
114
|
+
-- Public open state vs. animated-unmount state: closing must finish its
|
|
115
|
+
-- fade before the portal actually disappears, so `shouldRender` lags
|
|
116
|
+
-- `open` on the way down (see beginExit above).
|
|
117
|
+
React.useEffect(function()
|
|
118
|
+
if open then
|
|
119
|
+
local fadeThread = fadeThreadRef.current
|
|
120
|
+
if fadeThread ~= nil then
|
|
121
|
+
task.cancel(fadeThread)
|
|
122
|
+
fadeThreadRef.current = nil
|
|
123
|
+
end
|
|
124
|
+
dismissingRef.current = false
|
|
125
|
+
setShouldRender(true)
|
|
126
|
+
elseif shouldRender then
|
|
127
|
+
beginExit()
|
|
128
|
+
end
|
|
129
|
+
end, { open })
|
|
130
|
+
React.useEffect(function()
|
|
131
|
+
if not shouldRender then
|
|
132
|
+
return nil
|
|
133
|
+
end
|
|
134
|
+
backdropTween:setGoal(if open then backdropGoalTransparency else 1)
|
|
135
|
+
panelTween:setGoal(if open then 0 else 1)
|
|
136
|
+
end, { open, shouldRender, backdropGoalTransparency })
|
|
137
|
+
React.useEffect(function()
|
|
138
|
+
return function()
|
|
139
|
+
local fadeThread = fadeThreadRef.current
|
|
140
|
+
if fadeThread ~= nil then
|
|
141
|
+
task.cancel(fadeThread)
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
end, {})
|
|
145
|
+
-- Registers with the shared modal stack only while actually visible
|
|
146
|
+
-- (including through the closing fade), so escape only ever targets the
|
|
147
|
+
-- topmost visible modal. closeOnEscape/requestClose are read through
|
|
148
|
+
-- refs kept current every render (see above) so this effect only needs
|
|
149
|
+
-- to run when shouldRender flips.
|
|
150
|
+
React.useEffect(function()
|
|
151
|
+
if not shouldRender then
|
|
152
|
+
return nil
|
|
153
|
+
end
|
|
154
|
+
stack.register({
|
|
155
|
+
id = id,
|
|
156
|
+
closeOnEscape = function()
|
|
157
|
+
return closeOnEscapeRef.current
|
|
158
|
+
end,
|
|
159
|
+
requestClose = function()
|
|
160
|
+
return requestCloseRef.current()
|
|
161
|
+
end,
|
|
162
|
+
})
|
|
163
|
+
return function()
|
|
164
|
+
stack.unregister(id)
|
|
165
|
+
end
|
|
166
|
+
end, { shouldRender })
|
|
167
|
+
-- Scoped per-instance so nested modals restore focus to whatever was
|
|
168
|
+
-- selected right before THEY opened, not a single shared value.
|
|
169
|
+
React.useEffect(function()
|
|
170
|
+
if not shouldRender then
|
|
171
|
+
return nil
|
|
172
|
+
end
|
|
173
|
+
previousSelectionRef.current = GuiService.SelectedObject
|
|
174
|
+
local _result = props.initialFocus
|
|
175
|
+
if _result ~= nil then
|
|
176
|
+
_result = _result.current
|
|
177
|
+
end
|
|
178
|
+
local _condition_4 = _result
|
|
179
|
+
if _condition_4 == nil then
|
|
180
|
+
_condition_4 = panelRef.current
|
|
181
|
+
end
|
|
182
|
+
trySetSelectedObject(_condition_4)
|
|
183
|
+
return function()
|
|
184
|
+
trySetSelectedObject(previousSelectionRef.current)
|
|
185
|
+
end
|
|
186
|
+
end, { shouldRender })
|
|
187
|
+
if not shouldRender then
|
|
188
|
+
return nil
|
|
189
|
+
end
|
|
190
|
+
local layerIndex = stack.getLayerIndex(id)
|
|
191
|
+
local backdropZIndex = theme.components.modal.baseZIndex + layerIndex * theme.components.modal.zIndexStep
|
|
192
|
+
return React.createElement(OverlayConsumer, {
|
|
193
|
+
render = function(overlay)
|
|
194
|
+
if overlay == nil then
|
|
195
|
+
return nil
|
|
196
|
+
end
|
|
197
|
+
local panelChildren = if props.draggable then React.Children.map(props.children, function(child)
|
|
198
|
+
return if React.isValidElement(child) and child.type == Card.Header then React.createElement(Draggable.Handle, nil, child) else child
|
|
199
|
+
end) else props.children
|
|
200
|
+
local _object = table.clone(props)
|
|
201
|
+
setmetatable(_object, nil)
|
|
202
|
+
local _left = "width"
|
|
203
|
+
local _condition_4 = props.width
|
|
204
|
+
if _condition_4 == nil then
|
|
205
|
+
_condition_4 = theme.components.modal.width
|
|
206
|
+
end
|
|
207
|
+
_object[_left] = _condition_4
|
|
208
|
+
local panelSizingProps = _object
|
|
209
|
+
local panelSize = SizeHelper:GetSize(panelSizingProps)
|
|
210
|
+
local panelAutomaticSize = SizeHelper:GetAutoSize(panelSizingProps)
|
|
211
|
+
local panelContentSize = if type(panelAutomaticSize) == "table" and panelAutomaticSize.map ~= nil then panelAutomaticSize:map(getPanelContentSize) else getPanelContentSize(panelAutomaticSize)
|
|
212
|
+
local _attributes = table.clone(props)
|
|
213
|
+
setmetatable(_attributes, nil)
|
|
214
|
+
local _condition_5 = props.name
|
|
215
|
+
if _condition_5 == nil then
|
|
216
|
+
_condition_5 = "Modal"
|
|
217
|
+
end
|
|
218
|
+
_attributes.name = _condition_5
|
|
219
|
+
_attributes.ref = panelRef
|
|
220
|
+
_attributes.Selectable = true
|
|
221
|
+
_attributes.Size = panelContentSize
|
|
222
|
+
_attributes.AutomaticSize = panelAutomaticSize
|
|
223
|
+
_attributes.width = nil
|
|
224
|
+
_attributes.height = nil
|
|
225
|
+
local panel = (React.createElement("imagebutton", {
|
|
226
|
+
key = "ModalPanelInputShield",
|
|
227
|
+
Active = true,
|
|
228
|
+
AnchorPoint = if props.draggable then Vector2.new(0.5, 0.5) else nil,
|
|
229
|
+
AutoButtonColor = false,
|
|
230
|
+
AutomaticSize = panelAutomaticSize,
|
|
231
|
+
BackgroundTransparency = 1,
|
|
232
|
+
ImageTransparency = 1,
|
|
233
|
+
Position = if props.draggable then UDim2.fromScale(0.5, 0.5) else nil,
|
|
234
|
+
Size = panelSize,
|
|
235
|
+
Event = {
|
|
236
|
+
Activated = function() end,
|
|
237
|
+
},
|
|
238
|
+
}, React.createElement(Card, _attributes, panelChildren)))
|
|
239
|
+
return ReactRoblox.createPortal(React.createElement("imagebutton", {
|
|
240
|
+
key = "ModalBackdrop",
|
|
241
|
+
Size = UDim2.fromScale(1, 1),
|
|
242
|
+
AutoButtonColor = false,
|
|
243
|
+
Active = true,
|
|
244
|
+
BackgroundColor3 = theme.components.modal.backdrop.backgroundColor,
|
|
245
|
+
BackgroundTransparency = backdropTransparency,
|
|
246
|
+
ZIndex = backdropZIndex,
|
|
247
|
+
Event = {
|
|
248
|
+
Activated = function()
|
|
249
|
+
if closeOnBackdropClick then
|
|
250
|
+
requestClose()
|
|
251
|
+
end
|
|
252
|
+
end,
|
|
253
|
+
},
|
|
254
|
+
}, React.createElement("canvasgroup", {
|
|
255
|
+
key = "ModalPanel",
|
|
256
|
+
Size = UDim2.fromScale(1, 1),
|
|
257
|
+
BackgroundTransparency = 1,
|
|
258
|
+
GroupTransparency = panelTransparency,
|
|
259
|
+
ZIndex = 2,
|
|
260
|
+
}, not props.draggable and (React.createElement("uilistlayout", {
|
|
261
|
+
key = "CenterLayout",
|
|
262
|
+
FillDirection = Enum.FillDirection.Horizontal,
|
|
263
|
+
HorizontalAlignment = Enum.HorizontalAlignment.Center,
|
|
264
|
+
VerticalAlignment = Enum.VerticalAlignment.Center,
|
|
265
|
+
})), React.createElement(ModalCloseContext.Provider, {
|
|
266
|
+
value = requestClose,
|
|
267
|
+
}, if props.draggable then (React.createElement(Draggable, {
|
|
268
|
+
placeholder = false,
|
|
269
|
+
retainPosition = true,
|
|
270
|
+
}, panel)) else panel))), overlay)
|
|
271
|
+
end,
|
|
272
|
+
})
|
|
273
|
+
end
|
|
274
|
+
return {
|
|
275
|
+
Modal = Modal,
|
|
276
|
+
}
|
|
@@ -4,8 +4,9 @@ import { ToastOptions } from "../../Contexts";
|
|
|
4
4
|
interface ToastProps extends ToastOptions {
|
|
5
5
|
onDismiss: () => void;
|
|
6
6
|
}
|
|
7
|
-
export declare function Toast({ title, description, icon, intent, duration, dismissible, children, onDismiss, }: ToastProps): React.JSX.Element;
|
|
7
|
+
export declare function Toast({ title, description, icon, intent, duration, dismissible, children, name, onDismiss, }: ToastProps): React.JSX.Element;
|
|
8
8
|
interface ToastContainerProps extends SizeElementProps {
|
|
9
|
+
name?: string;
|
|
9
10
|
}
|
|
10
11
|
export declare function ToastContainer(props: ToastContainerProps): React.JSX.Element | undefined;
|
|
11
12
|
export {};
|
|
@@ -49,6 +49,10 @@ local function Toast(_param)
|
|
|
49
49
|
if children == nil then
|
|
50
50
|
children = nil
|
|
51
51
|
end
|
|
52
|
+
local name = _param.name
|
|
53
|
+
if name == nil then
|
|
54
|
+
name = nil
|
|
55
|
+
end
|
|
52
56
|
local onDismiss = _param.onDismiss
|
|
53
57
|
local theme = React.useContext(CleanThemeContext)
|
|
54
58
|
local dismissRef = React.useRef(onDismiss)
|
|
@@ -109,53 +113,69 @@ local function Toast(_param)
|
|
|
109
113
|
end
|
|
110
114
|
end, {})
|
|
111
115
|
local boxStyles = ColorHelper:getIntentColors(theme, intent, "default", theme.components.toast.intents)
|
|
112
|
-
local
|
|
113
|
-
|
|
116
|
+
local _attributes = {}
|
|
117
|
+
local _condition = name
|
|
118
|
+
if _condition == nil then
|
|
119
|
+
_condition = "Toast"
|
|
120
|
+
end
|
|
121
|
+
_attributes.key = _condition
|
|
122
|
+
_attributes.Size = UDim2.fromScale(0, 0)
|
|
123
|
+
_attributes.AutomaticSize = Enum.AutomaticSize.XY
|
|
124
|
+
_attributes.BackgroundTransparency = 1
|
|
125
|
+
_attributes.GroupTransparency = groupTransparency
|
|
126
|
+
local _condition_1 = children ~= nil and children
|
|
127
|
+
if not _condition_1 then
|
|
114
128
|
local _exp = icon ~= nil and React.createElement(Icon, {
|
|
129
|
+
name = "ToastIcon",
|
|
115
130
|
icon = icon,
|
|
116
131
|
scale = "sm",
|
|
117
132
|
color = boxStyles.textColor,
|
|
118
133
|
})
|
|
119
|
-
local
|
|
134
|
+
local _attributes_1 = {
|
|
135
|
+
name = "ToastTitle",
|
|
120
136
|
TextColor3 = boxStyles.textColor,
|
|
121
137
|
}
|
|
122
|
-
local
|
|
123
|
-
if
|
|
124
|
-
|
|
138
|
+
local _condition_2 = title
|
|
139
|
+
if _condition_2 == nil then
|
|
140
|
+
_condition_2 = ""
|
|
125
141
|
end
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
142
|
+
_attributes_1.text = _condition_2
|
|
143
|
+
_attributes_1.typography = TypographyHelper:getTypography(theme, nil, theme.components.toast.header.typography)
|
|
144
|
+
_condition_1 = React.createElement(VStack, {
|
|
129
145
|
spacing = "None",
|
|
130
|
-
}, React.createElement(Container,
|
|
146
|
+
}, React.createElement(Container, {
|
|
147
|
+
name = "ToastHeader",
|
|
148
|
+
}, React.createElement(HStack, {
|
|
131
149
|
valign = "Center",
|
|
132
|
-
}, _exp, React.createElement(Text,
|
|
150
|
+
}, _exp, React.createElement(Text, _attributes_1), dismissible and (React.createElement(FlexItem, {
|
|
133
151
|
align = "Right",
|
|
134
152
|
}, React.createElement(Button, {
|
|
153
|
+
name = "ToastDismissButton",
|
|
135
154
|
intent = intent,
|
|
136
155
|
spacing = "xs",
|
|
137
156
|
Event = {
|
|
138
157
|
Activated = beginDismiss,
|
|
139
158
|
},
|
|
140
159
|
}, React.createElement(Button.Icon, {
|
|
160
|
+
name = "ToastDismissIcon",
|
|
141
161
|
intent = intent,
|
|
142
162
|
icon = "times",
|
|
143
163
|
scale = "sm",
|
|
144
|
-
})))))), description ~= nil and (React.createElement(Container,
|
|
164
|
+
})))))), description ~= nil and (React.createElement(Container, {
|
|
165
|
+
name = "ToastDescriptionContainer",
|
|
166
|
+
}, React.createElement(Text, {
|
|
167
|
+
name = "ToastDescription",
|
|
145
168
|
text = description,
|
|
146
169
|
TextColor3 = boxStyles.textColor,
|
|
147
170
|
}))))
|
|
148
171
|
end
|
|
149
|
-
return React.createElement("canvasgroup", {
|
|
150
|
-
|
|
151
|
-
AutomaticSize = Enum.AutomaticSize.XY,
|
|
152
|
-
BackgroundTransparency = 1,
|
|
153
|
-
GroupTransparency = groupTransparency,
|
|
154
|
-
}, React.createElement(Box, {
|
|
172
|
+
return React.createElement("canvasgroup", _attributes, React.createElement(Box, {
|
|
173
|
+
name = "ToastBox",
|
|
155
174
|
["border-color"] = boxStyles.borderColor,
|
|
156
175
|
BackgroundColor3 = boxStyles.backgroundColor,
|
|
157
176
|
BackgroundTransparency = boxStyles.backgroundTransparency,
|
|
158
|
-
},
|
|
177
|
+
}, _condition_1), statusBarTheme ~= nil and React.createElement(React.Fragment, nil, React.createElement("frame", {
|
|
178
|
+
key = "StatusBar",
|
|
159
179
|
Size = progress:map(function(value)
|
|
160
180
|
return UDim2.new(UDim.new(value, 0), SizeHelper:toUDim(statusBarTheme.height))
|
|
161
181
|
end),
|
|
@@ -179,29 +199,34 @@ local function ToastContainer(props)
|
|
|
179
199
|
end
|
|
180
200
|
local position = if theme.components.toast.position then SizeHelper:GetPosition(theme.components.toast.position) else UDim2.fromOffset(5, 5)
|
|
181
201
|
local anchor = if theme.components.toast.position then SizeHelper:GetAnchor(theme.components.toast.position) else Vector2.new(0, 0)
|
|
202
|
+
local _attributes = {}
|
|
203
|
+
local _condition = props.name
|
|
204
|
+
if _condition == nil then
|
|
205
|
+
_condition = "ToastContainer"
|
|
206
|
+
end
|
|
207
|
+
_attributes.name = _condition
|
|
208
|
+
_attributes.Size = SizeHelper:GetSize(props, UDim2.new(SizeHelper:toUDim(theme.components.toast.width), UDim.new(0, 0)))
|
|
209
|
+
_attributes.Position = position
|
|
210
|
+
_attributes.AnchorPoint = anchor
|
|
182
211
|
-- ▼ ReadonlyArray.map ▼
|
|
183
212
|
local _newValue = table.create(#toasts)
|
|
184
213
|
local _callback = function(toast)
|
|
185
|
-
local
|
|
214
|
+
local _attributes_1 = {
|
|
186
215
|
key = toast.id,
|
|
187
216
|
}
|
|
188
217
|
for _k, _v in toast do
|
|
189
|
-
|
|
218
|
+
_attributes_1[_k] = _v
|
|
190
219
|
end
|
|
191
|
-
|
|
220
|
+
_attributes_1.onDismiss = function()
|
|
192
221
|
return dismiss(toast.id)
|
|
193
222
|
end
|
|
194
|
-
return React.createElement(Toast,
|
|
223
|
+
return React.createElement(Toast, _attributes_1)
|
|
195
224
|
end
|
|
196
225
|
for _k, _v in toasts do
|
|
197
226
|
_newValue[_k] = _callback(_v, _k - 1, toasts)
|
|
198
227
|
end
|
|
199
228
|
-- ▲ ReadonlyArray.map ▲
|
|
200
|
-
return React.createElement(Container, {
|
|
201
|
-
Size = SizeHelper:GetSize(props, UDim2.new(SizeHelper:toUDim(theme.components.toast.width), UDim.new(0, 0))),
|
|
202
|
-
Position = position,
|
|
203
|
-
AnchorPoint = anchor,
|
|
204
|
-
}, React.createElement(VStack, {
|
|
229
|
+
return React.createElement(Container, _attributes, React.createElement(VStack, {
|
|
205
230
|
spacing = "xs",
|
|
206
231
|
}, _newValue))
|
|
207
232
|
end
|