@rbxts/react-clean-ui 1.2.2 → 1.2.5
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/Pie.luau +0 -1
- package/out/Components/Decorator/Gradient.d.ts +8 -0
- package/out/Components/Decorator/Gradient.luau +23 -0
- package/out/Components/Decorator/index.d.ts +1 -0
- package/out/Components/Decorator/init.luau +3 -0
- package/out/Components/Input/Button.luau +5 -1
- package/out/Components/Input/Checkbox.luau +6 -2
- package/out/Components/Input/HoverButton.luau +0 -2
- package/out/Components/Input/Input.luau +8 -6
- package/out/Components/Input/Select.d.ts +2 -1
- package/out/Components/Input/Select.luau +10 -11
- package/out/Components/Input/Slider.luau +0 -24
- package/out/Components/Input/Switch.luau +0 -2
- package/out/Components/Interaction/Modal.luau +0 -14
- package/out/Components/Interaction/Tooltip.luau +0 -1
- package/out/Components/Layout/Container.d.ts +2 -0
- package/out/Components/Layout/Container.luau +4 -1
- package/out/Components/Layout/Grid.d.ts +10 -0
- package/out/Components/Layout/Grid.luau +172 -0
- package/out/Components/Layout/Group.luau +38 -33
- package/out/Components/Layout/Pagination.luau +0 -5
- package/out/Components/Layout/Tabs.d.ts +2 -1
- package/out/Components/Layout/Tabs.luau +12 -33
- package/out/Components/Layout/index.d.ts +1 -0
- package/out/Components/Layout/init.luau +3 -0
- package/out/Components/Surface/Box.d.ts +2 -1
- package/out/Components/Surface/Box.luau +3 -0
- package/out/Components/Surface/Card.luau +54 -111
- package/out/Components/Surface/ProgressBar.d.ts +14 -0
- package/out/Components/Surface/ProgressBar.luau +230 -0
- package/out/Components/Surface/index.d.ts +1 -0
- package/out/Components/Surface/init.luau +3 -0
- package/out/Components/Typography/Text.luau +0 -6
- package/out/Contexts/modal.context.luau +0 -3
- package/out/Helpers/color.helper.luau +28 -0
- package/out/Helpers/css.helper.d.ts +4 -1
- package/out/Helpers/css.helper.luau +76 -6
- package/out/Helpers/gui.helper.luau +0 -3
- package/out/Helpers/size.helper.luau +0 -2
- package/out/Helpers/spacing.helper.luau +0 -3
- package/out/Helpers/typography.helper.luau +0 -2
- package/out/Interfaces/css.types.d.ts +7 -0
- package/out/Interfaces/css.types.luau +0 -20
- package/out/Providers/registry.provider.luau +0 -2
- package/out/Theme/theme.style.d.ts +8 -1
- package/out/Theme/theme.template.d.ts +44 -2
- package/out/Theme/themes/dark.theme.luau +122 -0
- package/out/Theme/themes/default.theme.luau +80 -0
- package/out/Theme/themes/sandstone.theme.luau +70 -0
- package/out/Theme/themes/wooden.theme.luau +73 -0
- package/package.json +1 -1
|
@@ -0,0 +1,230 @@
|
|
|
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 _Helpers = TS.import(script, script.Parent.Parent.Parent, "Helpers")
|
|
7
|
+
local ColorHelper = _Helpers.ColorHelper
|
|
8
|
+
local CssHelper = _Helpers.CssHelper
|
|
9
|
+
local SizeHelper = _Helpers.SizeHelper
|
|
10
|
+
local SpacingHelper = _Helpers.SpacingHelper
|
|
11
|
+
local TypographyHelper = _Helpers.TypographyHelper
|
|
12
|
+
local _Decorator = TS.import(script, script.Parent.Parent, "Decorator")
|
|
13
|
+
local Corners = _Decorator.Corners
|
|
14
|
+
local Gradient = _Decorator.Gradient
|
|
15
|
+
local _Layout = TS.import(script, script.Parent.Parent, "Layout")
|
|
16
|
+
local Container = _Layout.Container
|
|
17
|
+
local HStack = _Layout.HStack
|
|
18
|
+
local VStack = _Layout.VStack
|
|
19
|
+
local Text = TS.import(script, script.Parent.Parent, "Typography").Text
|
|
20
|
+
local function defaultValueFormatter(value, max)
|
|
21
|
+
local percent = if max > 0 then (value / max) * 100 else 0
|
|
22
|
+
return `{math.round(percent)}%`
|
|
23
|
+
end
|
|
24
|
+
local ProgressBar = React.forwardRef(function(props, ref)
|
|
25
|
+
local theme = React.useContext(CleanThemeContext)
|
|
26
|
+
local progressBarTheme = theme.components.progressBar
|
|
27
|
+
local _condition = props.max
|
|
28
|
+
if _condition == nil then
|
|
29
|
+
_condition = 100
|
|
30
|
+
end
|
|
31
|
+
local maxValue = math.max(_condition, 0)
|
|
32
|
+
local clampedValue = math.clamp(props.value, 0, maxValue)
|
|
33
|
+
local targetProgress = if maxValue > 0 then clampedValue / maxValue else 0
|
|
34
|
+
local duration = progressBarTheme.animation.duration
|
|
35
|
+
local progress, progressTween = useTween(targetProgress, {
|
|
36
|
+
duration = duration,
|
|
37
|
+
})
|
|
38
|
+
React.useEffect(function()
|
|
39
|
+
progressTween:setGoal(targetProgress, {
|
|
40
|
+
duration = duration,
|
|
41
|
+
})
|
|
42
|
+
if duration == 0 then
|
|
43
|
+
progressTween:setPosition(targetProgress)
|
|
44
|
+
end
|
|
45
|
+
end, { targetProgress, duration, progressTween })
|
|
46
|
+
local colors = ColorHelper:getIntentColors(theme, props.intent, "default", progressBarTheme.fill.intents)
|
|
47
|
+
local height = SizeHelper:toUDim(progressBarTheme.height[props.scale or theme.default.scale])
|
|
48
|
+
local fillSize = progress:map(function(value)
|
|
49
|
+
return UDim2.fromScale(value, 1)
|
|
50
|
+
end)
|
|
51
|
+
local fillPosition = UDim2.fromScale(0, 0)
|
|
52
|
+
local stripeTheme = progressBarTheme.fill.stripe
|
|
53
|
+
local _condition_1 = props.striped
|
|
54
|
+
if _condition_1 == nil then
|
|
55
|
+
local _result = stripeTheme
|
|
56
|
+
if _result ~= nil then
|
|
57
|
+
_result = _result.enabled
|
|
58
|
+
end
|
|
59
|
+
_condition_1 = _result
|
|
60
|
+
if _condition_1 == nil then
|
|
61
|
+
_condition_1 = false
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
local striped = _condition_1
|
|
65
|
+
local _condition_2 = props.stripeDuration
|
|
66
|
+
if _condition_2 == nil then
|
|
67
|
+
local _result = stripeTheme
|
|
68
|
+
if _result ~= nil then
|
|
69
|
+
_result = _result.duration
|
|
70
|
+
end
|
|
71
|
+
_condition_2 = _result
|
|
72
|
+
if _condition_2 == nil then
|
|
73
|
+
_condition_2 = 0.75
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
local stripeDuration = _condition_2
|
|
77
|
+
local _condition_3 = props.stripeDirection
|
|
78
|
+
if _condition_3 == nil then
|
|
79
|
+
local _result = stripeTheme
|
|
80
|
+
if _result ~= nil then
|
|
81
|
+
_result = _result.direction
|
|
82
|
+
end
|
|
83
|
+
_condition_3 = _result
|
|
84
|
+
end
|
|
85
|
+
local rawStripeDirection = _condition_3
|
|
86
|
+
local stripeDirection = if rawStripeDirection == -1 then -1 else 1
|
|
87
|
+
local _result = stripeTheme
|
|
88
|
+
if _result ~= nil then
|
|
89
|
+
_result = _result.image
|
|
90
|
+
end
|
|
91
|
+
local resolvedStripeImage = CssHelper:resolveBackgroundImage(_result)
|
|
92
|
+
local stripeTileSize = resolvedStripeImage.TileSize or UDim2.fromOffset(16, 16)
|
|
93
|
+
local stripeTileWidth = if stripeTileSize.X.Offset ~= 0 then stripeTileSize.X.Offset else 16
|
|
94
|
+
local stripeProgress, stripeTween = useTween(0, {
|
|
95
|
+
duration = stripeDuration,
|
|
96
|
+
easing = "linear",
|
|
97
|
+
repeats = math.huge,
|
|
98
|
+
reverses = false,
|
|
99
|
+
})
|
|
100
|
+
React.useEffect(function()
|
|
101
|
+
if not striped then
|
|
102
|
+
return nil
|
|
103
|
+
end
|
|
104
|
+
stripeTween:setPosition(0)
|
|
105
|
+
stripeTween:setGoal(1, {
|
|
106
|
+
duration = stripeDuration,
|
|
107
|
+
})
|
|
108
|
+
end, { striped, stripeDuration, stripeTween })
|
|
109
|
+
local stripePosition = stripeProgress:map(function(value)
|
|
110
|
+
return if stripeDirection == 1 then UDim2.fromOffset(-stripeTileWidth + value * stripeTileWidth, 0) else UDim2.fromOffset(-value * stripeTileWidth, 0)
|
|
111
|
+
end)
|
|
112
|
+
local showHeader = props.label ~= nil or props.showValue == true
|
|
113
|
+
local formattedValue = if props.showValue then (props.valueFormatter or defaultValueFormatter)(clampedValue, maxValue) else nil
|
|
114
|
+
local labelTypography = TypographyHelper:getTypography(theme, props.scale, progressBarTheme.header.label.typography)
|
|
115
|
+
local valueTypography = TypographyHelper:getTypography(theme, props.scale, progressBarTheme.header.value.typography or progressBarTheme.header.label.typography)
|
|
116
|
+
local _attributes = {}
|
|
117
|
+
local _condition_4 = props.name
|
|
118
|
+
if _condition_4 == nil then
|
|
119
|
+
_condition_4 = "ProgressBar"
|
|
120
|
+
end
|
|
121
|
+
_attributes.name = _condition_4
|
|
122
|
+
_attributes.ref = ref
|
|
123
|
+
for _k, _v in props do
|
|
124
|
+
_attributes[_k] = _v
|
|
125
|
+
end
|
|
126
|
+
_attributes.Size = SizeHelper:GetSize(props, UDim2.new(UDim.new(1, 0), height))
|
|
127
|
+
local _condition_5 = props.ClipsDescendants
|
|
128
|
+
if _condition_5 == nil then
|
|
129
|
+
_condition_5 = true
|
|
130
|
+
end
|
|
131
|
+
_attributes.ClipsDescendants = _condition_5
|
|
132
|
+
_attributes.BackgroundColor3 = progressBarTheme.track.backgroundColor
|
|
133
|
+
_attributes.BackgroundTransparency = progressBarTheme.track.backgroundTransparency
|
|
134
|
+
_attributes.backgroundImage = progressBarTheme.track.backgroundImage
|
|
135
|
+
_attributes.backgroundGradient = progressBarTheme.track.backgroundGradient
|
|
136
|
+
local _exp = React.createElement("uistroke", {
|
|
137
|
+
key = "Stroke",
|
|
138
|
+
Thickness = progressBarTheme.track.borderThickness,
|
|
139
|
+
BorderStrokePosition = Enum.BorderStrokePosition.Inner,
|
|
140
|
+
Color = progressBarTheme.track.borderColor,
|
|
141
|
+
})
|
|
142
|
+
local _exp_1 = React.createElement(Corners, {
|
|
143
|
+
radius = progressBarTheme.track.cornerRadius,
|
|
144
|
+
})
|
|
145
|
+
local _attributes_1 = {
|
|
146
|
+
key = "Fill",
|
|
147
|
+
Size = fillSize,
|
|
148
|
+
Position = fillPosition,
|
|
149
|
+
BackgroundColor3 = colors.backgroundColor,
|
|
150
|
+
}
|
|
151
|
+
local _condition_6 = colors.backgroundTransparency
|
|
152
|
+
if _condition_6 == nil then
|
|
153
|
+
_condition_6 = 0
|
|
154
|
+
end
|
|
155
|
+
_attributes_1.BackgroundTransparency = _condition_6
|
|
156
|
+
_attributes_1.BorderSizePixel = 0
|
|
157
|
+
_attributes_1.ClipsDescendants = true
|
|
158
|
+
local _exp_2 = React.createElement(Corners, {
|
|
159
|
+
radius = progressBarTheme.fill.cornerRadius,
|
|
160
|
+
})
|
|
161
|
+
local _exp_3 = React.createElement(Gradient, {
|
|
162
|
+
value = colors.backgroundGradient,
|
|
163
|
+
})
|
|
164
|
+
local _condition_7 = striped
|
|
165
|
+
if _condition_7 then
|
|
166
|
+
local _attributes_2 = {
|
|
167
|
+
key = "Stripe",
|
|
168
|
+
BackgroundTransparency = 1,
|
|
169
|
+
}
|
|
170
|
+
local _condition_8 = resolvedStripeImage.ImageTransparency
|
|
171
|
+
if _condition_8 == nil then
|
|
172
|
+
_condition_8 = 0.9
|
|
173
|
+
end
|
|
174
|
+
_attributes_2.ImageTransparency = _condition_8
|
|
175
|
+
_attributes_2.ImageColor3 = resolvedStripeImage.ImageColor3
|
|
176
|
+
_attributes_2.Size = UDim2.new(1, stripeTileWidth, 1, 0)
|
|
177
|
+
_attributes_2.Position = stripePosition
|
|
178
|
+
local _condition_9 = resolvedStripeImage.Image
|
|
179
|
+
if _condition_9 == nil then
|
|
180
|
+
_condition_9 = `rbxassetid://86644568183933`
|
|
181
|
+
end
|
|
182
|
+
_attributes_2.Image = _condition_9
|
|
183
|
+
_attributes_2.ScaleType = Enum.ScaleType.Tile
|
|
184
|
+
_attributes_2.TileSize = stripeTileSize
|
|
185
|
+
_condition_7 = (React.createElement("imagelabel", _attributes_2))
|
|
186
|
+
end
|
|
187
|
+
local track = (React.createElement(Container, _attributes, _exp, _exp_1, React.createElement("frame", _attributes_1, _exp_2, _exp_3, _condition_7)))
|
|
188
|
+
if not showHeader then
|
|
189
|
+
return track
|
|
190
|
+
end
|
|
191
|
+
local _attributes_2 = {}
|
|
192
|
+
local _condition_8 = props.name
|
|
193
|
+
if _condition_8 == nil then
|
|
194
|
+
_condition_8 = "ProgressBar"
|
|
195
|
+
end
|
|
196
|
+
_attributes_2.key = _condition_8
|
|
197
|
+
_attributes_2.BackgroundTransparency = 1
|
|
198
|
+
_attributes_2.Size = SizeHelper:GetSize(props, UDim2.fromScale(1, 0))
|
|
199
|
+
_attributes_2.AutomaticSize = Enum.AutomaticSize.Y
|
|
200
|
+
_attributes_2.Position = SizeHelper:GetPosition(props)
|
|
201
|
+
_attributes_2.AnchorPoint = SizeHelper:GetAnchor(props)
|
|
202
|
+
_attributes_2.ZIndex = props.ZIndex
|
|
203
|
+
return React.createElement("frame", _attributes_2, React.createElement(VStack, {
|
|
204
|
+
spacing = "None",
|
|
205
|
+
HorizontalFlex = Enum.UIFlexAlignment.None,
|
|
206
|
+
Padding = UDim.new(0, SpacingHelper:GetPadding(theme, props.scale, progressBarTheme.header.spacing)),
|
|
207
|
+
}, React.createElement("frame", {
|
|
208
|
+
key = "ProgressBarHeader",
|
|
209
|
+
BackgroundTransparency = 1,
|
|
210
|
+
Size = UDim2.fromScale(1, 0),
|
|
211
|
+
AutomaticSize = Enum.AutomaticSize.Y,
|
|
212
|
+
}, React.createElement(HStack, {
|
|
213
|
+
valign = "Center",
|
|
214
|
+
Wraps = false,
|
|
215
|
+
HorizontalFlex = Enum.UIFlexAlignment.SpaceBetween,
|
|
216
|
+
}, props.label ~= nil and (React.createElement(Text, {
|
|
217
|
+
name = "ProgressBarLabel",
|
|
218
|
+
text = props.label,
|
|
219
|
+
TextColor3 = labelTypography.color,
|
|
220
|
+
typography = labelTypography,
|
|
221
|
+
})), formattedValue ~= nil and (React.createElement(Text, {
|
|
222
|
+
name = "ProgressBarValue",
|
|
223
|
+
text = formattedValue,
|
|
224
|
+
TextColor3 = valueTypography.color,
|
|
225
|
+
typography = valueTypography,
|
|
226
|
+
})))), track))
|
|
227
|
+
end)
|
|
228
|
+
return {
|
|
229
|
+
ProgressBar = ProgressBar,
|
|
230
|
+
}
|
|
@@ -12,12 +12,6 @@ local Text = React.forwardRef(function(props, ref)
|
|
|
12
12
|
_condition = style.letterSpacing
|
|
13
13
|
end
|
|
14
14
|
local letterSpacing = _condition
|
|
15
|
-
-- Roblox text instances have no native letter-spacing property, so a nonzero
|
|
16
|
-
-- value is faked by splitting the text into one TextLabel per character laid
|
|
17
|
-
-- out in a UIListLayout row with the spacing as its Padding. This only makes
|
|
18
|
-
-- sense for short, single-line, plain text: RichText is forced off per-character
|
|
19
|
-
-- (markup tags can't survive being split apart), and wrapping/truncation are
|
|
20
|
-
-- moot since each character label auto-sizes to itself and never overflows.
|
|
21
15
|
if letterSpacing ~= nil and letterSpacing ~= 0 and props.text ~= "" then
|
|
22
16
|
local characters = {}
|
|
23
17
|
for index = 0, #props.text - 1 do
|
|
@@ -8,9 +8,6 @@ local function useModalStack()
|
|
|
8
8
|
assert(_arg0, "ModalProvider is missing.")
|
|
9
9
|
return context
|
|
10
10
|
end
|
|
11
|
-
-- Per-instance, provided by each <Modal> around its own children so a
|
|
12
|
-
-- header close button or footer button can close the nearest modal
|
|
13
|
-
-- without the consumer threading their own handler down manually.
|
|
14
11
|
local ModalCloseContext = React.createContext(nil)
|
|
15
12
|
local function useModalClose()
|
|
16
13
|
local context = React.useContext(ModalCloseContext)
|
|
@@ -46,6 +46,7 @@ do
|
|
|
46
46
|
function ColorHelper:mergeLayers(layers)
|
|
47
47
|
local merged = {}
|
|
48
48
|
local backgroundImage
|
|
49
|
+
local backgroundGradient
|
|
49
50
|
local typography
|
|
50
51
|
for _, layer in layers do
|
|
51
52
|
if layer == nil then
|
|
@@ -69,6 +70,32 @@ do
|
|
|
69
70
|
end
|
|
70
71
|
backgroundImage = _object_1
|
|
71
72
|
end
|
|
73
|
+
if layer.backgroundGradient ~= nil then
|
|
74
|
+
local _result
|
|
75
|
+
if layer.backgroundGradient.colors ~= nil then
|
|
76
|
+
local _object_1 = {}
|
|
77
|
+
if backgroundGradient then
|
|
78
|
+
for _k, _v in backgroundGradient do
|
|
79
|
+
_object_1[_k] = _v
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
_object_1.stops = nil
|
|
83
|
+
_result = _object_1
|
|
84
|
+
else
|
|
85
|
+
_result = backgroundGradient
|
|
86
|
+
end
|
|
87
|
+
local inheritedGradient = _result
|
|
88
|
+
local _object_1 = {}
|
|
89
|
+
if inheritedGradient then
|
|
90
|
+
for _k, _v in inheritedGradient do
|
|
91
|
+
_object_1[_k] = _v
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
for _k, _v in layer.backgroundGradient do
|
|
95
|
+
_object_1[_k] = _v
|
|
96
|
+
end
|
|
97
|
+
backgroundGradient = _object_1
|
|
98
|
+
end
|
|
72
99
|
if layer.typography ~= nil then
|
|
73
100
|
local _object_1 = {}
|
|
74
101
|
if typography then
|
|
@@ -83,6 +110,7 @@ do
|
|
|
83
110
|
end
|
|
84
111
|
end
|
|
85
112
|
merged.backgroundImage = backgroundImage
|
|
113
|
+
merged.backgroundGradient = backgroundGradient
|
|
86
114
|
merged.typography = typography
|
|
87
115
|
return merged
|
|
88
116
|
end
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { CssBoxShadow, CssShadow, CssCalcSize, CssQuad, CssDual, CssSliceInset } from "../Interfaces/css.types";
|
|
1
|
+
import { CssBoxShadow, CssShadow, CssCalcSize, CssQuad, CssDual, CssSliceInset, CssBackgroundGradient } from "../Interfaces/css.types";
|
|
2
2
|
import { CssBackgroundImage } from "../Theme";
|
|
3
3
|
interface ParsedShadow {
|
|
4
4
|
offset: UDim2;
|
|
@@ -35,5 +35,8 @@ export declare class CssHelper {
|
|
|
35
35
|
SliceScale?: number;
|
|
36
36
|
TileSize?: UDim2;
|
|
37
37
|
};
|
|
38
|
+
static resolveBackgroundGradient(value: Partial<CssBackgroundGradient> | undefined): React.InstanceProps<UIGradient> | undefined;
|
|
39
|
+
private static buildColorSequence;
|
|
40
|
+
private static buildTransparencySequence;
|
|
38
41
|
}
|
|
39
42
|
export {};
|
|
@@ -86,12 +86,6 @@ do
|
|
|
86
86
|
if type(_value) == "number" then
|
|
87
87
|
return UDim.new(0, value)
|
|
88
88
|
end
|
|
89
|
-
-- The one CSS calc() shape supported: "<percent>% - <px>px" /
|
|
90
|
-
-- "<percent>% + <px>px" (e.g. "100% - 50px") maps directly onto
|
|
91
|
-
-- UDim(scale, offset) — split on the literal " - "/" + " separator
|
|
92
|
-
-- and parse each term with this same function. Anything without
|
|
93
|
-
-- either separator falls through to the single-token parsing below,
|
|
94
|
-
-- unchanged.
|
|
95
89
|
local minusParts = string.split(value, " - ")
|
|
96
90
|
if #minusParts == 2 then
|
|
97
91
|
local scale = self:parseCssSize(minusParts[1]).Scale
|
|
@@ -341,6 +335,82 @@ do
|
|
|
341
335
|
_object.TileSize = if value.tileSize ~= nil then self:parseCssDual(value.tileSize) else nil
|
|
342
336
|
return _object
|
|
343
337
|
end
|
|
338
|
+
function CssHelper:resolveBackgroundGradient(value)
|
|
339
|
+
local _colors = value
|
|
340
|
+
if _colors ~= nil then
|
|
341
|
+
_colors = _colors.colors
|
|
342
|
+
end
|
|
343
|
+
local colors = _colors
|
|
344
|
+
if value == nil or colors == nil then
|
|
345
|
+
return nil
|
|
346
|
+
end
|
|
347
|
+
if not (typeof(colors) == "ColorSequence") and #colors == 0 then
|
|
348
|
+
return nil
|
|
349
|
+
end
|
|
350
|
+
local color = if typeof(colors) == "ColorSequence" then colors else self:buildColorSequence(colors, value.stops)
|
|
351
|
+
return {
|
|
352
|
+
Color = color,
|
|
353
|
+
Transparency = self:buildTransparencySequence(value.transparency),
|
|
354
|
+
Rotation = value.rotation,
|
|
355
|
+
Offset = value.offset,
|
|
356
|
+
}
|
|
357
|
+
end
|
|
358
|
+
function CssHelper:buildColorSequence(colors, stops)
|
|
359
|
+
if #colors == 1 then
|
|
360
|
+
return ColorSequence.new(colors[1])
|
|
361
|
+
end
|
|
362
|
+
local lastIndex = #colors - 1
|
|
363
|
+
-- ▼ ReadonlyArray.map ▼
|
|
364
|
+
local _newValue = table.create(#colors)
|
|
365
|
+
local _callback = function(color, index)
|
|
366
|
+
local _result = stops
|
|
367
|
+
if _result ~= nil then
|
|
368
|
+
_result = _result[index + 1]
|
|
369
|
+
end
|
|
370
|
+
local time = if _result ~= nil then math.clamp(stops[index + 1], 0, 1) else index / lastIndex
|
|
371
|
+
if index == 0 then
|
|
372
|
+
time = 0
|
|
373
|
+
elseif index == lastIndex then
|
|
374
|
+
time = 1
|
|
375
|
+
end
|
|
376
|
+
return {
|
|
377
|
+
time = time,
|
|
378
|
+
color = color,
|
|
379
|
+
index = index,
|
|
380
|
+
}
|
|
381
|
+
end
|
|
382
|
+
for _k, _v in colors do
|
|
383
|
+
_newValue[_k] = _callback(_v, _k - 1, colors)
|
|
384
|
+
end
|
|
385
|
+
-- ▲ ReadonlyArray.map ▲
|
|
386
|
+
local entries = _newValue
|
|
387
|
+
table.sort(entries, function(a, b)
|
|
388
|
+
if a.time ~= b.time then
|
|
389
|
+
return a.time < b.time
|
|
390
|
+
end
|
|
391
|
+
return a.index < b.index
|
|
392
|
+
end)
|
|
393
|
+
-- ▼ ReadonlyArray.map ▼
|
|
394
|
+
local _newValue_1 = table.create(#entries)
|
|
395
|
+
local _callback_1 = function(entry)
|
|
396
|
+
return ColorSequenceKeypoint.new(entry.time, entry.color)
|
|
397
|
+
end
|
|
398
|
+
for _k, _v in entries do
|
|
399
|
+
_newValue_1[_k] = _callback_1(_v, _k - 1, entries)
|
|
400
|
+
end
|
|
401
|
+
-- ▲ ReadonlyArray.map ▲
|
|
402
|
+
return ColorSequence.new(_newValue_1)
|
|
403
|
+
end
|
|
404
|
+
function CssHelper:buildTransparencySequence(value)
|
|
405
|
+
if value == nil then
|
|
406
|
+
return nil
|
|
407
|
+
end
|
|
408
|
+
local _value = value
|
|
409
|
+
if typeof(_value) == "NumberSequence" then
|
|
410
|
+
return value
|
|
411
|
+
end
|
|
412
|
+
return NumberSequence.new(math.clamp(value, 0, 1))
|
|
413
|
+
end
|
|
344
414
|
end
|
|
345
415
|
return {
|
|
346
416
|
CssHelper = CssHelper,
|
|
@@ -84,7 +84,6 @@ do
|
|
|
84
84
|
rootIndex = index,
|
|
85
85
|
}
|
|
86
86
|
table.insert(surfaces, _arg0)
|
|
87
|
-
-- Don't recurse into another render surface.
|
|
88
87
|
continue
|
|
89
88
|
end
|
|
90
89
|
visit(child)
|
|
@@ -117,11 +116,9 @@ do
|
|
|
117
116
|
if a.object.ZIndex ~= b.object.ZIndex then
|
|
118
117
|
return a.object.ZIndex < b.object.ZIndex
|
|
119
118
|
end
|
|
120
|
-
-- Preserve sibling order.
|
|
121
119
|
return a.siblingIndex < b.siblingIndex
|
|
122
120
|
end)
|
|
123
121
|
for _, child in children do
|
|
124
|
-
-- Parent renders before its children.
|
|
125
122
|
local _result = result
|
|
126
123
|
local _object = child.object
|
|
127
124
|
table.insert(_result, _object)
|
|
@@ -63,8 +63,6 @@ do
|
|
|
63
63
|
if props.AutomaticSize ~= nil then
|
|
64
64
|
return props.AutomaticSize
|
|
65
65
|
end
|
|
66
|
-
-- "Auto" behaves like an unset dimension for the purposes of deciding
|
|
67
|
-
-- which axes get AutomaticSize, but still forces that axis to 0 in GetSize.
|
|
68
66
|
local width = if props.width == "Auto" then nil else props.width
|
|
69
67
|
local height = if props.height == "Auto" then nil else props.height
|
|
70
68
|
local _condition = props.Size ~= nil
|
|
@@ -39,9 +39,6 @@ do
|
|
|
39
39
|
end
|
|
40
40
|
local isNone = props.spacing == "None"
|
|
41
41
|
local key = if props.spacing ~= nil and props.spacing ~= "None" then props.spacing else (defaultSpacing or theme.default.spacing)
|
|
42
|
-
-- tier 3: a scale-indexed map picks the quad for the active key
|
|
43
|
-
-- (falling through to tiers 1/2 if that key isn't defined in the
|
|
44
|
-
-- map); a plain quad applies regardless of key.
|
|
45
42
|
local _result
|
|
46
43
|
if isNone or componentPadding == nil then
|
|
47
44
|
_result = nil
|
|
@@ -37,7 +37,6 @@ do
|
|
|
37
37
|
function TypographyHelper:getClosestTypography(typography, scale)
|
|
38
38
|
local _scale = scale
|
|
39
39
|
local scaleIndex = (table.find(ScaleSizes, _scale) or 0) - 1
|
|
40
|
-
-- Prefer the exact scale, then progressively smaller scales.
|
|
41
40
|
do
|
|
42
41
|
local index = scaleIndex
|
|
43
42
|
local _shouldIncrement = false
|
|
@@ -56,7 +55,6 @@ do
|
|
|
56
55
|
end
|
|
57
56
|
end
|
|
58
57
|
end
|
|
59
|
-
-- If no smaller scale exists, use the nearest larger scale.
|
|
60
58
|
do
|
|
61
59
|
local index = scaleIndex + 1
|
|
62
60
|
local _shouldIncrement = false
|
|
@@ -28,3 +28,10 @@ export type CssBoxShadow = {
|
|
|
28
28
|
export type CssPadding = CssQuad;
|
|
29
29
|
export type ScaledCssPadding = CssPadding | ScaleSizeValue<CssPadding>;
|
|
30
30
|
export type ResponsiveCssSize = CssSize | CssBreakpointSize;
|
|
31
|
+
export type CssBackgroundGradient = {
|
|
32
|
+
colors: Color3[] | ColorSequence;
|
|
33
|
+
stops?: number[];
|
|
34
|
+
rotation?: number;
|
|
35
|
+
offset?: Vector2;
|
|
36
|
+
transparency?: number | NumberSequence;
|
|
37
|
+
};
|
|
@@ -1,21 +1 @@
|
|
|
1
1
|
-- Compiled with roblox-ts v3.0.0
|
|
2
|
-
-- The one CSS calc() shape supported on top of CssSize: a percent term
|
|
3
|
-
-- plus/minus a pixel term (e.g. "100% - 50px"), which maps directly onto
|
|
4
|
-
-- UDim(scale, offset) — no general calc() parser needed for anything beyond
|
|
5
|
-
-- this two-term form. Deliberately kept as its own type rather than folded
|
|
6
|
-
-- directly into CssSize: CssSize is composed multiple times over in CssQuad/
|
|
7
|
-
-- CssDual (a 4-term CssQuad is `${CssSize} ${CssSize} ${CssSize} ${CssSize}`),
|
|
8
|
-
-- so widening CssSize itself multiplies out through every one of those
|
|
9
|
-
-- combinations — doing so was observed to blow past TypeScript's template-
|
|
10
|
-
-- literal complexity limit ("union type that is too complex to represent")
|
|
11
|
-
-- at unrelated call sites that spread a large props object containing
|
|
12
|
-
-- several CssQuad-shaped fields (e.g. Button.tsx's `<BoxShadow {...props} />`).
|
|
13
|
-
-- Use CssCalcSize only where a calc() term is actually needed (currently
|
|
14
|
-
-- just CssPosition.width) rather than everywhere CssSize appears.
|
|
15
|
-
-- absolute pixel corner coordinates for Rect.new(minX, minY, maxX, maxY)-style slicing,
|
|
16
|
-
-- e.g. Roblox's SliceCenter — not a CSS border-image-slice edge-inset shorthand, since
|
|
17
|
-
-- Roblox has no intrinsic-image-size equivalent to derive corners from an inset alone
|
|
18
|
-
-- A CssPadding quad, or a scale-key-indexed map of quads (e.g. a component's
|
|
19
|
-
-- theme.components.X.padding tier, which can pick a different quad shape per
|
|
20
|
-
-- spacing scale key the same way theme.components.X.spacing does for the
|
|
21
|
-
-- numeric tier).
|
|
@@ -2,8 +2,6 @@
|
|
|
2
2
|
local TS = _G[script]
|
|
3
3
|
local React = TS.import(script, TS.getModule(script, "@rbxts", "react"))
|
|
4
4
|
local HttpService = TS.import(script, TS.getModule(script, "@rbxts", "services")).HttpService
|
|
5
|
-
-- This registry is used to keep a global map of GuiObjects => React components
|
|
6
|
-
-- For example Droppable zones use this to register themselves
|
|
7
5
|
local DroppableRegistryKey = {
|
|
8
6
|
name = "Droppable",
|
|
9
7
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Binding } from "@rbxts/react";
|
|
2
|
-
import { ScaleSize, CssShadow, ButtonFlag, CssDual, CssSliceInset, CssSize, CssCalcSize } from "../Interfaces/";
|
|
2
|
+
import { ScaleSize, CssShadow, ButtonFlag, CssDual, CssSliceInset, CssSize, CssCalcSize, CssBackgroundGradient } from "../Interfaces/";
|
|
3
3
|
export interface TypographyStyle {
|
|
4
4
|
font: Enum.Font;
|
|
5
5
|
size: Enum.FontSize;
|
|
@@ -18,6 +18,7 @@ export interface IntentScheme {
|
|
|
18
18
|
boxShadow?: CssShadow;
|
|
19
19
|
typography?: Partial<TypographyStyle>;
|
|
20
20
|
backgroundImage?: Partial<CssBackgroundImage>;
|
|
21
|
+
backgroundGradient?: Partial<CssBackgroundGradient>;
|
|
21
22
|
}
|
|
22
23
|
export interface IntentColors extends Partial<Record<ButtonFlag, IntentScheme>> {
|
|
23
24
|
default: IntentScheme;
|
|
@@ -46,3 +47,9 @@ export interface CssPosition {
|
|
|
46
47
|
zIndex?: number;
|
|
47
48
|
width?: CssCalcSize;
|
|
48
49
|
}
|
|
50
|
+
export interface CssCornerRadius {
|
|
51
|
+
topLeft?: CssSize;
|
|
52
|
+
topRight?: CssSize;
|
|
53
|
+
bottomLeft?: CssSize;
|
|
54
|
+
bottomRight?: CssSize;
|
|
55
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { CssShadow, CssSize, ScaledCssPadding, Breakpoint, BreakpointValue, ScaleSizeValue, ScaleSize, Intent, IconSet, TextVariant, PositionElementProps, CssBoxShadow } from "../Interfaces/";
|
|
2
|
-
import { TypographyStyle, ScaledTypographyStyle, IntentScheme, IntentColors, InlineIntentColors, CssBackgroundImage, CssPosition } from "./theme.style";
|
|
1
|
+
import { CssShadow, CssSize, ScaledCssPadding, Breakpoint, BreakpointValue, ScaleSizeValue, ScaleSize, Intent, IconSet, TextVariant, PositionElementProps, CssBoxShadow, CssBackgroundGradient } from "../Interfaces/";
|
|
2
|
+
import { TypographyStyle, ScaledTypographyStyle, IntentScheme, IntentColors, InlineIntentColors, CssBackgroundImage, CssPosition, CssCornerRadius } from "./theme.style";
|
|
3
3
|
export interface ThemeTemplate {
|
|
4
4
|
colors: {
|
|
5
5
|
intents: Record<Intent, IntentColors>;
|
|
@@ -52,6 +52,7 @@ export interface ThemeTemplate {
|
|
|
52
52
|
padding?: ScaledCssPadding;
|
|
53
53
|
boxShadow?: CssShadow;
|
|
54
54
|
backgroundImage?: CssBackgroundImage;
|
|
55
|
+
backgroundGradient?: CssBackgroundGradient;
|
|
55
56
|
intents?: Partial<Record<Intent, InlineIntentColors>>;
|
|
56
57
|
};
|
|
57
58
|
button: {
|
|
@@ -71,6 +72,7 @@ export interface ThemeTemplate {
|
|
|
71
72
|
cornerRadius: CssSize;
|
|
72
73
|
typography?: Partial<TypographyStyle> | ScaledTypographyStyle;
|
|
73
74
|
backgroundImage?: CssBackgroundImage;
|
|
75
|
+
backgroundGradient?: CssBackgroundGradient;
|
|
74
76
|
placeholder?: Partial<TypographyStyle> | ScaledTypographyStyle;
|
|
75
77
|
iconColor?: Color3;
|
|
76
78
|
};
|
|
@@ -79,6 +81,7 @@ export interface ThemeTemplate {
|
|
|
79
81
|
borderThickness: number;
|
|
80
82
|
cornerRadius: CssSize;
|
|
81
83
|
backgroundImage?: CssBackgroundImage;
|
|
84
|
+
backgroundGradient?: CssBackgroundGradient;
|
|
82
85
|
dropDownBackgroundColor: Color3;
|
|
83
86
|
typography?: Partial<TypographyStyle> | ScaledTypographyStyle;
|
|
84
87
|
intents?: Partial<Record<Intent, InlineIntentColors>>;
|
|
@@ -105,6 +108,7 @@ export interface ThemeTemplate {
|
|
|
105
108
|
spacing?: ScaleSizeValue<number>;
|
|
106
109
|
padding?: ScaledCssPadding;
|
|
107
110
|
backgroundImage?: CssBackgroundImage;
|
|
111
|
+
backgroundGradient?: CssBackgroundGradient;
|
|
108
112
|
};
|
|
109
113
|
switch: {
|
|
110
114
|
width: CssSize;
|
|
@@ -135,6 +139,7 @@ export interface ThemeTemplate {
|
|
|
135
139
|
borderColor: Color3;
|
|
136
140
|
backgroundColor: Color3;
|
|
137
141
|
backgroundImage?: CssBackgroundImage;
|
|
142
|
+
backgroundGradient?: CssBackgroundGradient;
|
|
138
143
|
borderThickness: number;
|
|
139
144
|
cornerRadius: CssSize;
|
|
140
145
|
spacing?: ScaleSizeValue<number>;
|
|
@@ -148,6 +153,7 @@ export interface ThemeTemplate {
|
|
|
148
153
|
spacing?: ScaleSizeValue<number>;
|
|
149
154
|
padding?: ScaledCssPadding;
|
|
150
155
|
backgroundImage?: CssBackgroundImage;
|
|
156
|
+
backgroundGradient?: CssBackgroundGradient;
|
|
151
157
|
};
|
|
152
158
|
button: {
|
|
153
159
|
borderThickness: number;
|
|
@@ -224,6 +230,7 @@ export interface ThemeTemplate {
|
|
|
224
230
|
cornerRadius: CssSize;
|
|
225
231
|
header: {
|
|
226
232
|
borderThickness?: number;
|
|
233
|
+
cornerRadius?: CssCornerRadius;
|
|
227
234
|
spacing?: ScaleSizeValue<number>;
|
|
228
235
|
padding?: ScaledCssPadding;
|
|
229
236
|
intents?: Partial<Record<Intent, InlineIntentColors>>;
|
|
@@ -231,6 +238,7 @@ export interface ThemeTemplate {
|
|
|
231
238
|
};
|
|
232
239
|
footer: {
|
|
233
240
|
borderThickness?: number;
|
|
241
|
+
cornerRadius?: CssCornerRadius;
|
|
234
242
|
spacing?: ScaleSizeValue<number>;
|
|
235
243
|
padding?: ScaledCssPadding;
|
|
236
244
|
intents?: Partial<Record<Intent, InlineIntentColors>>;
|
|
@@ -267,6 +275,40 @@ export interface ThemeTemplate {
|
|
|
267
275
|
aspectRatio?: number;
|
|
268
276
|
};
|
|
269
277
|
};
|
|
278
|
+
progressBar: {
|
|
279
|
+
height: ScaleSizeValue<CssSize>;
|
|
280
|
+
animation: {
|
|
281
|
+
duration: number;
|
|
282
|
+
};
|
|
283
|
+
header: {
|
|
284
|
+
spacing?: ScaleSizeValue<number>;
|
|
285
|
+
label: {
|
|
286
|
+
typography?: Partial<TypographyStyle> | ScaledTypographyStyle;
|
|
287
|
+
};
|
|
288
|
+
value: {
|
|
289
|
+
typography?: Partial<TypographyStyle> | ScaledTypographyStyle;
|
|
290
|
+
};
|
|
291
|
+
};
|
|
292
|
+
track: {
|
|
293
|
+
backgroundColor: Color3;
|
|
294
|
+
backgroundTransparency: number;
|
|
295
|
+
borderColor: Color3;
|
|
296
|
+
borderThickness: number;
|
|
297
|
+
cornerRadius: CssSize;
|
|
298
|
+
backgroundImage?: CssBackgroundImage;
|
|
299
|
+
backgroundGradient?: CssBackgroundGradient;
|
|
300
|
+
};
|
|
301
|
+
fill: {
|
|
302
|
+
cornerRadius: CssSize;
|
|
303
|
+
intents?: Partial<Record<Intent, InlineIntentColors>>;
|
|
304
|
+
stripe?: {
|
|
305
|
+
enabled: boolean;
|
|
306
|
+
image?: Omit<Partial<CssBackgroundImage>, "size">;
|
|
307
|
+
duration?: number;
|
|
308
|
+
direction?: number;
|
|
309
|
+
};
|
|
310
|
+
};
|
|
311
|
+
};
|
|
270
312
|
toast: {
|
|
271
313
|
width: CssSize;
|
|
272
314
|
fadeDuration: number;
|