@k9kbdev/roblox-css 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/LICENSE +15 -0
  2. package/README.md +245 -0
  3. package/default.project.json +6 -0
  4. package/out/index.d.ts +35 -0
  5. package/out/init.luau +57 -0
  6. package/out/logger.d.ts +23 -0
  7. package/out/logger.luau +73 -0
  8. package/out/primitives/Box.d.ts +23 -0
  9. package/out/primitives/Box.luau +103 -0
  10. package/out/primitives/Button.d.ts +62 -0
  11. package/out/primitives/Button.luau +170 -0
  12. package/out/primitives/Image.d.ts +37 -0
  13. package/out/primitives/Image.luau +79 -0
  14. package/out/primitives/InlineText.d.ts +25 -0
  15. package/out/primitives/InlineText.luau +273 -0
  16. package/out/primitives/Input.d.ts +59 -0
  17. package/out/primitives/Input.luau +126 -0
  18. package/out/primitives/MotionBox.d.ts +15 -0
  19. package/out/primitives/MotionBox.luau +69 -0
  20. package/out/primitives/MotionButton.d.ts +15 -0
  21. package/out/primitives/MotionButton.luau +146 -0
  22. package/out/primitives/MotionImage.d.ts +13 -0
  23. package/out/primitives/MotionImage.luau +70 -0
  24. package/out/primitives/MotionText.d.ts +12 -0
  25. package/out/primitives/MotionText.luau +116 -0
  26. package/out/primitives/MotionUIScale.d.ts +9 -0
  27. package/out/primitives/MotionUIScale.luau +48 -0
  28. package/out/primitives/ScrollBox.d.ts +25 -0
  29. package/out/primitives/ScrollBox.luau +69 -0
  30. package/out/primitives/Text.d.ts +50 -0
  31. package/out/primitives/Text.luau +139 -0
  32. package/out/primitives/usePercentageConstraints.d.ts +3 -0
  33. package/out/primitives/usePercentageConstraints.luau +112 -0
  34. package/out/primitives/useVariantResolver.d.ts +13 -0
  35. package/out/primitives/useVariantResolver.luau +260 -0
  36. package/out/styles/CSSTypes.d.ts +96 -0
  37. package/out/styles/ParentSizeContext.d.ts +6 -0
  38. package/out/styles/ParentSizeContext.luau +13 -0
  39. package/out/styles/colorParser.d.ts +28 -0
  40. package/out/styles/colorParser.luau +229 -0
  41. package/out/styles/dimensionParser.d.ts +49 -0
  42. package/out/styles/dimensionParser.luau +205 -0
  43. package/out/styles/gradientParser.d.ts +9 -0
  44. package/out/styles/gradientParser.luau +434 -0
  45. package/out/styles/namedColors.d.ts +7 -0
  46. package/out/styles/namedColors.luau +162 -0
  47. package/out/styles/transitions.d.ts +18 -0
  48. package/out/styles/transitions.luau +19 -0
  49. package/out/styles/webStyle.d.ts +74 -0
  50. package/out/styles/webStyle.luau +973 -0
  51. package/out/types.d.ts +4 -0
  52. package/out/types.luau +3 -0
  53. package/out/utils/parseInlineImages.d.ts +20 -0
  54. package/out/utils/parseInlineImages.luau +93 -0
  55. package/package.json +56 -0
@@ -0,0 +1,126 @@
1
+ -- Compiled with roblox-ts v3.0.0
2
+ local TS = _G[script]
3
+ --[[
4
+ *
5
+ * Input.tsx — <input> equivalent for Roblox.
6
+ *
7
+ * Renders a <textbox> with web-like style props.
8
+ * Extends the core webStyle translation by adding input-specific mappings.
9
+ * Automatically maps web-like placeholder and onChange props to their
10
+ * Roblox equivalents for a more familiar developer experience.
11
+ *
12
+ * Input mappings:
13
+ * Web Property → Roblox Output
14
+ * ─────────────────────────────────────────────────────────
15
+ * placeholder → PlaceholderText (string)
16
+ * onChange(text) → Change.Text (event listener)
17
+ * style → (Maps via webStyle)
18
+ *
19
+ * Maps to: HTML <input> → Roblox <textbox>
20
+ *
21
+ * Usage:
22
+ * <Input
23
+ * placeholder="Enter your name..."
24
+ * onChange={(text) => print("User typed:", text)}
25
+ * style={{ width: 200, height: 40, backgroundColor: "#FFFFFF" }}
26
+ * />
27
+
28
+ ]]
29
+ local React = TS.import(script, TS.getModule(script, "@rbxts", "react"))
30
+ local webStyle = TS.import(script, script.Parent.Parent, "styles", "webStyle").webStyle
31
+ --[[
32
+ *
33
+ * Branded InputProps — the `_inputProps` brand ensures strict nominal typing.
34
+ * This prevents accidental bypasses or incorrect prop structures.
35
+
36
+ ]]
37
+ --* Helper to construct a branded InputProps.
38
+ local function makeInputProps(props)
39
+ return props
40
+ end
41
+ --[[
42
+ *
43
+ * Input component — The primary component for receiving user text input.
44
+ *
45
+ * Maps to: HTML <input> → Roblox <textbox>
46
+ * Renders a native <textbox> while mapping web input props to Roblox properties.
47
+
48
+ ]]
49
+ local Input = React.forwardRef(function(props, ref)
50
+ local style = props.style
51
+ local children = props.children
52
+ local placeholder = props.placeholder
53
+ local onChange = props.onChange
54
+ local defaultProps = {
55
+ BackgroundTransparency = 1,
56
+ Text = "",
57
+ }
58
+ local _object = table.clone(props)
59
+ setmetatable(_object, nil)
60
+ local explicitProps = _object
61
+ explicitProps.style = nil
62
+ explicitProps.children = nil
63
+ explicitProps.placeholder = nil
64
+ explicitProps.onChange = nil
65
+ if placeholder ~= nil then
66
+ explicitProps.PlaceholderText = placeholder
67
+ end
68
+ -- Merge user-provided Change listeners with our internal Text handler
69
+ -- to avoid silently overwriting user event handlers.
70
+ local userChange = (props.Change) or {}
71
+ local _object_1 = table.clone(userChange)
72
+ setmetatable(_object_1, nil)
73
+ local mergedChange = _object_1
74
+ if onChange then
75
+ mergedChange.Text = function(rbx)
76
+ onChange(rbx.Text)
77
+ -- Forward to user handler if present
78
+ local userHandler = userChange.Text
79
+ if userHandler ~= nil then
80
+ userHandler(rbx)
81
+ end
82
+ end
83
+ end
84
+ explicitProps.Change = nil
85
+ local hasChange = onChange ~= nil or (next(userChange)) ~= nil
86
+ if style then
87
+ local parsed = webStyle(style)
88
+ local _attributes = {
89
+ ref = ref,
90
+ }
91
+ for _k, _v in defaultProps do
92
+ _attributes[_k] = _v
93
+ end
94
+ for _k, _v in (parsed.props) do
95
+ _attributes[_k] = _v
96
+ end
97
+ for _k, _v in explicitProps do
98
+ _attributes[_k] = _v
99
+ end
100
+ for _k, _v in (if hasChange then {
101
+ Change = mergedChange,
102
+ } else {}) do
103
+ _attributes[_k] = _v
104
+ end
105
+ return React.createElement("textbox", _attributes, parsed.children, children)
106
+ end
107
+ local _attributes = {
108
+ ref = ref,
109
+ }
110
+ for _k, _v in defaultProps do
111
+ _attributes[_k] = _v
112
+ end
113
+ for _k, _v in explicitProps do
114
+ _attributes[_k] = _v
115
+ end
116
+ for _k, _v in (if hasChange then {
117
+ Change = mergedChange,
118
+ } else {}) do
119
+ _attributes[_k] = _v
120
+ end
121
+ return React.createElement("textbox", _attributes, children)
122
+ end)
123
+ return {
124
+ makeInputProps = makeInputProps,
125
+ Input = Input,
126
+ }
@@ -0,0 +1,15 @@
1
+ import React from "@rbxts/react";
2
+ import { CSSProperties } from "../styles/webStyle";
3
+ import { MotionProps } from "./useVariantResolver";
4
+ export type MotionBoxProps = React.PropsWithChildren<React.ComponentProps<"frame">> & {
5
+ style?: CSSProperties;
6
+ } & MotionProps & {
7
+ readonly _motionBoxProps?: unique symbol;
8
+ };
9
+ /**
10
+ * MotionBox component — Declarative animated equivalent of Box.
11
+ *
12
+ * Exposes Framer Motion-like props (`animate`, `variants`, `transition`)
13
+ * over the base `webStyle` layout engine.
14
+ */
15
+ export declare const MotionBox: React.ForwardRefExoticComponent<Omit<MotionBoxProps, "ref"> & React.RefAttributes<Frame>>;
@@ -0,0 +1,69 @@
1
+ -- Compiled with roblox-ts v3.0.0
2
+ local TS = _G[script]
3
+ local _react = TS.import(script, TS.getModule(script, "@rbxts", "react"))
4
+ local React = _react
5
+ local forwardRef = _react.forwardRef
6
+ local webStyle = TS.import(script, script.Parent.Parent, "styles", "webStyle").webStyle
7
+ local useVariantResolver = TS.import(script, script.Parent, "useVariantResolver").useVariantResolver
8
+ --[[
9
+ *
10
+ * MotionBox component — Declarative animated equivalent of Box.
11
+ *
12
+ * Exposes Framer Motion-like props (`animate`, `variants`, `transition`)
13
+ * over the base `webStyle` layout engine.
14
+
15
+ ]]
16
+ local MotionBox = forwardRef(function(props, ref)
17
+ local animate = props.animate
18
+ local initial = props.initial
19
+ local variants = props.variants
20
+ local transition = props.transition
21
+ local style = props.style
22
+ local children = props.children
23
+ local _binding = useVariantResolver(animate, initial, variants, transition)
24
+ local animatedProps = _binding.animatedProps
25
+ local staticProps = _binding.staticProps
26
+ local defaultProps = {
27
+ BackgroundTransparency = 1,
28
+ BorderSizePixel = 0,
29
+ }
30
+ local _object = table.clone(props)
31
+ setmetatable(_object, nil)
32
+ local explicitProps = _object
33
+ explicitProps.animate = nil
34
+ explicitProps.initial = nil
35
+ explicitProps.variants = nil
36
+ explicitProps.transition = nil
37
+ explicitProps.style = nil
38
+ explicitProps.children = nil
39
+ explicitProps._motionBoxProps = nil
40
+ local parsedStyleProps = {}
41
+ local parsedStyleChildren = {}
42
+ if style then
43
+ local parsed = webStyle(style)
44
+ parsedStyleProps = parsed.props
45
+ parsedStyleChildren = parsed.children
46
+ end
47
+ local _attributes = {
48
+ ref = ref,
49
+ }
50
+ for _k, _v in defaultProps do
51
+ _attributes[_k] = _v
52
+ end
53
+ for _k, _v in parsedStyleProps do
54
+ _attributes[_k] = _v
55
+ end
56
+ for _k, _v in explicitProps do
57
+ _attributes[_k] = _v
58
+ end
59
+ for _k, _v in staticProps do
60
+ _attributes[_k] = _v
61
+ end
62
+ for _k, _v in animatedProps do
63
+ _attributes[_k] = _v
64
+ end
65
+ return React.createElement("frame", _attributes, parsedStyleChildren, children)
66
+ end)
67
+ return {
68
+ MotionBox = MotionBox,
69
+ }
@@ -0,0 +1,15 @@
1
+ import React from "@rbxts/react";
2
+ import { CSSProperties } from "../styles/CSSTypes";
3
+ import { MotionProps } from "./useVariantResolver";
4
+ export type MotionButtonProps = React.PropsWithChildren<React.ComponentProps<"textbutton">> & {
5
+ style?: CSSProperties;
6
+ onClick?: () => void;
7
+ onMouseEnter?: () => void;
8
+ onMouseLeave?: () => void;
9
+ } & MotionProps & {
10
+ readonly _motionButtonProps?: unique symbol;
11
+ };
12
+ /**
13
+ * MotionButton component — Declarative animated equivalent of Button.
14
+ */
15
+ export declare const MotionButton: React.ForwardRefExoticComponent<Omit<MotionButtonProps, "ref"> & React.RefAttributes<TextButton>>;
@@ -0,0 +1,146 @@
1
+ -- Compiled with roblox-ts v3.0.0
2
+ local TS = _G[script]
3
+ local _react = TS.import(script, TS.getModule(script, "@rbxts", "react"))
4
+ local React = _react
5
+ local forwardRef = _react.forwardRef
6
+ local webStyle = TS.import(script, script.Parent.Parent, "styles", "webStyle").webStyle
7
+ local useVariantResolver = TS.import(script, script.Parent, "useVariantResolver").useVariantResolver
8
+ local function buttonParser(style)
9
+ -- Delegate entirely to webStyle() which already handles all typography
10
+ -- properties (fontSize, textAlign, whiteSpace, color, fontFamily, fontWeight).
11
+ -- Previously this duplicated that logic with a different default font (SourceSansPro
12
+ -- vs BuilderSans), causing an inconsistency.
13
+ local parsed = webStyle(style)
14
+ return parsed.props
15
+ end
16
+ --[[
17
+ *
18
+ * MotionButton component — Declarative animated equivalent of Button.
19
+
20
+ ]]
21
+ local MotionButton = forwardRef(function(props, ref)
22
+ local animate = props.animate
23
+ local initial = props.initial
24
+ local variants = props.variants
25
+ local transition = props.transition
26
+ local style = props.style
27
+ local children = props.children
28
+ local onClick = props.onClick
29
+ local onMouseEnter = props.onMouseEnter
30
+ local onMouseLeave = props.onMouseLeave
31
+ local _binding = useVariantResolver(animate, initial, variants, transition, buttonParser)
32
+ local animatedProps = _binding.animatedProps
33
+ local staticProps = _binding.staticProps
34
+ local defaultProps = {
35
+ BackgroundTransparency = 1,
36
+ TextWrapped = true,
37
+ Text = "",
38
+ AutoButtonColor = false,
39
+ }
40
+ if props.Size == nil and (not style or (style.width == nil and style.height == nil)) then
41
+ defaultProps.AutomaticSize = Enum.AutomaticSize.XY
42
+ end
43
+ local _object = table.clone(props)
44
+ setmetatable(_object, nil)
45
+ local explicitProps = _object
46
+ explicitProps.animate = nil
47
+ explicitProps.initial = nil
48
+ explicitProps.variants = nil
49
+ explicitProps.transition = nil
50
+ explicitProps.style = nil
51
+ explicitProps.children = nil
52
+ explicitProps.onClick = nil
53
+ explicitProps.onMouseEnter = nil
54
+ explicitProps.onMouseLeave = nil
55
+ explicitProps._motionButtonProps = nil
56
+ -- 3. Map primitive children directly to the Text property
57
+ if type(children) == "string" or type(children) == "number" then
58
+ explicitProps.Text = tostring(children)
59
+ end
60
+ local parsedStyleProps = {}
61
+ local parsedStyleChildren = {}
62
+ -- 4. If a style object is provided, compile it and extract typography mappings
63
+ if style then
64
+ local parsed = webStyle(style)
65
+ parsedStyleProps = parsed.props
66
+ parsedStyleChildren = parsed.children
67
+ -- wordBreak — inject zero-width spaces or newlines for character-level wrapping
68
+ if style.wordBreak ~= nil then
69
+ if style.wordBreak == "break-all" then
70
+ local _text = explicitProps.Text
71
+ if type(_text) == "string" then
72
+ explicitProps.Text = table.concat(string.split(explicitProps.Text, ""), "\u{200B}")
73
+ end
74
+ elseif style.wordBreak == "keep-all" then
75
+ local _text = explicitProps.Text
76
+ if type(_text) == "string" then
77
+ explicitProps.Text = table.concat(string.split(explicitProps.Text, " "), "\n")
78
+ end
79
+ end
80
+ end
81
+ -- textTransform — mutate text content
82
+ if style.textTransform ~= nil and style.textTransform ~= "none" then
83
+ local _text = explicitProps.Text
84
+ if type(_text) == "string" then
85
+ if style.textTransform == "uppercase" then
86
+ explicitProps.Text = string.upper((explicitProps.Text))
87
+ elseif style.textTransform == "lowercase" then
88
+ explicitProps.Text = string.lower((explicitProps.Text))
89
+ elseif style.textTransform == "capitalize" then
90
+ explicitProps.Text = (string.gsub((explicitProps.Text), "%w+", function(word)
91
+ return string.upper(string.sub(word, 1, 1)) .. string.sub(word, 2)
92
+ end))
93
+ end
94
+ end
95
+ end
96
+ -- textDecoration — wrap text in rich text tags (RichText=true is set by webStyle)
97
+ if style.textDecoration ~= nil and style.textDecoration ~= "none" then
98
+ local _text = explicitProps.Text
99
+ if type(_text) == "string" then
100
+ if style.textDecoration == "underline" then
101
+ explicitProps.Text = `<u>{explicitProps.Text}</u>`
102
+ elseif style.textDecoration == "line-through" then
103
+ explicitProps.Text = `<s>{explicitProps.Text}</s>`
104
+ end
105
+ end
106
+ end
107
+ end
108
+ -- 5. Map React-style event props to the Roblox Event table
109
+ local existingEvents = (props.Event) or {}
110
+ local _object_1 = table.clone(existingEvents)
111
+ setmetatable(_object_1, nil)
112
+ local mergedEvents = _object_1
113
+ if onClick ~= nil then
114
+ mergedEvents.Activated = onClick
115
+ end
116
+ if onMouseEnter ~= nil then
117
+ mergedEvents.MouseEnter = onMouseEnter
118
+ end
119
+ if onMouseLeave ~= nil then
120
+ mergedEvents.MouseLeave = onMouseLeave
121
+ end
122
+ explicitProps.Event = mergedEvents
123
+ -- 6. Render the native textbutton with merged properties and children
124
+ local _attributes = {
125
+ ref = ref,
126
+ }
127
+ for _k, _v in defaultProps do
128
+ _attributes[_k] = _v
129
+ end
130
+ for _k, _v in parsedStyleProps do
131
+ _attributes[_k] = _v
132
+ end
133
+ for _k, _v in explicitProps do
134
+ _attributes[_k] = _v
135
+ end
136
+ for _k, _v in staticProps do
137
+ _attributes[_k] = _v
138
+ end
139
+ for _k, _v in animatedProps do
140
+ _attributes[_k] = _v
141
+ end
142
+ return React.createElement("textbutton", _attributes, parsedStyleChildren, if type(children) == "string" or type(children) == "number" then nil else children)
143
+ end)
144
+ return {
145
+ MotionButton = MotionButton,
146
+ }
@@ -0,0 +1,13 @@
1
+ import React from "@rbxts/react";
2
+ import { CSSProperties } from "../styles/CSSTypes";
3
+ import { MotionProps } from "./useVariantResolver";
4
+ export type MotionImageProps = React.PropsWithChildren<React.ComponentProps<"imagelabel">> & {
5
+ style?: CSSProperties;
6
+ src?: string;
7
+ } & MotionProps & {
8
+ readonly _motionImageProps?: unique symbol;
9
+ };
10
+ /**
11
+ * MotionImage component — Declarative animated equivalent of Image.
12
+ */
13
+ export declare const MotionImage: React.ForwardRefExoticComponent<Omit<MotionImageProps, "ref"> & React.RefAttributes<ImageLabel>>;
@@ -0,0 +1,70 @@
1
+ -- Compiled with roblox-ts v3.0.0
2
+ local TS = _G[script]
3
+ local _react = TS.import(script, TS.getModule(script, "@rbxts", "react"))
4
+ local React = _react
5
+ local forwardRef = _react.forwardRef
6
+ local webStyle = TS.import(script, script.Parent.Parent, "styles", "webStyle").webStyle
7
+ local useVariantResolver = TS.import(script, script.Parent, "useVariantResolver").useVariantResolver
8
+ --[[
9
+ *
10
+ * MotionImage component — Declarative animated equivalent of Image.
11
+
12
+ ]]
13
+ local MotionImage = forwardRef(function(props, ref)
14
+ local animate = props.animate
15
+ local initial = props.initial
16
+ local variants = props.variants
17
+ local transition = props.transition
18
+ local style = props.style
19
+ local src = props.src
20
+ local children = props.children
21
+ local _binding = useVariantResolver(animate, initial, variants, transition)
22
+ local animatedProps = _binding.animatedProps
23
+ local staticProps = _binding.staticProps
24
+ local defaultProps = {
25
+ BackgroundTransparency = 1,
26
+ }
27
+ local _object = table.clone(props)
28
+ setmetatable(_object, nil)
29
+ local explicitProps = _object
30
+ explicitProps.animate = nil
31
+ explicitProps.initial = nil
32
+ explicitProps.variants = nil
33
+ explicitProps.transition = nil
34
+ explicitProps.style = nil
35
+ explicitProps.src = nil
36
+ explicitProps.children = nil
37
+ explicitProps._motionImageProps = nil
38
+ if src ~= nil then
39
+ explicitProps.Image = src
40
+ end
41
+ local parsedStyleProps = {}
42
+ local parsedStyleChildren = {}
43
+ if style then
44
+ local parsed = webStyle(style)
45
+ parsedStyleProps = parsed.props
46
+ parsedStyleChildren = parsed.children
47
+ end
48
+ local _attributes = {
49
+ ref = ref,
50
+ }
51
+ for _k, _v in defaultProps do
52
+ _attributes[_k] = _v
53
+ end
54
+ for _k, _v in parsedStyleProps do
55
+ _attributes[_k] = _v
56
+ end
57
+ for _k, _v in explicitProps do
58
+ _attributes[_k] = _v
59
+ end
60
+ for _k, _v in staticProps do
61
+ _attributes[_k] = _v
62
+ end
63
+ for _k, _v in animatedProps do
64
+ _attributes[_k] = _v
65
+ end
66
+ return React.createElement("imagelabel", _attributes, parsedStyleChildren, children)
67
+ end)
68
+ return {
69
+ MotionImage = MotionImage,
70
+ }
@@ -0,0 +1,12 @@
1
+ import React from "@rbxts/react";
2
+ import { CSSProperties } from "../styles/CSSTypes";
3
+ import { MotionProps } from "./useVariantResolver";
4
+ export type MotionTextProps = React.PropsWithChildren<React.ComponentProps<"textlabel">> & {
5
+ style?: CSSProperties;
6
+ } & MotionProps & {
7
+ readonly _motionTextProps?: unique symbol;
8
+ };
9
+ /**
10
+ * MotionText component — Declarative animated equivalent of Text.
11
+ */
12
+ export declare const MotionText: React.ForwardRefExoticComponent<Omit<MotionTextProps, "ref"> & React.RefAttributes<TextLabel>>;
@@ -0,0 +1,116 @@
1
+ -- Compiled with roblox-ts v3.0.0
2
+ local TS = _G[script]
3
+ local _react = TS.import(script, TS.getModule(script, "@rbxts", "react"))
4
+ local React = _react
5
+ local forwardRef = _react.forwardRef
6
+ local webStyle = TS.import(script, script.Parent.Parent, "styles", "webStyle").webStyle
7
+ local useVariantResolver = TS.import(script, script.Parent, "useVariantResolver").useVariantResolver
8
+ local function textParser(style)
9
+ return webStyle(style).props
10
+ end
11
+ --[[
12
+ *
13
+ * MotionText component — Declarative animated equivalent of Text.
14
+
15
+ ]]
16
+ local MotionText = forwardRef(function(props, ref)
17
+ local animate = props.animate
18
+ local initial = props.initial
19
+ local variants = props.variants
20
+ local transition = props.transition
21
+ local style = props.style
22
+ local children = props.children
23
+ local _binding = useVariantResolver(animate, initial, variants, transition, textParser)
24
+ local animatedProps = _binding.animatedProps
25
+ local staticProps = _binding.staticProps
26
+ local defaultProps = {
27
+ BackgroundTransparency = 1,
28
+ TextWrapped = true,
29
+ Text = "",
30
+ }
31
+ if props.Size == nil and (not style or (style.width == nil and style.height == nil)) then
32
+ defaultProps.AutomaticSize = Enum.AutomaticSize.XY
33
+ end
34
+ local _object = table.clone(props)
35
+ setmetatable(_object, nil)
36
+ local explicitProps = _object
37
+ explicitProps.animate = nil
38
+ explicitProps.initial = nil
39
+ explicitProps.variants = nil
40
+ explicitProps.transition = nil
41
+ explicitProps.style = nil
42
+ explicitProps.children = nil
43
+ explicitProps._motionTextProps = nil
44
+ if type(children) == "string" or type(children) == "number" then
45
+ explicitProps.Text = tostring(children)
46
+ end
47
+ local parsedStyleProps = {}
48
+ local parsedStyleChildren = {}
49
+ if style then
50
+ local parsed = webStyle(style)
51
+ parsedStyleProps = parsed.props
52
+ parsedStyleChildren = parsed.children
53
+ -- Specialized string manipulation for wordBreak
54
+ if style.wordBreak ~= nil then
55
+ if style.wordBreak == "break-all" then
56
+ local _text = explicitProps.Text
57
+ if type(_text) == "string" then
58
+ explicitProps.Text = table.concat(string.split(explicitProps.Text, ""), "\u{200B}")
59
+ end
60
+ elseif style.wordBreak == "keep-all" then
61
+ local _text = explicitProps.Text
62
+ if type(_text) == "string" then
63
+ explicitProps.Text = table.concat(string.split(explicitProps.Text, " "), "\n")
64
+ end
65
+ end
66
+ end
67
+ -- textTransform — mutate text content
68
+ if style.textTransform ~= nil and style.textTransform ~= "none" then
69
+ local _text = explicitProps.Text
70
+ if type(_text) == "string" then
71
+ if style.textTransform == "uppercase" then
72
+ explicitProps.Text = string.upper((explicitProps.Text))
73
+ elseif style.textTransform == "lowercase" then
74
+ explicitProps.Text = string.lower((explicitProps.Text))
75
+ elseif style.textTransform == "capitalize" then
76
+ explicitProps.Text = (string.gsub((explicitProps.Text), "%w+", function(word)
77
+ return string.upper(string.sub(word, 1, 1)) .. string.sub(word, 2)
78
+ end))
79
+ end
80
+ end
81
+ end
82
+ -- textDecoration — wrap text in rich text tags (RichText=true is set by webStyle)
83
+ if style.textDecoration ~= nil and style.textDecoration ~= "none" then
84
+ local _text = explicitProps.Text
85
+ if type(_text) == "string" then
86
+ if style.textDecoration == "underline" then
87
+ explicitProps.Text = `<u>{explicitProps.Text}</u>`
88
+ elseif style.textDecoration == "line-through" then
89
+ explicitProps.Text = `<s>{explicitProps.Text}</s>`
90
+ end
91
+ end
92
+ end
93
+ end
94
+ local _attributes = {
95
+ ref = ref,
96
+ }
97
+ for _k, _v in defaultProps do
98
+ _attributes[_k] = _v
99
+ end
100
+ for _k, _v in parsedStyleProps do
101
+ _attributes[_k] = _v
102
+ end
103
+ for _k, _v in explicitProps do
104
+ _attributes[_k] = _v
105
+ end
106
+ for _k, _v in staticProps do
107
+ _attributes[_k] = _v
108
+ end
109
+ for _k, _v in animatedProps do
110
+ _attributes[_k] = _v
111
+ end
112
+ return React.createElement("textlabel", _attributes, parsedStyleChildren, if type(children) == "string" or type(children) == "number" then nil else children)
113
+ end)
114
+ return {
115
+ MotionText = MotionText,
116
+ }
@@ -0,0 +1,9 @@
1
+ import React from "@rbxts/react";
2
+ import { MotionProps } from "./useVariantResolver";
3
+ export type MotionUIScaleProps = React.ComponentProps<"uiscale"> & MotionProps & {
4
+ readonly _motionUIScaleProps?: unique symbol;
5
+ };
6
+ /**
7
+ * MotionUIScale component — Declarative animated equivalent of UIScale.
8
+ */
9
+ export declare const MotionUIScale: React.ForwardRefExoticComponent<Omit<MotionUIScaleProps, "ref"> & React.RefAttributes<UIScale>>;
@@ -0,0 +1,48 @@
1
+ -- Compiled with roblox-ts v3.0.0
2
+ local TS = _G[script]
3
+ local _react = TS.import(script, TS.getModule(script, "@rbxts", "react"))
4
+ local React = _react
5
+ local forwardRef = _react.forwardRef
6
+ local useVariantResolver = TS.import(script, script.Parent, "useVariantResolver").useVariantResolver
7
+ --[[
8
+ *
9
+ * MotionUIScale component — Declarative animated equivalent of UIScale.
10
+
11
+ ]]
12
+ local MotionUIScale = forwardRef(function(props, ref)
13
+ local animate = props.animate
14
+ local initial = props.initial
15
+ local variants = props.variants
16
+ local transition = props.transition
17
+ -- We pass a dummy parser that just passes through styles,
18
+ -- because UIScale doesn't use CSS webStyle mappings.
19
+ local _binding = useVariantResolver(animate, initial, variants, transition, function(style)
20
+ return style
21
+ end)
22
+ local animatedProps = _binding.animatedProps
23
+ local staticProps = _binding.staticProps
24
+ local _object = table.clone(props)
25
+ setmetatable(_object, nil)
26
+ local uiscaleProps = _object
27
+ uiscaleProps.animate = nil
28
+ uiscaleProps.initial = nil
29
+ uiscaleProps.variants = nil
30
+ uiscaleProps.transition = nil
31
+ uiscaleProps._motionUIScaleProps = nil
32
+ local _attributes = {
33
+ ref = ref,
34
+ }
35
+ for _k, _v in uiscaleProps do
36
+ _attributes[_k] = _v
37
+ end
38
+ for _k, _v in staticProps do
39
+ _attributes[_k] = _v
40
+ end
41
+ for _k, _v in animatedProps do
42
+ _attributes[_k] = _v
43
+ end
44
+ return React.createElement("uiscale", _attributes)
45
+ end)
46
+ return {
47
+ MotionUIScale = MotionUIScale,
48
+ }
@@ -0,0 +1,25 @@
1
+ /**
2
+ * ScrollBox.tsx — A scrollable container component for Roblox.
3
+ *
4
+ * Provides a scrollable <div> equivalent that supports a web-like CSS syntax (`style` prop).
5
+ * It automatically translates CSS properties (e.g., `backgroundColor: "red"`) into
6
+ * Roblox engine equivalents (`BackgroundColor3`) and injects layout constraints
7
+ * like `UICorner`, `UIPadding`, `UIListLayout`, and `UIGridLayout` as child instances.
8
+ *
9
+ * Mirrors the architecture of Box.tsx but renders a native <scrollingframe> instead
10
+ * of a <frame>, with clean defaults for a modern scrolling experience.
11
+ *
12
+ * Usage:
13
+ * <ScrollBox style={{ width: "100%", height: "300px", display: "flex", gap: "8px" }}>
14
+ * <textlabel Text="Item 1" />
15
+ * <textlabel Text="Item 2" />
16
+ * </ScrollBox>
17
+ */
18
+ import React from "@rbxts/react";
19
+ import { CSSProperties } from "../styles/webStyle";
20
+ export type ScrollBoxProps = React.PropsWithChildren<React.ComponentProps<"scrollingframe">> & {
21
+ style?: CSSProperties;
22
+ } & {
23
+ readonly _scrollBoxProps?: unique symbol;
24
+ };
25
+ export declare const ScrollBox: React.ForwardRefExoticComponent<Omit<ScrollBoxProps, "ref"> & React.RefAttributes<ScrollingFrame>>;