@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.
- 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 +2 -103
- 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 +2 -1
- package/out/Theme/theme.template.d.ts +41 -1
- 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
|
@@ -1,27 +1,32 @@
|
|
|
1
1
|
-- Compiled with roblox-ts v3.0.0
|
|
2
2
|
local TS = _G[script]
|
|
3
3
|
local React = TS.import(script, TS.getModule(script, "@rbxts", "react"))
|
|
4
|
-
-- import { HttpService } from "@rbxts/services";
|
|
5
4
|
local RegistryContext = TS.import(script, script.Parent.Parent.Parent, "Providers").RegistryContext
|
|
6
5
|
local GroupContext = React.createContext(nil)
|
|
6
|
+
local nextFallbackElementId = 0
|
|
7
7
|
local function GroupElement(props)
|
|
8
8
|
local registry = React.useContext(RegistryContext)
|
|
9
9
|
local context = React.useContext(GroupContext)
|
|
10
|
-
local
|
|
11
|
-
if
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
10
|
+
local idRef = React.useRef()
|
|
11
|
+
if idRef.current == nil then
|
|
12
|
+
nextFallbackElementId += 1
|
|
13
|
+
local _result = registry
|
|
14
|
+
if _result ~= nil then
|
|
15
|
+
_result = _result.GetNextId()
|
|
16
|
+
end
|
|
17
|
+
local _condition = _result
|
|
18
|
+
if _condition == nil then
|
|
19
|
+
_condition = `group-element-{nextFallbackElementId}`
|
|
20
|
+
end
|
|
21
|
+
idRef.current = _condition
|
|
17
22
|
end
|
|
18
|
-
local id =
|
|
23
|
+
local id = idRef.current
|
|
19
24
|
local enabled = props.enabled == true and context ~= nil
|
|
20
25
|
local _exp = function()
|
|
21
26
|
if not enabled then
|
|
22
|
-
local
|
|
23
|
-
if
|
|
24
|
-
|
|
27
|
+
local _result = context
|
|
28
|
+
if _result ~= nil then
|
|
29
|
+
_result.removeElement(id)
|
|
25
30
|
end
|
|
26
31
|
return nil
|
|
27
32
|
end
|
|
@@ -29,54 +34,54 @@ local function GroupElement(props)
|
|
|
29
34
|
context.removeElement(id)
|
|
30
35
|
end
|
|
31
36
|
end
|
|
32
|
-
local
|
|
33
|
-
if
|
|
34
|
-
|
|
37
|
+
local _result = context
|
|
38
|
+
if _result ~= nil then
|
|
39
|
+
_result = _result.removeElement
|
|
35
40
|
end
|
|
36
|
-
React.useEffect(_exp, { enabled,
|
|
41
|
+
React.useEffect(_exp, { enabled, _result })
|
|
37
42
|
if not enabled then
|
|
38
43
|
return props.children
|
|
39
44
|
end
|
|
45
|
+
local _result_1 = props.padding
|
|
46
|
+
if _result_1 ~= nil then
|
|
47
|
+
_result_1 = _result_1.left
|
|
48
|
+
end
|
|
49
|
+
local _condition = _result_1
|
|
50
|
+
if _condition == nil then
|
|
51
|
+
_condition = 0
|
|
52
|
+
end
|
|
40
53
|
local _result_2 = props.padding
|
|
41
54
|
if _result_2 ~= nil then
|
|
42
|
-
_result_2 = _result_2.
|
|
55
|
+
_result_2 = _result_2.right
|
|
43
56
|
end
|
|
44
57
|
local _condition_1 = _result_2
|
|
45
58
|
if _condition_1 == nil then
|
|
46
59
|
_condition_1 = 0
|
|
47
60
|
end
|
|
61
|
+
local horizontalPadding = _condition + _condition_1
|
|
48
62
|
local _result_3 = props.padding
|
|
49
63
|
if _result_3 ~= nil then
|
|
50
|
-
_result_3 = _result_3.
|
|
64
|
+
_result_3 = _result_3.top
|
|
51
65
|
end
|
|
52
66
|
local _condition_2 = _result_3
|
|
53
67
|
if _condition_2 == nil then
|
|
54
68
|
_condition_2 = 0
|
|
55
69
|
end
|
|
56
|
-
local horizontalPadding = _condition_1 + _condition_2
|
|
57
70
|
local _result_4 = props.padding
|
|
58
71
|
if _result_4 ~= nil then
|
|
59
|
-
_result_4 = _result_4.
|
|
72
|
+
_result_4 = _result_4.bottom
|
|
60
73
|
end
|
|
61
74
|
local _condition_3 = _result_4
|
|
62
75
|
if _condition_3 == nil then
|
|
63
76
|
_condition_3 = 0
|
|
64
77
|
end
|
|
65
|
-
local
|
|
66
|
-
if _result_5 ~= nil then
|
|
67
|
-
_result_5 = _result_5.bottom
|
|
68
|
-
end
|
|
69
|
-
local _condition_4 = _result_5
|
|
70
|
-
if _condition_4 == nil then
|
|
71
|
-
_condition_4 = 0
|
|
72
|
-
end
|
|
73
|
-
local verticalPadding = _condition_3 + _condition_4
|
|
78
|
+
local verticalPadding = _condition_2 + _condition_3
|
|
74
79
|
local _attributes = {}
|
|
75
|
-
local
|
|
76
|
-
if
|
|
77
|
-
|
|
80
|
+
local _condition_4 = props.name
|
|
81
|
+
if _condition_4 == nil then
|
|
82
|
+
_condition_4 = "GroupElement"
|
|
78
83
|
end
|
|
79
|
-
_attributes.key =
|
|
84
|
+
_attributes.key = _condition_4
|
|
80
85
|
_attributes.BackgroundTransparency = 1
|
|
81
86
|
_attributes.AutomaticSize = Enum.AutomaticSize.XY
|
|
82
87
|
_attributes.Change = {
|
|
@@ -51,8 +51,6 @@ local function computePaginationItems(page, totalPages, siblingCount)
|
|
|
51
51
|
local showLeftEllipsis = leftSiblingIndex > 2
|
|
52
52
|
local showRightEllipsis = rightSiblingIndex < pageCount - 1
|
|
53
53
|
if not showLeftEllipsis and showRightEllipsis then
|
|
54
|
-
-- Near the start: no left ellipsis needed, so extend the leading run of
|
|
55
|
-
-- numbers to keep the total item count constant.
|
|
56
54
|
local leftItemCount = siblings * 2 + 3
|
|
57
55
|
local items = {}
|
|
58
56
|
do
|
|
@@ -76,8 +74,6 @@ local function computePaginationItems(page, totalPages, siblingCount)
|
|
|
76
74
|
return items
|
|
77
75
|
end
|
|
78
76
|
if showLeftEllipsis and not showRightEllipsis then
|
|
79
|
-
-- Near the end: no right ellipsis needed, so extend the trailing run of
|
|
80
|
-
-- numbers to keep the total item count constant.
|
|
81
77
|
local rightItemCount = siblings * 2 + 3
|
|
82
78
|
local items = { 1, "ellipsis" }
|
|
83
79
|
do
|
|
@@ -98,7 +94,6 @@ local function computePaginationItems(page, totalPages, siblingCount)
|
|
|
98
94
|
end
|
|
99
95
|
return items
|
|
100
96
|
end
|
|
101
|
-
-- Both ellipses shown (the normal middle case) — unchanged from before.
|
|
102
97
|
local items = { 1, "ellipsis" }
|
|
103
98
|
do
|
|
104
99
|
local value = leftSiblingIndex
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React from "@rbxts/react";
|
|
2
|
-
import { PaddingProps, ScalableElementProps } from "../../Interfaces";
|
|
2
|
+
import { CssBackgroundGradient, PaddingProps, ScalableElementProps } from "../../Interfaces";
|
|
3
3
|
import { CssBackgroundImage } from "../../Theme";
|
|
4
4
|
interface TabTitleProps extends PaddingProps {
|
|
5
5
|
value: string;
|
|
@@ -17,6 +17,7 @@ interface TabsListProps extends ScalableElementProps {
|
|
|
17
17
|
declare const TabsList: React.ForwardRefExoticComponent<TabsListProps & React.RefAttributes<ImageLabel>>;
|
|
18
18
|
interface TabsBodyProps extends ScalableElementProps {
|
|
19
19
|
backgroundImage?: CssBackgroundImage;
|
|
20
|
+
backgroundGradient?: CssBackgroundGradient;
|
|
20
21
|
children?: React.ReactNode;
|
|
21
22
|
}
|
|
22
23
|
declare const TabsBody: React.ForwardRefExoticComponent<TabsBodyProps & React.RefAttributes<ImageLabel>>;
|
|
@@ -9,6 +9,7 @@ local CleanThemeContext = TS.import(script, script.Parent.Parent.Parent, "Contex
|
|
|
9
9
|
local _Decorator = TS.import(script, script.Parent.Parent, "Decorator")
|
|
10
10
|
local BoxShadow = _Decorator.BoxShadow
|
|
11
11
|
local Corners = _Decorator.Corners
|
|
12
|
+
local Gradient = _Decorator.Gradient
|
|
12
13
|
local Padding = _Decorator.Padding
|
|
13
14
|
local _Helpers = TS.import(script, script.Parent.Parent.Parent, "Helpers")
|
|
14
15
|
local ColorHelper = _Helpers.ColorHelper
|
|
@@ -18,10 +19,6 @@ local TypographyHelper = _Helpers.TypographyHelper
|
|
|
18
19
|
local _HoverButton = TS.import(script, script.Parent.Parent, "Input", "HoverButton")
|
|
19
20
|
local HoverButton = _HoverButton.HoverButton
|
|
20
21
|
local HoverButtonContext = _HoverButton.HoverButtonContext
|
|
21
|
-
-- Selection only — Tabs.List/Tabs.Body/Tabs.Title/Tabs.Content each render
|
|
22
|
-
-- themselves for real (see Card.tsx's CardHeader/CardFooter for the same
|
|
23
|
-
-- "Root provides Context, subparts consume it independently" pattern), so
|
|
24
|
-
-- there's nothing here to scan or harvest from children.
|
|
25
22
|
local TabsContext = React.createContext({
|
|
26
23
|
selected = nil,
|
|
27
24
|
setSelected = function() end,
|
|
@@ -57,23 +54,20 @@ local function TabButtonContent(props)
|
|
|
57
54
|
typography = TypographyHelper:getTypography(theme, nil, intent.typography),
|
|
58
55
|
}))
|
|
59
56
|
end
|
|
60
|
-
-- The real per-tab button — derives its own default/hover/focus color scheme
|
|
61
|
-
-- from the theme (same per-instance derivation Card.Header/Card.Footer use,
|
|
62
|
-
-- not hoisted to Root) and drives selection itself via TabsContext.
|
|
63
57
|
local function TabTitle(props)
|
|
64
58
|
local theme = React.useContext(CleanThemeContext)
|
|
65
59
|
local _binding = React.useContext(TabsContext)
|
|
66
60
|
local selected = _binding.selected
|
|
67
61
|
local setSelected = _binding.setSelected
|
|
68
62
|
local isSelected = selected == props.value
|
|
69
|
-
-- The first-mounted Tabs.Title claims the selection if none is set yet,
|
|
70
|
-
-- preserving "first tab selected by default" now that nothing scans the
|
|
71
|
-
-- tab list up front. Known limitation: if the currently-selected tab's
|
|
72
|
-
-- Tabs.Title unmounts, selection isn't automatically reassigned.
|
|
73
63
|
React.useEffect(function()
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
64
|
+
setSelected(function(current)
|
|
65
|
+
local _condition = current
|
|
66
|
+
if _condition == nil then
|
|
67
|
+
_condition = props.value
|
|
68
|
+
end
|
|
69
|
+
return _condition
|
|
70
|
+
end)
|
|
77
71
|
end, {})
|
|
78
72
|
local buttonDefault = ColorHelper:getIntentColors(theme, "primary", "default", theme.components.tabs.button.intents)
|
|
79
73
|
local buttonHover = ColorHelper:getIntentColors(theme, "primary", "hover", theme.components.tabs.button.intents)
|
|
@@ -130,14 +124,6 @@ local function TabTitle(props)
|
|
|
130
124
|
},
|
|
131
125
|
}, React.createElement(TabButtonContent, _attributes))
|
|
132
126
|
end
|
|
133
|
-
-- Always mounted — visibility is toggled rather than the panel being
|
|
134
|
-
-- unmounted/remounted, so per-tab local state (e.g. a Scroller's scroll
|
|
135
|
-
-- position) survives switching tabs. Roblox excludes a GuiObject with
|
|
136
|
-
-- Visible=false from its ancestors' AutomaticSize/UIListLayout
|
|
137
|
-
-- content-size calculations, so the hidden panels don't inflate Tabs.Body's
|
|
138
|
-
-- own AutomaticSize; since only one panel is ever visible at a time, the
|
|
139
|
-
-- default (unset) Position/AnchorPoint every panel shares never causes a
|
|
140
|
-
-- visible overlap either.
|
|
141
127
|
local function TabContent(props)
|
|
142
128
|
local _binding = React.useContext(TabsContext)
|
|
143
129
|
local selected = _binding.selected
|
|
@@ -163,6 +149,8 @@ local TabsList = React.forwardRef(function(props, ref)
|
|
|
163
149
|
_attributes.backgroundImage = theme.components.tabs.list.backgroundImage
|
|
164
150
|
return React.createElement(Container, _attributes, React.createElement(Corners, {
|
|
165
151
|
radius = theme.components.tabs.list.cornerRadius,
|
|
152
|
+
}), React.createElement(Gradient, {
|
|
153
|
+
value = theme.components.tabs.list.backgroundGradient,
|
|
166
154
|
}), React.createElement(Padding, {
|
|
167
155
|
resolvedPadding = SpacingHelper:GetResolvedPadding(theme, {}, theme.components.tabs.list.spacing, theme.components.tabs.list.padding),
|
|
168
156
|
}), React.createElement(HStack, nil, props.children))
|
|
@@ -183,19 +171,10 @@ local TabsBody = React.forwardRef(function(props, ref)
|
|
|
183
171
|
resolvedPadding = SpacingHelper:GetResolvedPadding(theme, {}, theme.components.tabs.spacing, theme.components.tabs.padding),
|
|
184
172
|
}), React.createElement(Corners, {
|
|
185
173
|
radius = theme.components.tabs.cornerRadius,
|
|
174
|
+
}), React.createElement(Gradient, {
|
|
175
|
+
value = props.backgroundGradient or theme.components.tabs.backgroundGradient,
|
|
186
176
|
}), props.children)
|
|
187
177
|
end)
|
|
188
|
-
-- Root doesn't render a real Roblox Instance of its own (just a Context
|
|
189
|
-
-- Provider around a VStack, itself just a Fragment) — see Group.tsx for the
|
|
190
|
-
-- same shape. It's still wrapped in React.forwardRef, not a plain function,
|
|
191
|
-
-- because roblox-ts compiles a bare arrow function to an actual Lua
|
|
192
|
-
-- `function` value, and Lua functions can't have table-style properties
|
|
193
|
-
-- (Tabs.List = ...) assigned onto them — forwardRef's return value compiles
|
|
194
|
-
-- to a table instead. The ref itself is genuinely unused: there's no
|
|
195
|
-
-- sensible Instance for it to point at, so RefAttributes<Frame> below is a
|
|
196
|
-
-- type-level placeholder to keep this consistent with every other compound
|
|
197
|
-
-- component's shape, not a real forwarded ref — Tabs does not support a
|
|
198
|
-
-- `ref` prop in practice.
|
|
199
178
|
local Tabs = React.forwardRef(function(props, _ref)
|
|
200
179
|
local selected, setSelected = React.useState(props.defaultValue)
|
|
201
180
|
local contextValue = React.useMemo(function()
|
|
@@ -22,6 +22,9 @@ end
|
|
|
22
22
|
for _k, _v in TS.import(script, script, "FlexItem") or {} do
|
|
23
23
|
exports[_k] = _v
|
|
24
24
|
end
|
|
25
|
+
for _k, _v in TS.import(script, script, "Grid") or {} do
|
|
26
|
+
exports[_k] = _v
|
|
27
|
+
end
|
|
25
28
|
for _k, _v in TS.import(script, script, "Group") or {} do
|
|
26
29
|
exports[_k] = _v
|
|
27
30
|
end
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import React from "@rbxts/react";
|
|
2
|
-
import { BackgroundElementProps, PositionElementProps, ShadowElementProps, SizeElementProps, SpacedElementProps, ZIndexElementProps } from "../../Interfaces/";
|
|
2
|
+
import { BackgroundElementProps, CssBackgroundGradient, PositionElementProps, ShadowElementProps, SizeElementProps, SpacedElementProps, ZIndexElementProps } from "../../Interfaces/";
|
|
3
3
|
import { CssBackgroundImage } from "../../Theme";
|
|
4
4
|
export interface BoxProps extends SpacedElementProps, ShadowElementProps, BackgroundElementProps, ZIndexElementProps, SizeElementProps, PositionElementProps, React.InstanceProps<ImageLabel> {
|
|
5
5
|
'border-thickness'?: number;
|
|
6
6
|
'border-color'?: Color3;
|
|
7
7
|
'background-image'?: CssBackgroundImage;
|
|
8
|
+
'background-gradient'?: CssBackgroundGradient;
|
|
8
9
|
name?: string;
|
|
9
10
|
}
|
|
10
11
|
export declare const Box: React.ForwardRefExoticComponent<Omit<BoxProps, "ref"> & React.RefAttributes<ImageLabel>>;
|
|
@@ -6,6 +6,7 @@ local _Decorator = TS.import(script, script.Parent.Parent, "Decorator")
|
|
|
6
6
|
local Padding = _Decorator.Padding
|
|
7
7
|
local Corners = _Decorator.Corners
|
|
8
8
|
local BoxShadow = _Decorator.BoxShadow
|
|
9
|
+
local Gradient = _Decorator.Gradient
|
|
9
10
|
local Container = TS.import(script, script.Parent.Parent, "Layout").Container
|
|
10
11
|
local _Helpers = TS.import(script, script.Parent.Parent.Parent, "Helpers")
|
|
11
12
|
local SizeHelper = _Helpers.SizeHelper
|
|
@@ -54,6 +55,8 @@ local Box = React.forwardRef(function(props, ref)
|
|
|
54
55
|
resolvedPadding = SpacingHelper:GetResolvedPadding(theme, props, theme.components.box.spacing, theme.components.box.padding),
|
|
55
56
|
}), React.createElement(Corners, {
|
|
56
57
|
radius = theme.components.box.cornerRadius,
|
|
58
|
+
}), React.createElement(Gradient, {
|
|
59
|
+
value = props["background-gradient"] or theme.components.box.backgroundGradient,
|
|
57
60
|
}), props.children)
|
|
58
61
|
end)
|
|
59
62
|
return {
|
|
@@ -14,13 +14,6 @@ local SpacingHelper = _Helpers.SpacingHelper
|
|
|
14
14
|
local CleanThemeContext = TS.import(script, script.Parent.Parent.Parent, "Contexts").CleanThemeContext
|
|
15
15
|
local Padding = TS.import(script, script.Parent.Parent, "Decorator").Padding
|
|
16
16
|
local CardContext = React.createContext({})
|
|
17
|
-
-- Resolves a theme-driven CssPosition into raw Position/AnchorPoint offsets.
|
|
18
|
-
-- This is a one-off resolver rather than a SizeHelper addition because
|
|
19
|
-
-- CssPosition's `center` is axis-aware (`"x"` / `"y"`) so it can express
|
|
20
|
-
-- "center horizontally, anchor to the top with an offset" — something
|
|
21
|
-
-- SizeHelper.GetPosition/GetAnchor can't do since they apply `center`
|
|
22
|
-
-- identically to both axes, and that symmetric behavior is relied on
|
|
23
|
-
-- elsewhere in the codebase so isn't something to widen here.
|
|
24
17
|
local function resolveCssPositionOffset(position)
|
|
25
18
|
local centerX = position.center == true or position.center == "x"
|
|
26
19
|
local centerY = position.center == true or position.center == "y"
|
|
@@ -28,19 +21,6 @@ local function resolveCssPositionOffset(position)
|
|
|
28
21
|
local anchorY = if centerY then 0.5 else (if position.top == nil and position.bottom ~= nil then 1 else 0)
|
|
29
22
|
local posX = if centerX then UDim.new(0.5, 0) elseif position.left ~= nil then SizeHelper:toUDim(position.left) elseif position.right ~= nil then UDim.new(1 - SizeHelper:toUDim(position.right).Scale, -SizeHelper:toUDim(position.right).Offset) else UDim.new(0, 0)
|
|
30
23
|
local posY = if centerY then UDim.new(0.5, 0) elseif position.top ~= nil then SizeHelper:toUDim(position.top) elseif position.bottom ~= nil then UDim.new(1 - SizeHelper:toUDim(position.bottom).Scale, -SizeHelper:toUDim(position.bottom).Offset) else UDim.new(0, 0)
|
|
31
|
-
-- A theme-driven fixed/relative width (only meaningful in overlay mode,
|
|
32
|
-
-- see CssPosition.width) forces a fixed-width/auto-height Size, taking
|
|
33
|
-
-- over the caller's default Size={fromScale(0,0)}/AutomaticSize={XY} —
|
|
34
|
-
-- otherwise Size/AutomaticSize are left undefined so the caller's own
|
|
35
|
-
-- default applies unchanged. Parsed via CssHelper.parseCssSize (not
|
|
36
|
-
-- SizeHelper.toUDim, used for top/left/right/bottom above) since it's
|
|
37
|
-
-- the one that understands the "<percent>% - <px>px" calc() shape a
|
|
38
|
-
-- width value may use (e.g. "100% - 50px").
|
|
39
|
-
--
|
|
40
|
-
-- When `width` isn't explicit but both `left` and `right` are set, imply
|
|
41
|
-
-- a width from them the same way CSS does for an absolutely-positioned
|
|
42
|
-
-- element: width = 100% - left - right. Explicit `width` always wins if
|
|
43
|
-
-- somehow both are set.
|
|
44
24
|
local impliedWidth = if position.width == nil and position.left ~= nil and position.right ~= nil then (function()
|
|
45
25
|
local leftUDim = SizeHelper:toUDim(position.left)
|
|
46
26
|
local rightUDim = SizeHelper:toUDim(position.right)
|
|
@@ -63,18 +43,6 @@ local function resolveCssPositionOffset(position)
|
|
|
63
43
|
end
|
|
64
44
|
return _object
|
|
65
45
|
end
|
|
66
|
-
-- Header/footer overlay mode escapes the card's VStack (a UIListLayout
|
|
67
|
-
-- forcibly repositions every sibling it lays out, so there's no way to keep
|
|
68
|
-
-- a custom Position/AnchorPoint on a child that stays inside it) — Card
|
|
69
|
-
-- pulls an overlay-requesting Header/Footer out of the flow and renders it
|
|
70
|
-
-- as an absolutely-positioned sibling of the Box instead. Overlay mode is
|
|
71
|
-
-- requested via the instance `overlay` prop or `theme.components.card.header
|
|
72
|
-
-- /footer.position.position === "absolute"`; when the instance sets any of
|
|
73
|
-
-- its own Position/AnchorPoint/top/left/right/bottom/center fields, those
|
|
74
|
-
-- win wholesale over the theme's CssPosition (mixing partial fields across
|
|
75
|
-
-- the two differently-shaped position vocabularies isn't attempted), exactly
|
|
76
|
-
-- mirroring the precedence the previous PositionElementProps-based
|
|
77
|
-
-- implementation gave instance props.
|
|
78
46
|
local function resolveOverlayPosition(props, themePosition)
|
|
79
47
|
local _condition = props.overlay
|
|
80
48
|
if _condition == nil then
|
|
@@ -180,6 +148,7 @@ local CardHeader = React.forwardRef(function(props, ref)
|
|
|
180
148
|
_attributes.BackgroundColor3 = intent.backgroundColor
|
|
181
149
|
_attributes.BorderSizePixel = 0
|
|
182
150
|
_attributes.backgroundImage = intent.backgroundImage
|
|
151
|
+
_attributes.backgroundGradient = intent.backgroundGradient
|
|
183
152
|
_attributes.Change = if overlay and card.reportOverlayHeaderRect ~= nil then {
|
|
184
153
|
AbsolutePosition = function(instance)
|
|
185
154
|
return card.reportOverlayHeaderRect(instance.AbsolutePosition, instance.AbsoluteSize)
|
|
@@ -211,14 +180,6 @@ local CardHeader = React.forwardRef(function(props, ref)
|
|
|
211
180
|
end)
|
|
212
181
|
local CardBody = React.forwardRef(function(props, ref)
|
|
213
182
|
local theme = React.useContext(CleanThemeContext)
|
|
214
|
-
-- Unified 4-tier padding resolution (see SpacingHelper.GetResolvedPadding):
|
|
215
|
-
-- `card.body.spacing` (tier 2) overrides the global spacing map per
|
|
216
|
-
-- scale key, falling back to it for any key it doesn't define, and
|
|
217
|
-
-- `card.body.padding` (tier 3) overrides the scale-based tiers
|
|
218
|
-
-- entirely at the active key. CardBody wraps its children in a
|
|
219
|
-
-- Container, not a Box, so it doesn't get Box's automatic
|
|
220
|
-
-- `box.padding` application for free — this resolves independently
|
|
221
|
-
-- against `theme.components.card.body`'s own tiers.
|
|
222
183
|
local paddingSourceProps = props
|
|
223
184
|
local _attributes = {
|
|
224
185
|
name = "CardBody",
|
|
@@ -266,6 +227,7 @@ local CardFooter = React.forwardRef(function(props, ref)
|
|
|
266
227
|
_attributes.BackgroundColor3 = intent.backgroundColor
|
|
267
228
|
_attributes.BorderSizePixel = 0
|
|
268
229
|
_attributes.backgroundImage = intent.backgroundImage
|
|
230
|
+
_attributes.backgroundGradient = intent.backgroundGradient
|
|
269
231
|
_attributes.Change = if overlay and card.reportOverlayFooterRect ~= nil then {
|
|
270
232
|
AbsolutePosition = function(instance)
|
|
271
233
|
return card.reportOverlayFooterRect(instance.AbsolutePosition, instance.AbsoluteSize)
|
|
@@ -297,18 +259,6 @@ local CardFooter = React.forwardRef(function(props, ref)
|
|
|
297
259
|
end)
|
|
298
260
|
local Card = React.forwardRef(function(props, ref)
|
|
299
261
|
local theme = React.useContext(CleanThemeContext)
|
|
300
|
-
-- Overlay clearance: an overlay header (see resolveOverlayPosition)
|
|
301
|
-
-- is pulled out of the VStack entirely, so nothing reserves space
|
|
302
|
-
-- for it — its rendered box typically extends downward past its own
|
|
303
|
-
-- anchor point and overlaps into the top of the Box. These two
|
|
304
|
-
-- pieces of state capture the header's reported rect (via
|
|
305
|
-
-- CardContext.reportOverlayHeaderRect, set on CardHeader below) and
|
|
306
|
-
-- the overlay wrapper frame's own AbsolutePosition, so the amount of
|
|
307
|
-
-- that overlap can be measured and reserved as extra top padding on
|
|
308
|
-
-- the Box (see headerClearance/boxProps below). Both are undefined
|
|
309
|
-
-- until their first Change event fires after mount, which is the
|
|
310
|
-
-- same measure-then-settle characteristic Accordion.tsx accepts for
|
|
311
|
-
-- its own AbsoluteSize-driven measurements.
|
|
312
262
|
local headerRect, setHeaderRect = React.useState()
|
|
313
263
|
local footerRect, setFooterRect = React.useState()
|
|
314
264
|
local wrapperAbsoluteY, setWrapperAbsoluteY = React.useState()
|
|
@@ -334,10 +284,6 @@ local Card = React.forwardRef(function(props, ref)
|
|
|
334
284
|
}
|
|
335
285
|
end, { props.intent, reportOverlayHeaderRect, reportOverlayFooterRect })
|
|
336
286
|
local intent = ColorHelper:getIntentColors(theme, props.intent or "primary", "default", theme.components.card.header.intents)
|
|
337
|
-
-- Pull out a Header/Footer that wants overlay placement so it can be
|
|
338
|
-
-- rendered outside the VStack below (see resolveOverlayPosition above
|
|
339
|
-
-- for why it can't stay inside the VStack and still be positioned).
|
|
340
|
-
-- Everything else renders in place, in its original order.
|
|
341
287
|
local _binding = React.useMemo(function()
|
|
342
288
|
local flow = {}
|
|
343
289
|
local header
|
|
@@ -392,21 +338,9 @@ local Card = React.forwardRef(function(props, ref)
|
|
|
392
338
|
local overlayHeader = _binding.overlayHeader
|
|
393
339
|
local overlayFooter = _binding.overlayFooter
|
|
394
340
|
local hasOverlay = overlayHeader ~= nil or overlayFooter ~= nil
|
|
395
|
-
-- How far the overlay header's bottom edge extends past the
|
|
396
|
-
-- wrapper's (i.e. the Box's) top edge — 0 when there's no overlap
|
|
397
|
-
-- (e.g. a small/no theme offset) or nothing has been measured yet.
|
|
398
341
|
local headerClearance = if overlayHeader ~= nil and headerRect ~= nil and wrapperAbsoluteY ~= nil then math.max(0, (headerRect.position.Y + headerRect.size.Y) - wrapperAbsoluteY) else 0
|
|
399
|
-
-- Same idea, mirrored for the footer: the wrapper's bottom edge
|
|
400
|
-
-- (its top plus its own height) minus the footer's reported top
|
|
401
|
-
-- edge (AbsolutePosition is always the top-left corner regardless
|
|
402
|
-
-- of AnchorPoint) is how far the footer's top edge sits above the
|
|
403
|
-
-- Box's bottom edge, i.e. how much it overlaps upward into it.
|
|
404
342
|
local wrapperBottomY = if wrapperAbsoluteY ~= nil and wrapperAbsoluteSize ~= nil then wrapperAbsoluteY + wrapperAbsoluteSize.Y else nil
|
|
405
343
|
local footerClearance = if overlayFooter ~= nil and footerRect ~= nil and wrapperBottomY ~= nil then math.max(0, wrapperBottomY - footerRect.position.Y) else 0
|
|
406
|
-
-- The Box below now sits inside an extra positioning frame (see
|
|
407
|
-
-- boxWithOverlay), so its own Position/AnchorPoint/ZIndex/LayoutOrder
|
|
408
|
-
-- are cleared here to avoid double-applying them — the wrapper frame
|
|
409
|
-
-- owns those instead.
|
|
410
344
|
local _result
|
|
411
345
|
if hasOverlay then
|
|
412
346
|
local _object = table.clone(props)
|
|
@@ -424,18 +358,6 @@ local Card = React.forwardRef(function(props, ref)
|
|
|
424
358
|
_result = props
|
|
425
359
|
end
|
|
426
360
|
local boxProps = _result
|
|
427
|
-
-- When there's no footer at all, footerClearance is always 0 (there's
|
|
428
|
-
-- nothing to measure an overlap against), so fall back to the Box's
|
|
429
|
-
-- own explicit theme.components.box.padding bottom inset — if the
|
|
430
|
-
-- theme sets one — as a floor instead. This keeps content clear of a
|
|
431
|
-
-- themed Box's decorative border image (e.g. wooden's wood-frame art,
|
|
432
|
-
-- which needs a real bottom inset) even when there's no footer to
|
|
433
|
-
-- reserve that space via measured overlap. Themes that don't set an
|
|
434
|
-
-- explicit box padding (GetExplicitPadding returns undefined) resolve
|
|
435
|
-
-- this floor to 0, so behavior there is unchanged. When a footer IS
|
|
436
|
-
-- present, footerClearance (its real measured overlap) is used as-is
|
|
437
|
-
-- exactly as before — this floor never applies then, since the
|
|
438
|
-
-- footer's own overlap already reserves whatever space it needs.
|
|
439
361
|
local _result_1
|
|
440
362
|
if overlayFooter == nil then
|
|
441
363
|
local _result_2 = SpacingHelper:GetExplicitPadding(theme.components.box.padding, theme.default.spacing)
|
|
@@ -451,12 +373,6 @@ local Card = React.forwardRef(function(props, ref)
|
|
|
451
373
|
_result_1 = 0
|
|
452
374
|
end
|
|
453
375
|
local explicitBoxBottomFloor = _result_1
|
|
454
|
-
-- When an overlay header and/or footer measurably overlaps into the
|
|
455
|
-
-- Box (headerClearance/footerClearance > 0), or the footer-absent
|
|
456
|
-
-- floor above is nonzero, reserve that much extra top/bottom padding
|
|
457
|
-
-- via resolvedPadding — this takes over Box's own outer padding,
|
|
458
|
-
-- which is otherwise 0/0/0/0 since Card always forces spacing="None"
|
|
459
|
-
-- on Box below.
|
|
460
376
|
local _result_2
|
|
461
377
|
if headerClearance > 0 or footerClearance > 0 or explicitBoxBottomFloor > 0 then
|
|
462
378
|
local _object = table.clone(boxProps)
|
|
@@ -486,23 +402,6 @@ local Card = React.forwardRef(function(props, ref)
|
|
|
486
402
|
local cardBox = (React.createElement(Box, _attributes, React.createElement(VStack, {
|
|
487
403
|
spacing = "None",
|
|
488
404
|
}, flowChildren)))
|
|
489
|
-
-- ClipsDescendants is off so an overlay header/footer can protrude
|
|
490
|
-
-- past the Box's own edges (e.g. a plaque mounted above the top
|
|
491
|
-
-- border). This frame takes over the Position/AnchorPoint the Box
|
|
492
|
-
-- would otherwise have used, and auto-sizes to hug the Box (plus
|
|
493
|
-
-- whatever the overlay siblings protrude by).
|
|
494
|
-
--
|
|
495
|
-
-- `center` is stripped before deriving Position/AnchorPoint here,
|
|
496
|
-
-- the same way `cardBox`'s Box always gets `center={undefined}`:
|
|
497
|
-
-- when `center` is set, centering is handled by the outer
|
|
498
|
-
-- `isCentered` wrapper below (a UIListLayout that centers this
|
|
499
|
-
-- whole frame), not by this frame's own Position/AnchorPoint. If
|
|
500
|
-
-- both applied `center` at once, the UIListLayout would place the
|
|
501
|
-
-- frame using an (0,0)-anchor assumption while the frame itself
|
|
502
|
-
-- reported a (0.5,0.5) AnchorPoint, offsetting it by half its own
|
|
503
|
-
-- size and letting its (ClipsDescendants=false) contents spill out.
|
|
504
|
-
-- Explicit top/left/right/bottom/Position/AnchorPoint overrides are
|
|
505
|
-
-- unaffected and still apply directly to this frame.
|
|
506
405
|
local _object = table.clone(props)
|
|
507
406
|
setmetatable(_object, nil)
|
|
508
407
|
_object.center = nil
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import React from "@rbxts/react";
|
|
2
|
+
import { IntentElementProps, PositionElementProps, ScalableElementProps, SizeElementProps, ZIndexElementProps } from "../../Interfaces";
|
|
3
|
+
export interface ProgressBarProps extends IntentElementProps, ScalableElementProps, SizeElementProps, PositionElementProps, ZIndexElementProps, React.InstanceProps<ImageLabel> {
|
|
4
|
+
value: number;
|
|
5
|
+
max?: number;
|
|
6
|
+
label?: string;
|
|
7
|
+
showValue?: boolean;
|
|
8
|
+
valueFormatter?: (value: number, max: number) => string;
|
|
9
|
+
name?: string;
|
|
10
|
+
striped?: boolean;
|
|
11
|
+
stripeDuration?: number;
|
|
12
|
+
stripeDirection?: number;
|
|
13
|
+
}
|
|
14
|
+
export declare const ProgressBar: React.ForwardRefExoticComponent<Omit<ProgressBarProps, "ref"> & React.RefAttributes<ImageLabel>>;
|