@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,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>>;