@rbxts/react-clean-ui 1.0.36 → 1.0.38
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/Input/Button.d.ts +9 -0
- package/out/Components/Input/Button.luau +155 -46
- package/out/Components/Input/Checkbox.luau +21 -5
- package/out/Components/Input/Increment.d.ts +11 -0
- package/out/Components/Input/Increment.luau +107 -0
- package/out/Components/Input/Increment.step.d.ts +1 -0
- package/out/Components/Input/Increment.step.luau +25 -0
- package/out/Components/Input/Input.d.ts +4 -3
- package/out/Components/Input/Input.luau +124 -17
- package/out/Components/Input/Input.validation.d.ts +3 -0
- package/out/Components/Input/Input.validation.luau +21 -0
- package/out/Components/Input/Select.d.ts +4 -3
- package/out/Components/Input/Select.luau +23 -18
- package/out/Components/Input/Slider.d.ts +1 -1
- package/out/Components/Input/Slider.luau +68 -34
- package/out/Components/Input/index.d.ts +1 -0
- package/out/Components/Input/init.luau +3 -0
- package/out/Components/Layout/Accordion.d.ts +1 -1
- package/out/Components/Layout/Accordion.luau +7 -6
- package/out/Components/Layout/Container.d.ts +4 -2
- package/out/Components/Layout/Container.luau +12 -3
- package/out/Components/Layout/Draggable.luau +1 -1
- package/out/Components/Layout/Fieldset.d.ts +1 -1
- package/out/Components/Layout/FlexItem.d.ts +2 -1
- package/out/Components/Layout/FlexItem.luau +1 -0
- package/out/Components/Layout/Scroller.d.ts +1 -0
- package/out/Components/Layout/Scroller.luau +1 -1
- package/out/Components/Layout/Tabs.d.ts +1 -1
- package/out/Components/Layout/Tabs.luau +37 -7
- package/out/Components/Navigation/Menu.d.ts +1 -1
- package/out/Components/Surface/Box.d.ts +4 -2
- package/out/Components/Surface/Box.luau +12 -3
- package/out/Components/Surface/Card.d.ts +8 -6
- package/out/Components/Surface/Card.luau +416 -24
- package/out/Components/Surface/Icon.luau +42 -4
- package/out/Components/Typography/Text.d.ts +1 -0
- package/out/Components/Typography/Text.luau +119 -10
- package/out/Contexts/row.context.d.ts +1 -1
- package/out/Contexts/theme.context.d.ts +2 -2
- package/out/Helpers/color.helper.d.ts +5 -3
- package/out/Helpers/color.helper.luau +62 -34
- package/out/Helpers/create-ui-story.d.ts +2 -2
- package/out/Helpers/create-ui-story.luau +33 -1
- package/out/Helpers/css.helper.d.ts +28 -2
- package/out/Helpers/css.helper.luau +208 -0
- package/out/Helpers/index.d.ts +1 -0
- package/out/Helpers/init.luau +3 -0
- package/out/Helpers/size.helper.d.ts +3 -1
- package/out/Helpers/size.helper.luau +10 -9
- package/out/Helpers/spacing.helper.d.ts +3 -3
- package/out/Helpers/typography.helper.d.ts +2 -2
- package/out/Interfaces/css.types.d.ts +28 -0
- package/out/Interfaces/css.types.luau +17 -0
- package/out/Interfaces/element.props.d.ts +61 -0
- package/out/Interfaces/element.props.luau +1 -0
- package/out/Interfaces/index.d.ts +4 -2
- package/out/Interfaces/init.luau +9 -3
- package/out/Interfaces/responsive.types.d.ts +26 -0
- package/out/Interfaces/semantics.d.ts +3 -0
- package/out/Interfaces/semantics.luau +2 -0
- package/out/Providers/app.provider.d.ts +2 -2
- package/out/Providers/theme.provider.d.ts +2 -2
- package/out/Theme/index.d.ts +1 -0
- package/out/Theme/theme.factory.d.ts +3 -3
- package/out/Theme/theme.style.d.ts +48 -0
- package/out/Theme/theme.style.luau +1 -0
- package/out/Theme/theme.template.d.ts +23 -26
- package/out/Theme/themes/dark.theme.d.ts +1 -1
- package/out/Theme/themes/dark.theme.luau +28 -0
- package/out/Theme/themes/default.theme.d.ts +2 -2
- package/out/Theme/themes/default.theme.luau +11 -1
- package/out/Theme/themes/index.d.ts +1 -0
- package/out/Theme/themes/init.luau +3 -0
- package/out/Theme/themes/sandstone.theme.d.ts +1 -1
- package/out/Theme/themes/sandstone.theme.luau +25 -0
- package/out/Theme/themes/wooden.theme.d.ts +1 -0
- package/out/Theme/themes/wooden.theme.luau +443 -0
- package/out/index.d.ts +8 -8
- package/package.json +18 -6
- package/out/Interfaces/clean.element.props.d.ts +0 -114
- /package/out/{Interfaces/userinput.d.ts → Helpers/input.helper.d.ts} +0 -0
- /package/out/{Interfaces/userinput.luau → Helpers/input.helper.luau} +0 -0
- /package/out/Interfaces/{clean.element.props.luau → responsive.types.luau} +0 -0
|
@@ -7,22 +7,95 @@ local Text = React.forwardRef(function(props, ref)
|
|
|
7
7
|
local style = props.typography or theme.typography[props.variant or "body"]
|
|
8
8
|
local weight = if props.weight == "bold" then Enum.FontWeight.Bold else props.weight or style.weight or Enum.FontWeight.Regular
|
|
9
9
|
local textwrapped = props.TextWrap ~= false and props.TextWrapped ~= false
|
|
10
|
+
local _condition = props.letterSpacing
|
|
11
|
+
if _condition == nil then
|
|
12
|
+
_condition = style.letterSpacing
|
|
13
|
+
end
|
|
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
|
+
if letterSpacing ~= nil and letterSpacing ~= 0 and props.text ~= "" then
|
|
22
|
+
local characters = {}
|
|
23
|
+
for index = 0, #props.text - 1 do
|
|
24
|
+
local _text = props.text
|
|
25
|
+
local _arg0 = index + 1
|
|
26
|
+
local _arg1 = index + 1
|
|
27
|
+
local _arg0_1 = string.sub(_text, _arg0, _arg1)
|
|
28
|
+
table.insert(characters, _arg0_1)
|
|
29
|
+
end
|
|
30
|
+
local _exp = React.createElement("uilistlayout", {
|
|
31
|
+
FillDirection = Enum.FillDirection.Horizontal,
|
|
32
|
+
SortOrder = Enum.SortOrder.LayoutOrder,
|
|
33
|
+
Padding = UDim.new(0, letterSpacing),
|
|
34
|
+
VerticalAlignment = Enum.VerticalAlignment.Center,
|
|
35
|
+
HorizontalAlignment = props.align or Enum.HorizontalAlignment.Left,
|
|
36
|
+
})
|
|
37
|
+
-- ▼ ReadonlyArray.map ▼
|
|
38
|
+
local _newValue = table.create(#characters)
|
|
39
|
+
local _callback = function(character, index)
|
|
40
|
+
local _attributes = {
|
|
41
|
+
key = index,
|
|
42
|
+
LayoutOrder = index,
|
|
43
|
+
Size = UDim2.fromScale(0, 0),
|
|
44
|
+
AutomaticSize = Enum.AutomaticSize.XY,
|
|
45
|
+
BackgroundTransparency = 1,
|
|
46
|
+
TextColor3 = props.TextColor3 or theme.colors.intents.primary.default.textColor,
|
|
47
|
+
Text = character,
|
|
48
|
+
}
|
|
49
|
+
local _condition_1 = props.LineHeight
|
|
50
|
+
if _condition_1 == nil then
|
|
51
|
+
_condition_1 = style.lineHeight
|
|
52
|
+
end
|
|
53
|
+
_attributes.LineHeight = _condition_1
|
|
54
|
+
_attributes.FontFace = Font.fromName(style.font.Name, weight)
|
|
55
|
+
_attributes.FontSize = style.size
|
|
56
|
+
_attributes.RichText = false
|
|
57
|
+
local _condition_2 = props.TextScaled
|
|
58
|
+
if _condition_2 == nil then
|
|
59
|
+
_condition_2 = false
|
|
60
|
+
end
|
|
61
|
+
_attributes.TextScaled = _condition_2
|
|
62
|
+
_attributes.TextStrokeColor3 = props.TextStrokeColor3
|
|
63
|
+
_attributes.TextStrokeTransparency = props.TextStrokeTransparency
|
|
64
|
+
_attributes.TextTransparency = props.TextTransparency
|
|
65
|
+
return React.createElement("textlabel", _attributes)
|
|
66
|
+
end
|
|
67
|
+
for _k, _v in characters do
|
|
68
|
+
_newValue[_k] = _callback(_v, _k - 1, characters)
|
|
69
|
+
end
|
|
70
|
+
-- ▲ ReadonlyArray.map ▲
|
|
71
|
+
return React.createElement("frame", {
|
|
72
|
+
Size = UDim2.fromScale(0, 0),
|
|
73
|
+
AutomaticSize = Enum.AutomaticSize.XY,
|
|
74
|
+
AnchorPoint = props.AnchorPoint,
|
|
75
|
+
BackgroundTransparency = 1,
|
|
76
|
+
Position = props.Position,
|
|
77
|
+
ZIndex = props.ZIndex,
|
|
78
|
+
LayoutOrder = props.LayoutOrder,
|
|
79
|
+
Visible = props.Visible,
|
|
80
|
+
Rotation = props.Rotation,
|
|
81
|
+
}, _exp, _newValue)
|
|
82
|
+
end
|
|
10
83
|
local _attributes = {
|
|
11
84
|
ref = ref,
|
|
12
85
|
Size = UDim2.fromScale(0, 0),
|
|
13
86
|
AutomaticSize = Enum.AutomaticSize.XY,
|
|
14
87
|
AnchorPoint = props.AnchorPoint,
|
|
15
88
|
}
|
|
16
|
-
local
|
|
17
|
-
if _condition == nil then
|
|
18
|
-
_condition = style.lineHeight
|
|
19
|
-
end
|
|
20
|
-
_attributes.LineHeight = _condition
|
|
21
|
-
local _condition_1 = props.BackgroundTransparency
|
|
89
|
+
local _condition_1 = props.LineHeight
|
|
22
90
|
if _condition_1 == nil then
|
|
23
|
-
_condition_1 =
|
|
91
|
+
_condition_1 = style.lineHeight
|
|
92
|
+
end
|
|
93
|
+
_attributes.LineHeight = _condition_1
|
|
94
|
+
local _condition_2 = props.BackgroundTransparency
|
|
95
|
+
if _condition_2 == nil then
|
|
96
|
+
_condition_2 = 1
|
|
24
97
|
end
|
|
25
|
-
_attributes.BackgroundTransparency =
|
|
98
|
+
_attributes.BackgroundTransparency = _condition_2
|
|
26
99
|
_attributes.TextXAlignment = props.align or (props.TextXAlignment or Enum.TextXAlignment.Left)
|
|
27
100
|
_attributes.TextColor3 = props.TextColor3 or theme.colors.intents.primary.default.textColor
|
|
28
101
|
_attributes.Text = props.text
|
|
@@ -31,9 +104,45 @@ local Text = React.forwardRef(function(props, ref)
|
|
|
31
104
|
_attributes.TextWrapped = textwrapped
|
|
32
105
|
_attributes.FontFace = Font.fromName(style.font.Name, weight)
|
|
33
106
|
_attributes.FontSize = style.size
|
|
34
|
-
|
|
107
|
+
local _condition_3 = props.RichText
|
|
108
|
+
if _condition_3 == nil then
|
|
109
|
+
_condition_3 = true
|
|
110
|
+
end
|
|
111
|
+
_attributes.RichText = _condition_3
|
|
112
|
+
local _condition_4 = props.TextScaled
|
|
113
|
+
if _condition_4 == nil then
|
|
114
|
+
_condition_4 = false
|
|
115
|
+
end
|
|
116
|
+
_attributes.TextScaled = _condition_4
|
|
117
|
+
_attributes.ZIndex = props.ZIndex
|
|
118
|
+
_attributes.LayoutOrder = props.LayoutOrder
|
|
119
|
+
_attributes.Visible = props.Visible
|
|
120
|
+
_attributes.Rotation = props.Rotation
|
|
121
|
+
_attributes.Active = props.Active
|
|
122
|
+
_attributes.Archivable = props.Archivable
|
|
123
|
+
_attributes.BackgroundColor3 = props.BackgroundColor3
|
|
124
|
+
_attributes.BorderColor3 = props.BorderColor3
|
|
125
|
+
_attributes.BorderMode = props.BorderMode
|
|
126
|
+
_attributes.BorderSizePixel = props.BorderSizePixel
|
|
127
|
+
_attributes.ClipsDescendants = props.ClipsDescendants
|
|
128
|
+
_attributes.Selectable = props.Selectable
|
|
129
|
+
_attributes.SelectionImageObject = props.SelectionImageObject
|
|
130
|
+
_attributes.SizeConstraint = props.SizeConstraint
|
|
131
|
+
_attributes.Tag = props.Tag
|
|
132
|
+
_attributes.AutoLocalize = props.AutoLocalize
|
|
133
|
+
_attributes.RootLocalizationTable = props.RootLocalizationTable
|
|
134
|
+
_attributes.NextSelectionDown = props.NextSelectionDown
|
|
135
|
+
_attributes.NextSelectionLeft = props.NextSelectionLeft
|
|
136
|
+
_attributes.NextSelectionRight = props.NextSelectionRight
|
|
137
|
+
_attributes.NextSelectionUp = props.NextSelectionUp
|
|
138
|
+
_attributes.SelectionGroup = props.SelectionGroup
|
|
139
|
+
_attributes.SelectionOrder = props.SelectionOrder
|
|
140
|
+
_attributes.TextStrokeColor3 = props.TextStrokeColor3
|
|
141
|
+
_attributes.TextStrokeTransparency = props.TextStrokeTransparency
|
|
142
|
+
_attributes.TextTransparency = props.TextTransparency
|
|
143
|
+
_attributes.TextTruncate = props.TextTruncate
|
|
144
|
+
_attributes.Change = props.Change
|
|
35
145
|
_attributes.Event = props.Event
|
|
36
|
-
_attributes.TextScaled = false
|
|
37
146
|
return React.createElement("textlabel", _attributes, props.children)
|
|
38
147
|
end)
|
|
39
148
|
return {
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import React from "@rbxts/react";
|
|
2
|
-
import {
|
|
3
|
-
export declare const CleanThemeContext: React.Context<
|
|
2
|
+
import { ThemeTemplate } from "../Theme/theme.template";
|
|
3
|
+
export declare const CleanThemeContext: React.Context<ThemeTemplate>;
|
|
@@ -1,9 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ThemeTemplate, InlineIntentColors, IntentScheme } from "../Theme";
|
|
2
2
|
import { ButtonFlag, Intent } from "../Interfaces";
|
|
3
3
|
type ComponentIntentColors = Partial<Record<Intent, InlineIntentColors>> | Partial<Record<Intent, Partial<IntentScheme>>>;
|
|
4
4
|
export declare class ColorHelper {
|
|
5
|
-
static getIntentColors(theme:
|
|
6
|
-
private static
|
|
5
|
+
static getIntentColors(theme: ThemeTemplate, intent: Intent | undefined, state?: ButtonFlag, componentColors?: ComponentIntentColors, overrideColors?: ComponentIntentColors): IntentScheme;
|
|
6
|
+
private static mergeLayers;
|
|
7
|
+
private static resolveComponentDefaultLayer;
|
|
8
|
+
private static resolveComponentStateLayer;
|
|
7
9
|
private static isInlineIntentColors;
|
|
8
10
|
}
|
|
9
11
|
export {};
|
|
@@ -13,7 +13,7 @@ do
|
|
|
13
13
|
end
|
|
14
14
|
function ColorHelper:constructor()
|
|
15
15
|
end
|
|
16
|
-
function ColorHelper:getIntentColors(theme, intent, state, componentColors)
|
|
16
|
+
function ColorHelper:getIntentColors(theme, intent, state, componentColors, overrideColors)
|
|
17
17
|
if state == nil then
|
|
18
18
|
state = "default"
|
|
19
19
|
end
|
|
@@ -30,49 +30,77 @@ do
|
|
|
30
30
|
_componentMatching = _componentMatching[selectedIntent]
|
|
31
31
|
end
|
|
32
32
|
local componentMatching = _componentMatching
|
|
33
|
-
local
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
if _condition == nil then
|
|
37
|
-
_condition = {}
|
|
33
|
+
local _overridePrimary = overrideColors
|
|
34
|
+
if _overridePrimary ~= nil then
|
|
35
|
+
_overridePrimary = _overridePrimary.primary
|
|
38
36
|
end
|
|
39
|
-
|
|
40
|
-
|
|
37
|
+
local overridePrimary = _overridePrimary
|
|
38
|
+
local _overrideMatching = overrideColors
|
|
39
|
+
if _overrideMatching ~= nil then
|
|
40
|
+
_overrideMatching = _overrideMatching[selectedIntent]
|
|
41
41
|
end
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
42
|
+
local overrideMatching = _overrideMatching
|
|
43
|
+
local layers = { defaultPrimary.default, defaultMatching.default, defaultPrimary[state], defaultMatching[state], self:resolveComponentDefaultLayer(componentPrimary), self:resolveComponentDefaultLayer(componentMatching), self:resolveComponentStateLayer(componentPrimary, state), self:resolveComponentStateLayer(componentMatching, state), self:resolveComponentDefaultLayer(overridePrimary), self:resolveComponentDefaultLayer(overrideMatching), self:resolveComponentStateLayer(overridePrimary, state), self:resolveComponentStateLayer(overrideMatching, state) }
|
|
44
|
+
return self:mergeLayers(layers)
|
|
45
|
+
end
|
|
46
|
+
function ColorHelper:mergeLayers(layers)
|
|
47
|
+
local merged = {}
|
|
48
|
+
local backgroundImage
|
|
49
|
+
local typography
|
|
50
|
+
for _, layer in layers do
|
|
51
|
+
if layer == nil then
|
|
52
|
+
continue
|
|
53
|
+
end
|
|
54
|
+
local _object = table.clone(merged)
|
|
55
|
+
setmetatable(_object, nil)
|
|
56
|
+
for _k, _v in layer do
|
|
57
|
+
_object[_k] = _v
|
|
58
|
+
end
|
|
59
|
+
merged = _object
|
|
60
|
+
if layer.backgroundImage ~= nil then
|
|
61
|
+
local _object_1 = {}
|
|
62
|
+
if backgroundImage then
|
|
63
|
+
for _k, _v in backgroundImage do
|
|
64
|
+
_object_1[_k] = _v
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
for _k, _v in layer.backgroundImage do
|
|
68
|
+
_object_1[_k] = _v
|
|
69
|
+
end
|
|
70
|
+
backgroundImage = _object_1
|
|
71
|
+
end
|
|
72
|
+
if layer.typography ~= nil then
|
|
73
|
+
local _object_1 = {}
|
|
74
|
+
if typography then
|
|
75
|
+
for _k, _v in typography do
|
|
76
|
+
_object_1[_k] = _v
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
for _k, _v in layer.typography do
|
|
80
|
+
_object_1[_k] = _v
|
|
81
|
+
end
|
|
82
|
+
typography = _object_1
|
|
83
|
+
end
|
|
57
84
|
end
|
|
58
|
-
|
|
85
|
+
merged.backgroundImage = backgroundImage
|
|
86
|
+
merged.typography = typography
|
|
87
|
+
return merged
|
|
59
88
|
end
|
|
60
|
-
function ColorHelper:
|
|
89
|
+
function ColorHelper:resolveComponentDefaultLayer(colors)
|
|
61
90
|
if colors == nil then
|
|
62
|
-
return
|
|
91
|
+
return nil
|
|
63
92
|
end
|
|
64
93
|
if self:isInlineIntentColors(colors) then
|
|
65
|
-
|
|
66
|
-
setmetatable(_object, nil)
|
|
67
|
-
for _k, _v in (colors[state] or {}) do
|
|
68
|
-
_object[_k] = _v
|
|
69
|
-
end
|
|
70
|
-
return _object
|
|
94
|
+
return colors.default
|
|
71
95
|
end
|
|
72
|
-
-- A direct Partial<IntentScheme> has no state variants,
|
|
73
|
-
-- so the requested state is ignored.
|
|
74
96
|
return colors
|
|
75
97
|
end
|
|
98
|
+
function ColorHelper:resolveComponentStateLayer(colors, state)
|
|
99
|
+
if colors == nil or not self:isInlineIntentColors(colors) then
|
|
100
|
+
return nil
|
|
101
|
+
end
|
|
102
|
+
return colors[state]
|
|
103
|
+
end
|
|
76
104
|
function ColorHelper:isInlineIntentColors(colors)
|
|
77
105
|
local statefulColors = colors
|
|
78
106
|
return statefulColors.default ~= nil or statefulColors.hover ~= nil or statefulColors.focus ~= nil
|
|
@@ -2,7 +2,7 @@ import React from "@rbxts/react";
|
|
|
2
2
|
import ReactRoblox from "@rbxts/react-roblox";
|
|
3
3
|
import { InferProps } from "@rbxts/ui-labs";
|
|
4
4
|
declare const controls: {
|
|
5
|
-
Theme: import("@rbxts/ui-labs/src/ControlTypings/Advanced").AdvancedTypes.Choose<"Default" | "Dark" | "Sandstone">;
|
|
5
|
+
Theme: import("@rbxts/ui-labs/src/ControlTypings/Advanced").AdvancedTypes.Choose<"Default" | "Dark" | "Sandstone" | "Wooden">;
|
|
6
6
|
};
|
|
7
7
|
type StoryControl = Parameters<typeof import("@rbxts/ui-labs").Ordered>[0];
|
|
8
8
|
type StoryControls = Record<string, StoryControl>;
|
|
@@ -11,7 +11,7 @@ export declare function createStory<T extends StoryControls = {}>(StoryComponent
|
|
|
11
11
|
react: typeof React;
|
|
12
12
|
reactRoblox: typeof ReactRoblox;
|
|
13
13
|
controls: {
|
|
14
|
-
Theme: import("@rbxts/ui-labs/src/ControlTypings/Advanced").AdvancedTypes.Choose<"Default" | "Dark" | "Sandstone">;
|
|
14
|
+
Theme: import("@rbxts/ui-labs/src/ControlTypings/Advanced").AdvancedTypes.Choose<"Default" | "Dark" | "Sandstone" | "Wooden">;
|
|
15
15
|
} & T;
|
|
16
16
|
story: (props: StoryProps<T>) => React.JSX.Element;
|
|
17
17
|
};
|
|
@@ -6,10 +6,38 @@ local _Theme = TS.import(script, script.Parent.Parent, "Theme")
|
|
|
6
6
|
local DarkTheme = _Theme.DarkTheme
|
|
7
7
|
local DefaultTheme = _Theme.DefaultTheme
|
|
8
8
|
local SandstoneTheme = _Theme.SandstoneTheme
|
|
9
|
+
local WoodenTheme = _Theme.WoodenTheme
|
|
9
10
|
local Choose = TS.import(script, TS.getModule(script, "@rbxts", "ui-labs").src).Choose
|
|
10
11
|
local CleanUiProvider = TS.import(script, script.Parent.Parent, "Providers", "app.provider").CleanUiProvider
|
|
12
|
+
local THEME_ATTRIBUTE = "UILabsSelectedTheme"
|
|
13
|
+
local themeControl = Choose({ "Default", "Dark", "Sandstone", "Wooden" })
|
|
14
|
+
local persistedTheme = script:GetAttribute(THEME_ATTRIBUTE)
|
|
15
|
+
local function isThemeName(value)
|
|
16
|
+
local _value = value
|
|
17
|
+
local _condition = type(_value) == "string"
|
|
18
|
+
if _condition then
|
|
19
|
+
local _exp = themeControl.List
|
|
20
|
+
-- ▼ ReadonlyArray.some ▼
|
|
21
|
+
local _result = false
|
|
22
|
+
local _callback = function(theme)
|
|
23
|
+
return theme == value
|
|
24
|
+
end
|
|
25
|
+
for _k, _v in _exp do
|
|
26
|
+
if _callback(_v, _k - 1, _exp) then
|
|
27
|
+
_result = true
|
|
28
|
+
break
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
-- ▲ ReadonlyArray.some ▲
|
|
32
|
+
_condition = _result
|
|
33
|
+
end
|
|
34
|
+
return _condition
|
|
35
|
+
end
|
|
36
|
+
if isThemeName(persistedTheme) then
|
|
37
|
+
themeControl.ControlValue = persistedTheme
|
|
38
|
+
end
|
|
11
39
|
local controls = {
|
|
12
|
-
Theme =
|
|
40
|
+
Theme = themeControl,
|
|
13
41
|
}
|
|
14
42
|
local function createStory(StoryComponent, additionalControls)
|
|
15
43
|
local _object = {}
|
|
@@ -28,6 +56,7 @@ local function createStory(StoryComponent, additionalControls)
|
|
|
28
56
|
controls = storyControls,
|
|
29
57
|
story = function(props)
|
|
30
58
|
local baseProps = props
|
|
59
|
+
script:SetAttribute(THEME_ATTRIBUTE, baseProps.controls.Theme)
|
|
31
60
|
local theme = DefaultTheme
|
|
32
61
|
if baseProps.controls.Theme == "Dark" then
|
|
33
62
|
theme = DarkTheme
|
|
@@ -35,6 +64,9 @@ local function createStory(StoryComponent, additionalControls)
|
|
|
35
64
|
if baseProps.controls.Theme == "Sandstone" then
|
|
36
65
|
theme = SandstoneTheme
|
|
37
66
|
end
|
|
67
|
+
if baseProps.controls.Theme == "Wooden" then
|
|
68
|
+
theme = WoodenTheme
|
|
69
|
+
end
|
|
38
70
|
local _attributes = table.clone(props)
|
|
39
71
|
setmetatable(_attributes, nil)
|
|
40
72
|
return React.createElement(CleanUiProvider, {
|
|
@@ -1,13 +1,39 @@
|
|
|
1
|
-
import { CssBoxShadow, CssShadow,
|
|
1
|
+
import { CssBoxShadow, CssShadow, CssCalcSize, CssQuad, CssDual, CssSliceInset } from "../Interfaces/css.types";
|
|
2
|
+
import { CssBackgroundImage } from "../Theme";
|
|
2
3
|
interface ParsedShadow {
|
|
3
4
|
offset: UDim2;
|
|
4
5
|
blurRadius: UDim;
|
|
5
6
|
spread: UDim2;
|
|
6
7
|
}
|
|
8
|
+
interface ParsedQuad {
|
|
9
|
+
top: number;
|
|
10
|
+
right: number;
|
|
11
|
+
bottom: number;
|
|
12
|
+
left: number;
|
|
13
|
+
}
|
|
14
|
+
interface ParsedSliceInset {
|
|
15
|
+
x1: number;
|
|
16
|
+
y1: number;
|
|
17
|
+
x2: number;
|
|
18
|
+
y2: number;
|
|
19
|
+
}
|
|
7
20
|
export declare class CssHelper {
|
|
8
21
|
static parseCssShadow(value: CssShadow): ParsedShadow | undefined;
|
|
9
22
|
private static isZero;
|
|
10
|
-
static parseCssSize(value:
|
|
23
|
+
static parseCssSize(value: CssCalcSize): UDim;
|
|
24
|
+
static parseCssQuad(value: CssQuad): ParsedQuad;
|
|
25
|
+
private static toRawPixels;
|
|
26
|
+
static parseCssSliceInset(value: CssSliceInset): ParsedSliceInset;
|
|
27
|
+
static parseCssDual(value: CssDual): UDim2;
|
|
11
28
|
static ResolveShadow(shadow: CssBoxShadow): React.InstanceProps<UIShadow>;
|
|
29
|
+
static resolveBackgroundImage(value: Partial<CssBackgroundImage> | undefined): {
|
|
30
|
+
Image?: string;
|
|
31
|
+
ImageColor3?: Color3;
|
|
32
|
+
ImageTransparency?: number;
|
|
33
|
+
ScaleType?: CssBackgroundImage["size"];
|
|
34
|
+
SliceCenter?: Rect;
|
|
35
|
+
SliceScale?: number;
|
|
36
|
+
TileSize?: UDim2;
|
|
37
|
+
};
|
|
12
38
|
}
|
|
13
39
|
export {};
|
|
@@ -86,6 +86,24 @@ 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
|
+
local minusParts = string.split(value, " - ")
|
|
96
|
+
if #minusParts == 2 then
|
|
97
|
+
local scale = self:parseCssSize(minusParts[1]).Scale
|
|
98
|
+
local offset = self:parseCssSize(minusParts[2]).Offset
|
|
99
|
+
return UDim.new(scale, -offset)
|
|
100
|
+
end
|
|
101
|
+
local plusParts = string.split(value, " + ")
|
|
102
|
+
if #plusParts == 2 then
|
|
103
|
+
local scale = self:parseCssSize(plusParts[1]).Scale
|
|
104
|
+
local offset = self:parseCssSize(plusParts[2]).Offset
|
|
105
|
+
return UDim.new(scale, offset)
|
|
106
|
+
end
|
|
89
107
|
if string.sub(value, -1) == "%" then
|
|
90
108
|
local _condition = tonumber(string.sub(value, 1, -2))
|
|
91
109
|
if _condition == nil then
|
|
@@ -108,6 +126,179 @@ do
|
|
|
108
126
|
end
|
|
109
127
|
return UDim.new(0, _condition)
|
|
110
128
|
end
|
|
129
|
+
function CssHelper:parseCssQuad(value)
|
|
130
|
+
local _value = value
|
|
131
|
+
if type(_value) == "number" then
|
|
132
|
+
local size = self:parseCssSize(value).Offset
|
|
133
|
+
return {
|
|
134
|
+
top = size,
|
|
135
|
+
right = size,
|
|
136
|
+
bottom = size,
|
|
137
|
+
left = size,
|
|
138
|
+
}
|
|
139
|
+
end
|
|
140
|
+
local _exp = string.split(value, " ")
|
|
141
|
+
-- ▼ ReadonlyArray.filter ▼
|
|
142
|
+
local _newValue = {}
|
|
143
|
+
local _callback = function(part)
|
|
144
|
+
return #part > 0
|
|
145
|
+
end
|
|
146
|
+
local _length = 0
|
|
147
|
+
for _k, _v in _exp do
|
|
148
|
+
if _callback(_v, _k - 1, _exp) == true then
|
|
149
|
+
_length += 1
|
|
150
|
+
_newValue[_length] = _v
|
|
151
|
+
end
|
|
152
|
+
end
|
|
153
|
+
-- ▲ ReadonlyArray.filter ▲
|
|
154
|
+
local parts = _newValue
|
|
155
|
+
local _self = self
|
|
156
|
+
local _condition = parts[1]
|
|
157
|
+
if _condition == nil then
|
|
158
|
+
_condition = "0"
|
|
159
|
+
end
|
|
160
|
+
local top = _self:parseCssSize(_condition).Offset
|
|
161
|
+
local _self_1 = self
|
|
162
|
+
local _condition_1 = parts[2]
|
|
163
|
+
if _condition_1 == nil then
|
|
164
|
+
_condition_1 = parts[1]
|
|
165
|
+
if _condition_1 == nil then
|
|
166
|
+
_condition_1 = "0"
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
local right = _self_1:parseCssSize(_condition_1).Offset
|
|
170
|
+
local _self_2 = self
|
|
171
|
+
local _condition_2 = parts[3]
|
|
172
|
+
if _condition_2 == nil then
|
|
173
|
+
_condition_2 = parts[1]
|
|
174
|
+
if _condition_2 == nil then
|
|
175
|
+
_condition_2 = "0"
|
|
176
|
+
end
|
|
177
|
+
end
|
|
178
|
+
local bottom = _self_2:parseCssSize(_condition_2).Offset
|
|
179
|
+
local _self_3 = self
|
|
180
|
+
local _condition_3 = parts[4]
|
|
181
|
+
if _condition_3 == nil then
|
|
182
|
+
_condition_3 = parts[2]
|
|
183
|
+
if _condition_3 == nil then
|
|
184
|
+
_condition_3 = parts[1]
|
|
185
|
+
if _condition_3 == nil then
|
|
186
|
+
_condition_3 = "0"
|
|
187
|
+
end
|
|
188
|
+
end
|
|
189
|
+
end
|
|
190
|
+
local left = _self_3:parseCssSize(_condition_3).Offset
|
|
191
|
+
return {
|
|
192
|
+
top = top,
|
|
193
|
+
right = right,
|
|
194
|
+
bottom = bottom,
|
|
195
|
+
left = left,
|
|
196
|
+
}
|
|
197
|
+
end
|
|
198
|
+
function CssHelper:toRawPixels(value)
|
|
199
|
+
local _value = value
|
|
200
|
+
if type(_value) == "number" then
|
|
201
|
+
return value
|
|
202
|
+
end
|
|
203
|
+
if string.sub(value, -1) == "%" then
|
|
204
|
+
local _condition = tonumber(string.sub(value, 1, -2))
|
|
205
|
+
if _condition == nil then
|
|
206
|
+
_condition = 0
|
|
207
|
+
end
|
|
208
|
+
return _condition
|
|
209
|
+
end
|
|
210
|
+
if string.sub(value, -2) == "px" then
|
|
211
|
+
local _condition = tonumber(string.sub(value, 1, -3))
|
|
212
|
+
if _condition == nil then
|
|
213
|
+
_condition = 0
|
|
214
|
+
end
|
|
215
|
+
return _condition
|
|
216
|
+
end
|
|
217
|
+
local _condition = tonumber(value)
|
|
218
|
+
if _condition == nil then
|
|
219
|
+
_condition = 0
|
|
220
|
+
end
|
|
221
|
+
return _condition
|
|
222
|
+
end
|
|
223
|
+
function CssHelper:parseCssSliceInset(value)
|
|
224
|
+
local _exp = string.split(value, " ")
|
|
225
|
+
-- ▼ ReadonlyArray.filter ▼
|
|
226
|
+
local _newValue = {}
|
|
227
|
+
local _callback = function(part)
|
|
228
|
+
return #part > 0
|
|
229
|
+
end
|
|
230
|
+
local _length = 0
|
|
231
|
+
for _k, _v in _exp do
|
|
232
|
+
if _callback(_v, _k - 1, _exp) == true then
|
|
233
|
+
_length += 1
|
|
234
|
+
_newValue[_length] = _v
|
|
235
|
+
end
|
|
236
|
+
end
|
|
237
|
+
-- ▲ ReadonlyArray.filter ▲
|
|
238
|
+
local parts = _newValue
|
|
239
|
+
-- ▼ ReadonlyArray.map ▼
|
|
240
|
+
local _newValue_1 = table.create(#parts)
|
|
241
|
+
local _callback_1 = function(part)
|
|
242
|
+
return self:toRawPixels(part)
|
|
243
|
+
end
|
|
244
|
+
for _k, _v in parts do
|
|
245
|
+
_newValue_1[_k] = _callback_1(_v, _k - 1, parts)
|
|
246
|
+
end
|
|
247
|
+
-- ▲ ReadonlyArray.map ▲
|
|
248
|
+
local pixels = _newValue_1
|
|
249
|
+
if #pixels == 2 then
|
|
250
|
+
return {
|
|
251
|
+
x1 = pixels[1],
|
|
252
|
+
y1 = pixels[1],
|
|
253
|
+
x2 = pixels[2],
|
|
254
|
+
y2 = pixels[2],
|
|
255
|
+
}
|
|
256
|
+
end
|
|
257
|
+
return {
|
|
258
|
+
x1 = pixels[1],
|
|
259
|
+
y1 = pixels[2],
|
|
260
|
+
x2 = pixels[3],
|
|
261
|
+
y2 = pixels[4],
|
|
262
|
+
}
|
|
263
|
+
end
|
|
264
|
+
function CssHelper:parseCssDual(value)
|
|
265
|
+
local _value = value
|
|
266
|
+
if type(_value) == "number" then
|
|
267
|
+
local size = self:parseCssSize(value)
|
|
268
|
+
return UDim2.new(size, size)
|
|
269
|
+
end
|
|
270
|
+
local _exp = string.split(value, " ")
|
|
271
|
+
-- ▼ ReadonlyArray.filter ▼
|
|
272
|
+
local _newValue = {}
|
|
273
|
+
local _callback = function(part)
|
|
274
|
+
return #part > 0
|
|
275
|
+
end
|
|
276
|
+
local _length = 0
|
|
277
|
+
for _k, _v in _exp do
|
|
278
|
+
if _callback(_v, _k - 1, _exp) == true then
|
|
279
|
+
_length += 1
|
|
280
|
+
_newValue[_length] = _v
|
|
281
|
+
end
|
|
282
|
+
end
|
|
283
|
+
-- ▲ ReadonlyArray.filter ▲
|
|
284
|
+
local parts = _newValue
|
|
285
|
+
local _self = self
|
|
286
|
+
local _condition = parts[1]
|
|
287
|
+
if _condition == nil then
|
|
288
|
+
_condition = "0"
|
|
289
|
+
end
|
|
290
|
+
local x = _self:parseCssSize(_condition)
|
|
291
|
+
local _self_1 = self
|
|
292
|
+
local _condition_1 = parts[2]
|
|
293
|
+
if _condition_1 == nil then
|
|
294
|
+
_condition_1 = parts[1]
|
|
295
|
+
if _condition_1 == nil then
|
|
296
|
+
_condition_1 = "0"
|
|
297
|
+
end
|
|
298
|
+
end
|
|
299
|
+
local y = _self_1:parseCssSize(_condition_1)
|
|
300
|
+
return UDim2.new(x, y)
|
|
301
|
+
end
|
|
111
302
|
function CssHelper:ResolveShadow(shadow)
|
|
112
303
|
local offset = self:parseCssShadow(shadow.shadow)
|
|
113
304
|
local _object = {}
|
|
@@ -133,6 +324,23 @@ do
|
|
|
133
324
|
_object.Transparency = shadow.transparency
|
|
134
325
|
return _object
|
|
135
326
|
end
|
|
327
|
+
function CssHelper:resolveBackgroundImage(value)
|
|
328
|
+
if value == nil then
|
|
329
|
+
return {}
|
|
330
|
+
end
|
|
331
|
+
local slice = if value.slice ~= nil then self:parseCssSliceInset(value.slice) else nil
|
|
332
|
+
local _object = {}
|
|
333
|
+
local _left = "Image"
|
|
334
|
+
local _image = value.image
|
|
335
|
+
_object[_left] = if type(_image) == "number" then `rbxassetid://{value.image}` else value.image
|
|
336
|
+
_object.ImageColor3 = value.tintColor
|
|
337
|
+
_object.ImageTransparency = value.transparency
|
|
338
|
+
_object.ScaleType = if slice ~= nil then Enum.ScaleType.Slice else (value.size or Enum.ScaleType.Stretch)
|
|
339
|
+
_object.SliceCenter = if slice ~= nil then Rect.new(slice.x1, slice.y1, slice.x2, slice.y2) else nil
|
|
340
|
+
_object.SliceScale = value.sliceScale
|
|
341
|
+
_object.TileSize = if value.tileSize ~= nil then self:parseCssDual(value.tileSize) else nil
|
|
342
|
+
return _object
|
|
343
|
+
end
|
|
136
344
|
end
|
|
137
345
|
return {
|
|
138
346
|
CssHelper = CssHelper,
|
package/out/Helpers/index.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ export * from './breakpoint.helper';
|
|
|
2
2
|
export * from './color.helper';
|
|
3
3
|
export * from './css.helper';
|
|
4
4
|
export * from './gui.helper';
|
|
5
|
+
export * from './input.helper';
|
|
5
6
|
export * from './size.helper';
|
|
6
7
|
export * from './spacing.helper';
|
|
7
8
|
export * from './typography.helper';
|
package/out/Helpers/init.luau
CHANGED
|
@@ -13,6 +13,9 @@ end
|
|
|
13
13
|
for _k, _v in TS.import(script, script, "gui.helper") or {} do
|
|
14
14
|
exports[_k] = _v
|
|
15
15
|
end
|
|
16
|
+
for _k, _v in TS.import(script, script, "input.helper") or {} do
|
|
17
|
+
exports[_k] = _v
|
|
18
|
+
end
|
|
16
19
|
for _k, _v in TS.import(script, script, "size.helper") or {} do
|
|
17
20
|
exports[_k] = _v
|
|
18
21
|
end
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { Binding } from "@rbxts/react";
|
|
2
|
-
import { CssSize
|
|
2
|
+
import { CssSize } from "../Interfaces/css.types";
|
|
3
|
+
import { Breakpoint, ResponsiveValue } from "../Interfaces/responsive.types";
|
|
4
|
+
import { SizeElementProps, PositionElementProps } from "../Interfaces/element.props";
|
|
3
5
|
export declare class SizeHelper {
|
|
4
6
|
static GetSize(props: SizeElementProps, defaultSize?: UDim2): UDim2 | Binding<UDim2>;
|
|
5
7
|
static GetPosition(props: PositionElementProps): UDim2 | Binding<UDim2>;
|