@rbxts/react-clean-ui 1.2.2 → 1.2.4

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.
Files changed (51) hide show
  1. package/out/Components/Chart/Pie.luau +0 -1
  2. package/out/Components/Decorator/Gradient.d.ts +8 -0
  3. package/out/Components/Decorator/Gradient.luau +23 -0
  4. package/out/Components/Decorator/index.d.ts +1 -0
  5. package/out/Components/Decorator/init.luau +3 -0
  6. package/out/Components/Input/Button.luau +5 -1
  7. package/out/Components/Input/Checkbox.luau +6 -2
  8. package/out/Components/Input/HoverButton.luau +0 -2
  9. package/out/Components/Input/Input.luau +8 -6
  10. package/out/Components/Input/Select.d.ts +2 -1
  11. package/out/Components/Input/Select.luau +10 -11
  12. package/out/Components/Input/Slider.luau +0 -24
  13. package/out/Components/Input/Switch.luau +0 -2
  14. package/out/Components/Interaction/Modal.luau +0 -14
  15. package/out/Components/Interaction/Tooltip.luau +0 -1
  16. package/out/Components/Layout/Container.d.ts +2 -0
  17. package/out/Components/Layout/Container.luau +4 -1
  18. package/out/Components/Layout/Grid.d.ts +10 -0
  19. package/out/Components/Layout/Grid.luau +172 -0
  20. package/out/Components/Layout/Group.luau +38 -33
  21. package/out/Components/Layout/Pagination.luau +0 -5
  22. package/out/Components/Layout/Tabs.d.ts +2 -1
  23. package/out/Components/Layout/Tabs.luau +12 -33
  24. package/out/Components/Layout/index.d.ts +1 -0
  25. package/out/Components/Layout/init.luau +3 -0
  26. package/out/Components/Surface/Box.d.ts +2 -1
  27. package/out/Components/Surface/Box.luau +3 -0
  28. package/out/Components/Surface/Card.luau +2 -103
  29. package/out/Components/Surface/ProgressBar.d.ts +14 -0
  30. package/out/Components/Surface/ProgressBar.luau +230 -0
  31. package/out/Components/Surface/index.d.ts +1 -0
  32. package/out/Components/Surface/init.luau +3 -0
  33. package/out/Components/Typography/Text.luau +0 -6
  34. package/out/Contexts/modal.context.luau +0 -3
  35. package/out/Helpers/color.helper.luau +28 -0
  36. package/out/Helpers/css.helper.d.ts +4 -1
  37. package/out/Helpers/css.helper.luau +76 -6
  38. package/out/Helpers/gui.helper.luau +0 -3
  39. package/out/Helpers/size.helper.luau +0 -2
  40. package/out/Helpers/spacing.helper.luau +0 -3
  41. package/out/Helpers/typography.helper.luau +0 -2
  42. package/out/Interfaces/css.types.d.ts +7 -0
  43. package/out/Interfaces/css.types.luau +0 -20
  44. package/out/Providers/registry.provider.luau +0 -2
  45. package/out/Theme/theme.style.d.ts +2 -1
  46. package/out/Theme/theme.template.d.ts +41 -1
  47. package/out/Theme/themes/dark.theme.luau +122 -0
  48. package/out/Theme/themes/default.theme.luau +80 -0
  49. package/out/Theme/themes/sandstone.theme.luau +70 -0
  50. package/out/Theme/themes/wooden.theme.luau +73 -0
  51. 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
+ }
@@ -1,3 +1,4 @@
1
1
  export * from './Box';
2
2
  export * from './Card';
3
3
  export * from './Icon';
4
+ export * from './ProgressBar';
@@ -10,4 +10,7 @@ end
10
10
  for _k, _v in TS.import(script, script, "Icon") or {} do
11
11
  exports[_k] = _v
12
12
  end
13
+ for _k, _v in TS.import(script, script, "ProgressBar") or {} do
14
+ exports[_k] = _v
15
+ end
13
16
  return exports
@@ -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;
@@ -1,4 +1,4 @@
1
- import { CssShadow, CssSize, ScaledCssPadding, Breakpoint, BreakpointValue, ScaleSizeValue, ScaleSize, Intent, IconSet, TextVariant, PositionElementProps, CssBoxShadow } from "../Interfaces/";
1
+ import { CssShadow, CssSize, ScaledCssPadding, Breakpoint, BreakpointValue, ScaleSizeValue, ScaleSize, Intent, IconSet, TextVariant, PositionElementProps, CssBoxShadow, CssBackgroundGradient } from "../Interfaces/";
2
2
  import { TypographyStyle, ScaledTypographyStyle, IntentScheme, IntentColors, InlineIntentColors, CssBackgroundImage, CssPosition } from "./theme.style";
3
3
  export interface ThemeTemplate {
4
4
  colors: {
@@ -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;
@@ -267,6 +273,40 @@ export interface ThemeTemplate {
267
273
  aspectRatio?: number;
268
274
  };
269
275
  };
276
+ progressBar: {
277
+ height: ScaleSizeValue<CssSize>;
278
+ animation: {
279
+ duration: number;
280
+ };
281
+ header: {
282
+ spacing?: ScaleSizeValue<number>;
283
+ label: {
284
+ typography?: Partial<TypographyStyle> | ScaledTypographyStyle;
285
+ };
286
+ value: {
287
+ typography?: Partial<TypographyStyle> | ScaledTypographyStyle;
288
+ };
289
+ };
290
+ track: {
291
+ backgroundColor: Color3;
292
+ backgroundTransparency: number;
293
+ borderColor: Color3;
294
+ borderThickness: number;
295
+ cornerRadius: CssSize;
296
+ backgroundImage?: CssBackgroundImage;
297
+ backgroundGradient?: CssBackgroundGradient;
298
+ };
299
+ fill: {
300
+ cornerRadius: CssSize;
301
+ intents?: Partial<Record<Intent, InlineIntentColors>>;
302
+ stripe?: {
303
+ enabled: boolean;
304
+ image?: Omit<Partial<CssBackgroundImage>, "size">;
305
+ duration?: number;
306
+ direction?: number;
307
+ };
308
+ };
309
+ };
270
310
  toast: {
271
311
  width: CssSize;
272
312
  fadeDuration: number;