@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.
- package/LICENSE +15 -0
- package/README.md +245 -0
- package/default.project.json +6 -0
- package/out/index.d.ts +35 -0
- package/out/init.luau +57 -0
- package/out/logger.d.ts +23 -0
- package/out/logger.luau +73 -0
- package/out/primitives/Box.d.ts +23 -0
- package/out/primitives/Box.luau +103 -0
- package/out/primitives/Button.d.ts +62 -0
- package/out/primitives/Button.luau +170 -0
- package/out/primitives/Image.d.ts +37 -0
- package/out/primitives/Image.luau +79 -0
- package/out/primitives/InlineText.d.ts +25 -0
- package/out/primitives/InlineText.luau +273 -0
- package/out/primitives/Input.d.ts +59 -0
- package/out/primitives/Input.luau +126 -0
- package/out/primitives/MotionBox.d.ts +15 -0
- package/out/primitives/MotionBox.luau +69 -0
- package/out/primitives/MotionButton.d.ts +15 -0
- package/out/primitives/MotionButton.luau +146 -0
- package/out/primitives/MotionImage.d.ts +13 -0
- package/out/primitives/MotionImage.luau +70 -0
- package/out/primitives/MotionText.d.ts +12 -0
- package/out/primitives/MotionText.luau +116 -0
- package/out/primitives/MotionUIScale.d.ts +9 -0
- package/out/primitives/MotionUIScale.luau +48 -0
- package/out/primitives/ScrollBox.d.ts +25 -0
- package/out/primitives/ScrollBox.luau +69 -0
- package/out/primitives/Text.d.ts +50 -0
- package/out/primitives/Text.luau +139 -0
- package/out/primitives/usePercentageConstraints.d.ts +3 -0
- package/out/primitives/usePercentageConstraints.luau +112 -0
- package/out/primitives/useVariantResolver.d.ts +13 -0
- package/out/primitives/useVariantResolver.luau +260 -0
- package/out/styles/CSSTypes.d.ts +96 -0
- package/out/styles/ParentSizeContext.d.ts +6 -0
- package/out/styles/ParentSizeContext.luau +13 -0
- package/out/styles/colorParser.d.ts +28 -0
- package/out/styles/colorParser.luau +229 -0
- package/out/styles/dimensionParser.d.ts +49 -0
- package/out/styles/dimensionParser.luau +205 -0
- package/out/styles/gradientParser.d.ts +9 -0
- package/out/styles/gradientParser.luau +434 -0
- package/out/styles/namedColors.d.ts +7 -0
- package/out/styles/namedColors.luau +162 -0
- package/out/styles/transitions.d.ts +18 -0
- package/out/styles/transitions.luau +19 -0
- package/out/styles/webStyle.d.ts +74 -0
- package/out/styles/webStyle.luau +973 -0
- package/out/types.d.ts +4 -0
- package/out/types.luau +3 -0
- package/out/utils/parseInlineImages.d.ts +20 -0
- package/out/utils/parseInlineImages.luau +93 -0
- package/package.json +56 -0
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
-- Compiled with roblox-ts v3.0.0
|
|
2
|
+
local TS = _G[script]
|
|
3
|
+
--[[
|
|
4
|
+
*
|
|
5
|
+
* Button.tsx — <button> equivalent for Roblox.
|
|
6
|
+
*
|
|
7
|
+
* Renders a <textbutton> with web-like style props.
|
|
8
|
+
* Delegates CSS→Roblox translation to webStyle(), and adds text-content
|
|
9
|
+
* manipulation features (textTransform, textDecoration, wordBreak) that
|
|
10
|
+
* require mutating the Text string before rendering.
|
|
11
|
+
* Typography mapping:
|
|
12
|
+
* CSS Property → Roblox Output
|
|
13
|
+
* ─────────────────────────────────────────────────────────
|
|
14
|
+
* fontSize → TextSize (number)
|
|
15
|
+
* fontFamily → FontFace (Font object, defaults to BuilderSans)
|
|
16
|
+
* fontWeight → FontFace weight (normal/bold/black → Regular/Bold/Heavy)
|
|
17
|
+
* textAlign → TextXAlignment (left/center/right)
|
|
18
|
+
* whiteSpace → TextWrapped (nowrap → false, otherwise true)
|
|
19
|
+
* color → TextColor3 (Color3) + TextTransparency
|
|
20
|
+
*
|
|
21
|
+
* Event mapping:
|
|
22
|
+
* React Prop → Roblox Output
|
|
23
|
+
* ─────────────────────────────────────────────────────────
|
|
24
|
+
* onClick → Event.Activated
|
|
25
|
+
* onMouseEnter → Event.MouseEnter
|
|
26
|
+
* onMouseLeave → Event.MouseLeave
|
|
27
|
+
*
|
|
28
|
+
* Maps to: HTML <button> → Roblox <textbutton>
|
|
29
|
+
*
|
|
30
|
+
* Usage:
|
|
31
|
+
* <Button
|
|
32
|
+
* style={{ backgroundColor: "#007BFF", padding: "10px 20px", color: "white", borderRadius: "4px" }}
|
|
33
|
+
* onClick={() => print("Clicked!")}
|
|
34
|
+
* >
|
|
35
|
+
* Submit
|
|
36
|
+
* </Button>
|
|
37
|
+
|
|
38
|
+
]]
|
|
39
|
+
local _react = TS.import(script, TS.getModule(script, "@rbxts", "react"))
|
|
40
|
+
local React = _react
|
|
41
|
+
local forwardRef = _react.forwardRef
|
|
42
|
+
local webStyle = TS.import(script, script.Parent.Parent, "styles", "webStyle").webStyle
|
|
43
|
+
--[[
|
|
44
|
+
*
|
|
45
|
+
* Branded ButtonProps — the `_buttonProps` brand ensures strict nominal typing.
|
|
46
|
+
* This prevents accidental bypasses or incorrect prop structures.
|
|
47
|
+
|
|
48
|
+
]]
|
|
49
|
+
--* Helper to construct a branded ButtonProps.
|
|
50
|
+
local function makeButtonProps(props)
|
|
51
|
+
return props
|
|
52
|
+
end
|
|
53
|
+
--[[
|
|
54
|
+
*
|
|
55
|
+
* Button component — The primary component for interactive clickable elements.
|
|
56
|
+
*
|
|
57
|
+
* Maps to: HTML <button> → Roblox <textbutton>
|
|
58
|
+
* Renders a native <textbutton>, mapping web styles and React-like event handlers (onClick, etc.).
|
|
59
|
+
|
|
60
|
+
]]
|
|
61
|
+
local Button = forwardRef(function(props, ref)
|
|
62
|
+
-- 1. Extract custom styling props, children, and event handlers
|
|
63
|
+
local style = props.style
|
|
64
|
+
local children = props.children
|
|
65
|
+
local onClick = props.onClick
|
|
66
|
+
local onMouseEnter = props.onMouseEnter
|
|
67
|
+
local onMouseLeave = props.onMouseLeave
|
|
68
|
+
local defaultProps = {
|
|
69
|
+
BackgroundTransparency = 1,
|
|
70
|
+
TextWrapped = true,
|
|
71
|
+
Text = "",
|
|
72
|
+
AutoButtonColor = false,
|
|
73
|
+
}
|
|
74
|
+
if props.Size == nil and (not style or (style.width == nil and style.height == nil)) then
|
|
75
|
+
defaultProps.AutomaticSize = Enum.AutomaticSize.XY
|
|
76
|
+
end
|
|
77
|
+
local _object = table.clone(props)
|
|
78
|
+
setmetatable(_object, nil)
|
|
79
|
+
local explicitProps = _object
|
|
80
|
+
explicitProps.style = nil
|
|
81
|
+
explicitProps.children = nil
|
|
82
|
+
explicitProps.onClick = nil
|
|
83
|
+
explicitProps.onMouseEnter = nil
|
|
84
|
+
explicitProps.onMouseLeave = nil
|
|
85
|
+
-- 3. Map primitive children directly to the Text property
|
|
86
|
+
if type(children) == "string" or type(children) == "number" then
|
|
87
|
+
explicitProps.Text = tostring(children)
|
|
88
|
+
end
|
|
89
|
+
local parsedStyleProps = {}
|
|
90
|
+
local parsedStyleChildren = {}
|
|
91
|
+
-- 4. If a style object is provided, compile it and extract typography mappings
|
|
92
|
+
if style then
|
|
93
|
+
local parsed = webStyle(style)
|
|
94
|
+
parsedStyleProps = parsed.props
|
|
95
|
+
parsedStyleChildren = parsed.children
|
|
96
|
+
-- wordBreak — inject zero-width spaces or newlines for character-level wrapping
|
|
97
|
+
if style.wordBreak ~= nil then
|
|
98
|
+
if style.wordBreak == "break-all" then
|
|
99
|
+
local _text = explicitProps.Text
|
|
100
|
+
if type(_text) == "string" then
|
|
101
|
+
explicitProps.Text = table.concat(string.split(explicitProps.Text, ""), "\u{200B}")
|
|
102
|
+
end
|
|
103
|
+
elseif style.wordBreak == "keep-all" then
|
|
104
|
+
local _text = explicitProps.Text
|
|
105
|
+
if type(_text) == "string" then
|
|
106
|
+
explicitProps.Text = table.concat(string.split(explicitProps.Text, " "), "\n")
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
-- textTransform — mutate text content
|
|
111
|
+
if style.textTransform ~= nil and style.textTransform ~= "none" then
|
|
112
|
+
local _text = explicitProps.Text
|
|
113
|
+
if type(_text) == "string" then
|
|
114
|
+
if style.textTransform == "uppercase" then
|
|
115
|
+
explicitProps.Text = string.upper((explicitProps.Text))
|
|
116
|
+
elseif style.textTransform == "lowercase" then
|
|
117
|
+
explicitProps.Text = string.lower((explicitProps.Text))
|
|
118
|
+
elseif style.textTransform == "capitalize" then
|
|
119
|
+
explicitProps.Text = (string.gsub((explicitProps.Text), "%w+", function(word)
|
|
120
|
+
return string.upper(string.sub(word, 1, 1)) .. string.sub(word, 2)
|
|
121
|
+
end))
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
-- textDecoration — wrap text in rich text tags (RichText=true is set by webStyle)
|
|
126
|
+
if style.textDecoration ~= nil and style.textDecoration ~= "none" then
|
|
127
|
+
local _text = explicitProps.Text
|
|
128
|
+
if type(_text) == "string" then
|
|
129
|
+
if style.textDecoration == "underline" then
|
|
130
|
+
explicitProps.Text = `<u>{explicitProps.Text}</u>`
|
|
131
|
+
elseif style.textDecoration == "line-through" then
|
|
132
|
+
explicitProps.Text = `<s>{explicitProps.Text}</s>`
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
-- 5. Map React-style event props to the Roblox Event table
|
|
138
|
+
local existingEvents = (props.Event) or {}
|
|
139
|
+
local _object_1 = table.clone(existingEvents)
|
|
140
|
+
setmetatable(_object_1, nil)
|
|
141
|
+
local mergedEvents = _object_1
|
|
142
|
+
if onClick ~= nil then
|
|
143
|
+
mergedEvents.Activated = onClick
|
|
144
|
+
end
|
|
145
|
+
if onMouseEnter ~= nil then
|
|
146
|
+
mergedEvents.MouseEnter = onMouseEnter
|
|
147
|
+
end
|
|
148
|
+
if onMouseLeave ~= nil then
|
|
149
|
+
mergedEvents.MouseLeave = onMouseLeave
|
|
150
|
+
end
|
|
151
|
+
explicitProps.Event = mergedEvents
|
|
152
|
+
-- 6. Render the native textbutton with merged properties and children
|
|
153
|
+
local _attributes = {
|
|
154
|
+
ref = ref,
|
|
155
|
+
}
|
|
156
|
+
for _k, _v in defaultProps do
|
|
157
|
+
_attributes[_k] = _v
|
|
158
|
+
end
|
|
159
|
+
for _k, _v in parsedStyleProps do
|
|
160
|
+
_attributes[_k] = _v
|
|
161
|
+
end
|
|
162
|
+
for _k, _v in explicitProps do
|
|
163
|
+
_attributes[_k] = _v
|
|
164
|
+
end
|
|
165
|
+
return React.createElement("textbutton", _attributes, parsedStyleChildren, if type(children) == "string" or type(children) == "number" then nil else children)
|
|
166
|
+
end)
|
|
167
|
+
return {
|
|
168
|
+
makeButtonProps = makeButtonProps,
|
|
169
|
+
Button = Button,
|
|
170
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Image.tsx — <img> equivalent for Roblox.
|
|
3
|
+
*
|
|
4
|
+
* Renders an <imagelabel> with web-like style props.
|
|
5
|
+
* Accepts `src` (maps to Image property) as rbxassetid:// URI.
|
|
6
|
+
*
|
|
7
|
+
* Maps to: HTML <img> → Roblox <imagelabel>
|
|
8
|
+
*/
|
|
9
|
+
import React from "@rbxts/react";
|
|
10
|
+
import { CSSProperties } from "../styles/CSSTypes";
|
|
11
|
+
import { DeepReadonly } from "../types";
|
|
12
|
+
/**
|
|
13
|
+
* Branded ImageProps — the `_imageProps` brand ensures strict nominal typing.
|
|
14
|
+
* This prevents accidental bypasses or incorrect prop structures.
|
|
15
|
+
*/
|
|
16
|
+
export type ImageProps = React.PropsWithChildren<React.ComponentProps<"imagelabel">> & {
|
|
17
|
+
/**
|
|
18
|
+
* Web-like CSS styling object that automatically maps to Roblox properties
|
|
19
|
+
* and injects necessary UI constraints (UICorner, UIPadding, UIListLayout).
|
|
20
|
+
*/
|
|
21
|
+
style?: CSSProperties;
|
|
22
|
+
/**
|
|
23
|
+
* The source URI of the image (e.g., rbxassetid://...).
|
|
24
|
+
*/
|
|
25
|
+
src?: string;
|
|
26
|
+
} & {
|
|
27
|
+
readonly _imageProps?: unique symbol;
|
|
28
|
+
};
|
|
29
|
+
/** Helper to construct a branded ImageProps. */
|
|
30
|
+
export declare function makeImageProps(props: Omit<ImageProps, "_imageProps">): DeepReadonly<ImageProps>;
|
|
31
|
+
/**
|
|
32
|
+
* Image component — The primary component for rendering images.
|
|
33
|
+
*
|
|
34
|
+
* Maps to: HTML <img> → Roblox <imagelabel>
|
|
35
|
+
* Renders a native <imagelabel> while mapping web styles and translating `src` to the `Image` property.
|
|
36
|
+
*/
|
|
37
|
+
export declare const Image: React.ForwardRefExoticComponent<Omit<ImageProps, "ref"> & React.RefAttributes<ImageLabel>>;
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
-- Compiled with roblox-ts v3.0.0
|
|
2
|
+
local TS = _G[script]
|
|
3
|
+
--[[
|
|
4
|
+
*
|
|
5
|
+
* Image.tsx — <img> equivalent for Roblox.
|
|
6
|
+
*
|
|
7
|
+
* Renders an <imagelabel> with web-like style props.
|
|
8
|
+
* Accepts `src` (maps to Image property) as rbxassetid:// URI.
|
|
9
|
+
*
|
|
10
|
+
* Maps to: HTML <img> → Roblox <imagelabel>
|
|
11
|
+
|
|
12
|
+
]]
|
|
13
|
+
local _react = TS.import(script, TS.getModule(script, "@rbxts", "react"))
|
|
14
|
+
local React = _react
|
|
15
|
+
local forwardRef = _react.forwardRef
|
|
16
|
+
local webStyle = TS.import(script, script.Parent.Parent, "styles", "webStyle").webStyle
|
|
17
|
+
--[[
|
|
18
|
+
*
|
|
19
|
+
* Branded ImageProps — the `_imageProps` brand ensures strict nominal typing.
|
|
20
|
+
* This prevents accidental bypasses or incorrect prop structures.
|
|
21
|
+
|
|
22
|
+
]]
|
|
23
|
+
--* Helper to construct a branded ImageProps.
|
|
24
|
+
local function makeImageProps(props)
|
|
25
|
+
return props
|
|
26
|
+
end
|
|
27
|
+
--[[
|
|
28
|
+
*
|
|
29
|
+
* Image component — The primary component for rendering images.
|
|
30
|
+
*
|
|
31
|
+
* Maps to: HTML <img> → Roblox <imagelabel>
|
|
32
|
+
* Renders a native <imagelabel> while mapping web styles and translating `src` to the `Image` property.
|
|
33
|
+
|
|
34
|
+
]]
|
|
35
|
+
local Image = forwardRef(function(props, ref)
|
|
36
|
+
-- 1. Extract custom styling props, src, and children
|
|
37
|
+
local style = props.style
|
|
38
|
+
local src = props.src
|
|
39
|
+
local children = props.children
|
|
40
|
+
local defaultProps = {
|
|
41
|
+
BackgroundTransparency = 1,
|
|
42
|
+
}
|
|
43
|
+
local _object = table.clone(props)
|
|
44
|
+
setmetatable(_object, nil)
|
|
45
|
+
local explicitProps = _object
|
|
46
|
+
explicitProps.style = nil
|
|
47
|
+
explicitProps.src = nil
|
|
48
|
+
explicitProps.children = nil
|
|
49
|
+
-- 3. Map src prop to the Image property
|
|
50
|
+
if src ~= nil then
|
|
51
|
+
explicitProps.Image = src
|
|
52
|
+
end
|
|
53
|
+
local parsedStyleProps = {}
|
|
54
|
+
local parsedStyleChildren = {}
|
|
55
|
+
-- 4. If a style object is provided, compile it
|
|
56
|
+
if style then
|
|
57
|
+
local parsed = webStyle(style)
|
|
58
|
+
parsedStyleProps = parsed.props
|
|
59
|
+
parsedStyleChildren = parsed.children
|
|
60
|
+
end
|
|
61
|
+
-- 5. Render the native imagelabel with merged properties and children
|
|
62
|
+
local _attributes = {
|
|
63
|
+
ref = ref,
|
|
64
|
+
}
|
|
65
|
+
for _k, _v in defaultProps do
|
|
66
|
+
_attributes[_k] = _v
|
|
67
|
+
end
|
|
68
|
+
for _k, _v in parsedStyleProps do
|
|
69
|
+
_attributes[_k] = _v
|
|
70
|
+
end
|
|
71
|
+
for _k, _v in explicitProps do
|
|
72
|
+
_attributes[_k] = _v
|
|
73
|
+
end
|
|
74
|
+
return React.createElement("imagelabel", _attributes, parsedStyleChildren, children)
|
|
75
|
+
end)
|
|
76
|
+
return {
|
|
77
|
+
makeImageProps = makeImageProps,
|
|
78
|
+
Image = Image,
|
|
79
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* InlineText.tsx — Rich text with inline image support for Roblox.
|
|
3
|
+
*
|
|
4
|
+
* Parses `<img src="..." width="N" height="N" />` tags from text strings
|
|
5
|
+
* and renders them as a horizontal row of <Text> and <Image> elements.
|
|
6
|
+
*
|
|
7
|
+
* Roblox's built-in RichText does NOT support inline images, so this component
|
|
8
|
+
* splits the string into text and image segments, rendering each as a separate
|
|
9
|
+
* element inside a flex row container.
|
|
10
|
+
*
|
|
11
|
+
* When no images are found, falls back to a plain <Text> element.
|
|
12
|
+
*
|
|
13
|
+
* Usage:
|
|
14
|
+
* <InlineText style={{ fontSize: 18, color: "#FFF" }}>
|
|
15
|
+
* {"Hello <img src=\"rbxassetid://123\" width=\"20\" height=\"20\" /> World!"}
|
|
16
|
+
* </InlineText>
|
|
17
|
+
*/
|
|
18
|
+
import React from "@rbxts/react";
|
|
19
|
+
import { CSSProperties } from "../styles/CSSTypes";
|
|
20
|
+
interface InlineTextProps {
|
|
21
|
+
Text?: string;
|
|
22
|
+
style?: CSSProperties;
|
|
23
|
+
}
|
|
24
|
+
export declare function InlineText(props: InlineTextProps): React.JSX.Element;
|
|
25
|
+
export {};
|
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
-- Compiled with roblox-ts v3.0.0
|
|
2
|
+
local TS = _G[script]
|
|
3
|
+
--[[
|
|
4
|
+
*
|
|
5
|
+
* InlineText.tsx — Rich text with inline image support for Roblox.
|
|
6
|
+
*
|
|
7
|
+
* Parses `<img src="..." width="N" height="N" />` tags from text strings
|
|
8
|
+
* and renders them as a horizontal row of <Text> and <Image> elements.
|
|
9
|
+
*
|
|
10
|
+
* Roblox's built-in RichText does NOT support inline images, so this component
|
|
11
|
+
* splits the string into text and image segments, rendering each as a separate
|
|
12
|
+
* element inside a flex row container.
|
|
13
|
+
*
|
|
14
|
+
* When no images are found, falls back to a plain <Text> element.
|
|
15
|
+
*
|
|
16
|
+
* Usage:
|
|
17
|
+
* <InlineText style={{ fontSize: 18, color: "#FFF" }}>
|
|
18
|
+
* {"Hello <img src=\"rbxassetid://123\" width=\"20\" height=\"20\" /> World!"}
|
|
19
|
+
* </InlineText>
|
|
20
|
+
|
|
21
|
+
]]
|
|
22
|
+
local React = TS.import(script, TS.getModule(script, "@rbxts", "react"))
|
|
23
|
+
local Box = TS.import(script, script.Parent, "Box").Box
|
|
24
|
+
local Text = TS.import(script, script.Parent, "Text").Text
|
|
25
|
+
local Image = TS.import(script, script.Parent, "Image").Image
|
|
26
|
+
local _parseInlineImages = TS.import(script, script.Parent.Parent, "utils", "parseInlineImages")
|
|
27
|
+
local parseInlineImages = _parseInlineImages.parseInlineImages
|
|
28
|
+
local containsRichTextTags = _parseInlineImages.containsRichTextTags
|
|
29
|
+
local function InlineText(props)
|
|
30
|
+
local _condition = props.Text
|
|
31
|
+
if _condition == nil then
|
|
32
|
+
_condition = ""
|
|
33
|
+
end
|
|
34
|
+
local text = _condition
|
|
35
|
+
local style = props.style
|
|
36
|
+
local segments = parseInlineImages(text)
|
|
37
|
+
-- Check if any segment is an image
|
|
38
|
+
local hasImages = false
|
|
39
|
+
for _, seg in segments do
|
|
40
|
+
if seg.type == "image" then
|
|
41
|
+
hasImages = true
|
|
42
|
+
break
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
-- --- Fallback: no images, render a plain <Text> ---
|
|
46
|
+
if not hasImages then
|
|
47
|
+
local _result
|
|
48
|
+
if style then
|
|
49
|
+
local _object = table.clone(style)
|
|
50
|
+
setmetatable(_object, nil)
|
|
51
|
+
_result = _object
|
|
52
|
+
else
|
|
53
|
+
_result = ({})
|
|
54
|
+
end
|
|
55
|
+
local textStyle = _result
|
|
56
|
+
-- Auto-enable richText if the text contains RichText tags and it's not already
|
|
57
|
+
-- being set by textDecoration (which sets RichText=true via webStyle)
|
|
58
|
+
if textStyle.richText == nil and textStyle.textDecoration == nil and containsRichTextTags(text) then
|
|
59
|
+
textStyle.richText = true
|
|
60
|
+
end
|
|
61
|
+
return React.createElement(Text, {
|
|
62
|
+
style = textStyle,
|
|
63
|
+
Text = text,
|
|
64
|
+
})
|
|
65
|
+
end
|
|
66
|
+
-- --- Images found: render a flex row with Text and Image segments ---
|
|
67
|
+
-- Only pass layout/positioning props to the Box (Frame) container.
|
|
68
|
+
-- Text-specific props (font, color, etc.) go to the Text children only.
|
|
69
|
+
local containerStyle = {
|
|
70
|
+
display = "flex",
|
|
71
|
+
flexDirection = "row",
|
|
72
|
+
alignItems = "center",
|
|
73
|
+
}
|
|
74
|
+
if style then
|
|
75
|
+
-- Layout / positioning / sizing — safe for Frame
|
|
76
|
+
if style.width ~= nil then
|
|
77
|
+
containerStyle.width = style.width
|
|
78
|
+
end
|
|
79
|
+
if style.height ~= nil then
|
|
80
|
+
containerStyle.height = style.height
|
|
81
|
+
end
|
|
82
|
+
if style.position ~= nil then
|
|
83
|
+
containerStyle.position = style.position
|
|
84
|
+
end
|
|
85
|
+
if style.left ~= nil then
|
|
86
|
+
containerStyle.left = style.left
|
|
87
|
+
end
|
|
88
|
+
if style.right ~= nil then
|
|
89
|
+
containerStyle.right = style.right
|
|
90
|
+
end
|
|
91
|
+
if style.top ~= nil then
|
|
92
|
+
containerStyle.top = style.top
|
|
93
|
+
end
|
|
94
|
+
if style.bottom ~= nil then
|
|
95
|
+
containerStyle.bottom = style.bottom
|
|
96
|
+
end
|
|
97
|
+
if style.padding ~= nil then
|
|
98
|
+
containerStyle.padding = style.padding
|
|
99
|
+
end
|
|
100
|
+
if style.paddingLeft ~= nil then
|
|
101
|
+
containerStyle.paddingLeft = style.paddingLeft
|
|
102
|
+
end
|
|
103
|
+
if style.paddingRight ~= nil then
|
|
104
|
+
containerStyle.paddingRight = style.paddingRight
|
|
105
|
+
end
|
|
106
|
+
if style.paddingTop ~= nil then
|
|
107
|
+
containerStyle.paddingTop = style.paddingTop
|
|
108
|
+
end
|
|
109
|
+
if style.paddingBottom ~= nil then
|
|
110
|
+
containerStyle.paddingBottom = style.paddingBottom
|
|
111
|
+
end
|
|
112
|
+
if style.gap ~= nil then
|
|
113
|
+
containerStyle.gap = style.gap
|
|
114
|
+
end
|
|
115
|
+
if style.backgroundColor ~= nil then
|
|
116
|
+
containerStyle.backgroundColor = style.backgroundColor
|
|
117
|
+
end
|
|
118
|
+
if style.background ~= nil then
|
|
119
|
+
containerStyle.background = style.background
|
|
120
|
+
end
|
|
121
|
+
if style.opacity ~= nil then
|
|
122
|
+
containerStyle.opacity = style.opacity
|
|
123
|
+
end
|
|
124
|
+
if style.borderRadius ~= nil then
|
|
125
|
+
containerStyle.borderRadius = style.borderRadius
|
|
126
|
+
end
|
|
127
|
+
if style.border ~= nil then
|
|
128
|
+
containerStyle.border = style.border
|
|
129
|
+
end
|
|
130
|
+
if style.zIndex ~= nil then
|
|
131
|
+
containerStyle.zIndex = style.zIndex
|
|
132
|
+
end
|
|
133
|
+
if style.overflow ~= nil then
|
|
134
|
+
containerStyle.overflow = style.overflow
|
|
135
|
+
end
|
|
136
|
+
if style.visibility ~= nil then
|
|
137
|
+
containerStyle.visibility = style.visibility
|
|
138
|
+
end
|
|
139
|
+
if style.maxWidth ~= nil then
|
|
140
|
+
containerStyle.maxWidth = style.maxWidth
|
|
141
|
+
end
|
|
142
|
+
if style.maxHeight ~= nil then
|
|
143
|
+
containerStyle.maxHeight = style.maxHeight
|
|
144
|
+
end
|
|
145
|
+
if style.minWidth ~= nil then
|
|
146
|
+
containerStyle.minWidth = style.minWidth
|
|
147
|
+
end
|
|
148
|
+
if style.minHeight ~= nil then
|
|
149
|
+
containerStyle.minHeight = style.minHeight
|
|
150
|
+
end
|
|
151
|
+
if style.justifyContent ~= nil then
|
|
152
|
+
containerStyle.justifyContent = style.justifyContent
|
|
153
|
+
end
|
|
154
|
+
if style.flexWrap ~= nil then
|
|
155
|
+
containerStyle.flexWrap = style.flexWrap
|
|
156
|
+
end
|
|
157
|
+
if style.boxShadow ~= nil then
|
|
158
|
+
containerStyle.boxShadow = style.boxShadow
|
|
159
|
+
end
|
|
160
|
+
end
|
|
161
|
+
-- ▼ ReadonlyArray.map ▼
|
|
162
|
+
local _newValue = table.create(#segments)
|
|
163
|
+
local _callback = function(segment, i)
|
|
164
|
+
if segment.type == "text" then
|
|
165
|
+
-- Build a text-specific style that inherits typography from parent style
|
|
166
|
+
local segmentStyle = {}
|
|
167
|
+
local _result = style
|
|
168
|
+
if _result ~= nil then
|
|
169
|
+
_result = _result.fontSize
|
|
170
|
+
end
|
|
171
|
+
if _result ~= nil then
|
|
172
|
+
segmentStyle.fontSize = style.fontSize
|
|
173
|
+
end
|
|
174
|
+
local _result_1 = style
|
|
175
|
+
if _result_1 ~= nil then
|
|
176
|
+
_result_1 = _result_1.fontFamily
|
|
177
|
+
end
|
|
178
|
+
if _result_1 ~= nil then
|
|
179
|
+
segmentStyle.fontFamily = style.fontFamily
|
|
180
|
+
end
|
|
181
|
+
local _result_2 = style
|
|
182
|
+
if _result_2 ~= nil then
|
|
183
|
+
_result_2 = _result_2.fontWeight
|
|
184
|
+
end
|
|
185
|
+
if _result_2 ~= nil then
|
|
186
|
+
segmentStyle.fontWeight = style.fontWeight
|
|
187
|
+
end
|
|
188
|
+
local _result_3 = style
|
|
189
|
+
if _result_3 ~= nil then
|
|
190
|
+
_result_3 = _result_3.fontStyle
|
|
191
|
+
end
|
|
192
|
+
if _result_3 ~= nil then
|
|
193
|
+
segmentStyle.fontStyle = style.fontStyle
|
|
194
|
+
end
|
|
195
|
+
local _result_4 = style
|
|
196
|
+
if _result_4 ~= nil then
|
|
197
|
+
_result_4 = _result_4.color
|
|
198
|
+
end
|
|
199
|
+
if _result_4 ~= nil then
|
|
200
|
+
segmentStyle.color = style.color
|
|
201
|
+
end
|
|
202
|
+
local _result_5 = style
|
|
203
|
+
if _result_5 ~= nil then
|
|
204
|
+
_result_5 = _result_5.lineHeight
|
|
205
|
+
end
|
|
206
|
+
if _result_5 ~= nil then
|
|
207
|
+
segmentStyle.lineHeight = style.lineHeight
|
|
208
|
+
end
|
|
209
|
+
local _result_6 = style
|
|
210
|
+
if _result_6 ~= nil then
|
|
211
|
+
_result_6 = _result_6.whiteSpace
|
|
212
|
+
end
|
|
213
|
+
if _result_6 ~= nil then
|
|
214
|
+
segmentStyle.whiteSpace = style.whiteSpace
|
|
215
|
+
end
|
|
216
|
+
local _result_7 = style
|
|
217
|
+
if _result_7 ~= nil then
|
|
218
|
+
_result_7 = _result_7.textAlign
|
|
219
|
+
end
|
|
220
|
+
if _result_7 ~= nil then
|
|
221
|
+
segmentStyle.textAlign = style.textAlign
|
|
222
|
+
end
|
|
223
|
+
local _result_8 = style
|
|
224
|
+
if _result_8 ~= nil then
|
|
225
|
+
_result_8 = _result_8.textVerticalAlign
|
|
226
|
+
end
|
|
227
|
+
if _result_8 ~= nil then
|
|
228
|
+
segmentStyle.textVerticalAlign = style.textVerticalAlign
|
|
229
|
+
end
|
|
230
|
+
-- Always enable richText for text segments so <b>, <font> etc work
|
|
231
|
+
segmentStyle.richText = true
|
|
232
|
+
-- Apply textTransform and textDecoration from parent style
|
|
233
|
+
local _result_9 = style
|
|
234
|
+
if _result_9 ~= nil then
|
|
235
|
+
_result_9 = _result_9.textTransform
|
|
236
|
+
end
|
|
237
|
+
if _result_9 ~= nil then
|
|
238
|
+
segmentStyle.textTransform = style.textTransform
|
|
239
|
+
end
|
|
240
|
+
local _result_10 = style
|
|
241
|
+
if _result_10 ~= nil then
|
|
242
|
+
_result_10 = _result_10.textDecoration
|
|
243
|
+
end
|
|
244
|
+
if _result_10 ~= nil then
|
|
245
|
+
segmentStyle.textDecoration = style.textDecoration
|
|
246
|
+
end
|
|
247
|
+
return React.createElement(Text, {
|
|
248
|
+
key = `text-{i}`,
|
|
249
|
+
style = segmentStyle,
|
|
250
|
+
Text = segment.content,
|
|
251
|
+
})
|
|
252
|
+
end
|
|
253
|
+
-- Image segment
|
|
254
|
+
return React.createElement(Image, {
|
|
255
|
+
key = `img-{i}`,
|
|
256
|
+
src = segment.src,
|
|
257
|
+
style = {
|
|
258
|
+
width = segment.width,
|
|
259
|
+
height = segment.height,
|
|
260
|
+
},
|
|
261
|
+
})
|
|
262
|
+
end
|
|
263
|
+
for _k, _v in segments do
|
|
264
|
+
_newValue[_k] = _callback(_v, _k - 1, segments)
|
|
265
|
+
end
|
|
266
|
+
-- ▲ ReadonlyArray.map ▲
|
|
267
|
+
return React.createElement(Box, {
|
|
268
|
+
style = containerStyle,
|
|
269
|
+
}, _newValue)
|
|
270
|
+
end
|
|
271
|
+
return {
|
|
272
|
+
InlineText = InlineText,
|
|
273
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Input.tsx — <input> equivalent for Roblox.
|
|
3
|
+
*
|
|
4
|
+
* Renders a <textbox> with web-like style props.
|
|
5
|
+
* Extends the core webStyle translation by adding input-specific mappings.
|
|
6
|
+
* Automatically maps web-like placeholder and onChange props to their
|
|
7
|
+
* Roblox equivalents for a more familiar developer experience.
|
|
8
|
+
*
|
|
9
|
+
* Input mappings:
|
|
10
|
+
* Web Property → Roblox Output
|
|
11
|
+
* ─────────────────────────────────────────────────────────
|
|
12
|
+
* placeholder → PlaceholderText (string)
|
|
13
|
+
* onChange(text) → Change.Text (event listener)
|
|
14
|
+
* style → (Maps via webStyle)
|
|
15
|
+
*
|
|
16
|
+
* Maps to: HTML <input> → Roblox <textbox>
|
|
17
|
+
*
|
|
18
|
+
* Usage:
|
|
19
|
+
* <Input
|
|
20
|
+
* placeholder="Enter your name..."
|
|
21
|
+
* onChange={(text) => print("User typed:", text)}
|
|
22
|
+
* style={{ width: 200, height: 40, backgroundColor: "#FFFFFF" }}
|
|
23
|
+
* />
|
|
24
|
+
*/
|
|
25
|
+
import React from "@rbxts/react";
|
|
26
|
+
import { CSSProperties } from "../styles/webStyle";
|
|
27
|
+
import { DeepReadonly } from "../types";
|
|
28
|
+
/**
|
|
29
|
+
* Branded InputProps — the `_inputProps` brand ensures strict nominal typing.
|
|
30
|
+
* This prevents accidental bypasses or incorrect prop structures.
|
|
31
|
+
*/
|
|
32
|
+
export type InputProps = React.PropsWithChildren<React.ComponentProps<"textbox">> & {
|
|
33
|
+
/**
|
|
34
|
+
* Web-like CSS styling object that automatically maps to Roblox properties
|
|
35
|
+
* and injects necessary UI constraints (UICorner, UIPadding, UIListLayout).
|
|
36
|
+
*/
|
|
37
|
+
style?: CSSProperties;
|
|
38
|
+
/**
|
|
39
|
+
* Web-like alias for PlaceholderText.
|
|
40
|
+
* Sets the text that appears when the input is empty.
|
|
41
|
+
*/
|
|
42
|
+
placeholder?: string;
|
|
43
|
+
/**
|
|
44
|
+
* Fired when the text changes.
|
|
45
|
+
* Automatically maps to Roblox's `Change.Text` event.
|
|
46
|
+
*/
|
|
47
|
+
onChange?: (text: string) => void;
|
|
48
|
+
} & {
|
|
49
|
+
readonly _inputProps?: unique symbol;
|
|
50
|
+
};
|
|
51
|
+
/** Helper to construct a branded InputProps. */
|
|
52
|
+
export declare function makeInputProps(props: Omit<InputProps, "_inputProps">): DeepReadonly<InputProps>;
|
|
53
|
+
/**
|
|
54
|
+
* Input component — The primary component for receiving user text input.
|
|
55
|
+
*
|
|
56
|
+
* Maps to: HTML <input> → Roblox <textbox>
|
|
57
|
+
* Renders a native <textbox> while mapping web input props to Roblox properties.
|
|
58
|
+
*/
|
|
59
|
+
export declare const Input: React.ForwardRefExoticComponent<Omit<InputProps, "ref"> & React.RefAttributes<TextBox>>;
|