@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
|
@@ -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
|
|
@@ -161,6 +129,28 @@ local CardHeader = React.forwardRef(function(props, ref)
|
|
|
161
129
|
local intent = ColorHelper:getIntentColors(theme, props.intent or card.intent or "primary", "default", theme.components.card.header.intents)
|
|
162
130
|
local padding = SpacingHelper:GetResolvedPadding(theme, props, theme.components.card.header.spacing, theme.components.card.header.padding, "md")
|
|
163
131
|
local corners = CssHelper:parseCssSize(theme.components.card.cornerRadius)
|
|
132
|
+
local headerCorners = theme.components.card.header.cornerRadius
|
|
133
|
+
local noCorner = UDim.new(0, 0)
|
|
134
|
+
local _result = headerCorners
|
|
135
|
+
if _result ~= nil then
|
|
136
|
+
_result = _result.topLeft
|
|
137
|
+
end
|
|
138
|
+
local topLeftRadius = if _result ~= nil then CssHelper:parseCssSize(headerCorners.topLeft) else corners
|
|
139
|
+
local _result_1 = headerCorners
|
|
140
|
+
if _result_1 ~= nil then
|
|
141
|
+
_result_1 = _result_1.topRight
|
|
142
|
+
end
|
|
143
|
+
local topRightRadius = if _result_1 ~= nil then CssHelper:parseCssSize(headerCorners.topRight) else corners
|
|
144
|
+
local _result_2 = headerCorners
|
|
145
|
+
if _result_2 ~= nil then
|
|
146
|
+
_result_2 = _result_2.bottomLeft
|
|
147
|
+
end
|
|
148
|
+
local bottomLeftRadius = if _result_2 ~= nil then CssHelper:parseCssSize(headerCorners.bottomLeft) else noCorner
|
|
149
|
+
local _result_3 = headerCorners
|
|
150
|
+
if _result_3 ~= nil then
|
|
151
|
+
_result_3 = _result_3.bottomRight
|
|
152
|
+
end
|
|
153
|
+
local bottomRightRadius = if _result_3 ~= nil then CssHelper:parseCssSize(headerCorners.bottomRight) else noCorner
|
|
164
154
|
local _binding = resolveOverlayPosition(props, theme.components.card.header.position)
|
|
165
155
|
local overlay = _binding.overlay
|
|
166
156
|
local positionProps = _binding.positionProps
|
|
@@ -180,6 +170,7 @@ local CardHeader = React.forwardRef(function(props, ref)
|
|
|
180
170
|
_attributes.BackgroundColor3 = intent.backgroundColor
|
|
181
171
|
_attributes.BorderSizePixel = 0
|
|
182
172
|
_attributes.backgroundImage = intent.backgroundImage
|
|
173
|
+
_attributes.backgroundGradient = intent.backgroundGradient
|
|
183
174
|
_attributes.Change = if overlay and card.reportOverlayHeaderRect ~= nil then {
|
|
184
175
|
AbsolutePosition = function(instance)
|
|
185
176
|
return card.reportOverlayHeaderRect(instance.AbsolutePosition, instance.AbsoluteSize)
|
|
@@ -203,22 +194,14 @@ local CardHeader = React.forwardRef(function(props, ref)
|
|
|
203
194
|
_attributes_1.BorderStrokePosition = Enum.BorderStrokePosition.Inner
|
|
204
195
|
return React.createElement(Container, _attributes, _exp, React.createElement("uistroke", _attributes_1), React.createElement("uicorner", {
|
|
205
196
|
key = "Corners",
|
|
206
|
-
TopLeftRadius =
|
|
207
|
-
TopRightRadius =
|
|
208
|
-
BottomLeftRadius =
|
|
209
|
-
BottomRightRadius =
|
|
197
|
+
TopLeftRadius = topLeftRadius,
|
|
198
|
+
TopRightRadius = topRightRadius,
|
|
199
|
+
BottomLeftRadius = bottomLeftRadius,
|
|
200
|
+
BottomRightRadius = bottomRightRadius,
|
|
210
201
|
}), props.children)
|
|
211
202
|
end)
|
|
212
203
|
local CardBody = React.forwardRef(function(props, ref)
|
|
213
204
|
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
205
|
local paddingSourceProps = props
|
|
223
206
|
local _attributes = {
|
|
224
207
|
name = "CardBody",
|
|
@@ -247,6 +230,28 @@ local CardFooter = React.forwardRef(function(props, ref)
|
|
|
247
230
|
local intent = ColorHelper:getIntentColors(theme, props.intent or card.intent or "primary", "default", theme.components.card.footer.intents)
|
|
248
231
|
local padding = SpacingHelper:GetResolvedPadding(theme, props, theme.components.card.footer.spacing, theme.components.card.footer.padding, "md")
|
|
249
232
|
local corners = CssHelper:parseCssSize(theme.components.card.cornerRadius)
|
|
233
|
+
local footerCorners = theme.components.card.footer.cornerRadius
|
|
234
|
+
local noCorner = UDim.new(0, 0)
|
|
235
|
+
local _result = footerCorners
|
|
236
|
+
if _result ~= nil then
|
|
237
|
+
_result = _result.topLeft
|
|
238
|
+
end
|
|
239
|
+
local topLeftRadius = if _result ~= nil then CssHelper:parseCssSize(footerCorners.topLeft) else noCorner
|
|
240
|
+
local _result_1 = footerCorners
|
|
241
|
+
if _result_1 ~= nil then
|
|
242
|
+
_result_1 = _result_1.topRight
|
|
243
|
+
end
|
|
244
|
+
local topRightRadius = if _result_1 ~= nil then CssHelper:parseCssSize(footerCorners.topRight) else noCorner
|
|
245
|
+
local _result_2 = footerCorners
|
|
246
|
+
if _result_2 ~= nil then
|
|
247
|
+
_result_2 = _result_2.bottomLeft
|
|
248
|
+
end
|
|
249
|
+
local bottomLeftRadius = if _result_2 ~= nil then CssHelper:parseCssSize(footerCorners.bottomLeft) else corners
|
|
250
|
+
local _result_3 = footerCorners
|
|
251
|
+
if _result_3 ~= nil then
|
|
252
|
+
_result_3 = _result_3.bottomRight
|
|
253
|
+
end
|
|
254
|
+
local bottomRightRadius = if _result_3 ~= nil then CssHelper:parseCssSize(footerCorners.bottomRight) else corners
|
|
250
255
|
local _binding = resolveOverlayPosition(props, theme.components.card.footer.position)
|
|
251
256
|
local overlay = _binding.overlay
|
|
252
257
|
local positionProps = _binding.positionProps
|
|
@@ -266,6 +271,7 @@ local CardFooter = React.forwardRef(function(props, ref)
|
|
|
266
271
|
_attributes.BackgroundColor3 = intent.backgroundColor
|
|
267
272
|
_attributes.BorderSizePixel = 0
|
|
268
273
|
_attributes.backgroundImage = intent.backgroundImage
|
|
274
|
+
_attributes.backgroundGradient = intent.backgroundGradient
|
|
269
275
|
_attributes.Change = if overlay and card.reportOverlayFooterRect ~= nil then {
|
|
270
276
|
AbsolutePosition = function(instance)
|
|
271
277
|
return card.reportOverlayFooterRect(instance.AbsolutePosition, instance.AbsoluteSize)
|
|
@@ -289,26 +295,14 @@ local CardFooter = React.forwardRef(function(props, ref)
|
|
|
289
295
|
_attributes_1.BorderStrokePosition = Enum.BorderStrokePosition.Inner
|
|
290
296
|
return React.createElement(Container, _attributes, _exp, React.createElement("uistroke", _attributes_1), React.createElement("uicorner", {
|
|
291
297
|
key = "Corners",
|
|
292
|
-
TopLeftRadius =
|
|
293
|
-
TopRightRadius =
|
|
294
|
-
BottomLeftRadius =
|
|
295
|
-
BottomRightRadius =
|
|
298
|
+
TopLeftRadius = topLeftRadius,
|
|
299
|
+
TopRightRadius = topRightRadius,
|
|
300
|
+
BottomLeftRadius = bottomLeftRadius,
|
|
301
|
+
BottomRightRadius = bottomRightRadius,
|
|
296
302
|
}), props.children)
|
|
297
303
|
end)
|
|
298
304
|
local Card = React.forwardRef(function(props, ref)
|
|
299
305
|
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
306
|
local headerRect, setHeaderRect = React.useState()
|
|
313
307
|
local footerRect, setFooterRect = React.useState()
|
|
314
308
|
local wrapperAbsoluteY, setWrapperAbsoluteY = React.useState()
|
|
@@ -334,10 +328,6 @@ local Card = React.forwardRef(function(props, ref)
|
|
|
334
328
|
}
|
|
335
329
|
end, { props.intent, reportOverlayHeaderRect, reportOverlayFooterRect })
|
|
336
330
|
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
331
|
local _binding = React.useMemo(function()
|
|
342
332
|
local flow = {}
|
|
343
333
|
local header
|
|
@@ -392,21 +382,9 @@ local Card = React.forwardRef(function(props, ref)
|
|
|
392
382
|
local overlayHeader = _binding.overlayHeader
|
|
393
383
|
local overlayFooter = _binding.overlayFooter
|
|
394
384
|
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
385
|
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
386
|
local wrapperBottomY = if wrapperAbsoluteY ~= nil and wrapperAbsoluteSize ~= nil then wrapperAbsoluteY + wrapperAbsoluteSize.Y else nil
|
|
405
387
|
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
388
|
local _result
|
|
411
389
|
if hasOverlay then
|
|
412
390
|
local _object = table.clone(props)
|
|
@@ -424,18 +402,6 @@ local Card = React.forwardRef(function(props, ref)
|
|
|
424
402
|
_result = props
|
|
425
403
|
end
|
|
426
404
|
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
405
|
local _result_1
|
|
440
406
|
if overlayFooter == nil then
|
|
441
407
|
local _result_2 = SpacingHelper:GetExplicitPadding(theme.components.box.padding, theme.default.spacing)
|
|
@@ -451,12 +417,6 @@ local Card = React.forwardRef(function(props, ref)
|
|
|
451
417
|
_result_1 = 0
|
|
452
418
|
end
|
|
453
419
|
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
420
|
local _result_2
|
|
461
421
|
if headerClearance > 0 or footerClearance > 0 or explicitBoxBottomFloor > 0 then
|
|
462
422
|
local _object = table.clone(boxProps)
|
|
@@ -486,23 +446,6 @@ local Card = React.forwardRef(function(props, ref)
|
|
|
486
446
|
local cardBox = (React.createElement(Box, _attributes, React.createElement(VStack, {
|
|
487
447
|
spacing = "None",
|
|
488
448
|
}, 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
449
|
local _object = table.clone(props)
|
|
507
450
|
setmetatable(_object, nil)
|
|
508
451
|
_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>>;
|