@lattice-ui/textarea 0.3.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/README.md +18 -0
- package/out/Textarea/TextareaDescription.d.ts +3 -0
- package/out/Textarea/TextareaDescription.luau +31 -0
- package/out/Textarea/TextareaInput.d.ts +3 -0
- package/out/Textarea/TextareaInput.luau +109 -0
- package/out/Textarea/TextareaLabel.d.ts +3 -0
- package/out/Textarea/TextareaLabel.luau +49 -0
- package/out/Textarea/TextareaMessage.d.ts +3 -0
- package/out/Textarea/TextareaMessage.luau +31 -0
- package/out/Textarea/TextareaRoot.d.ts +4 -0
- package/out/Textarea/TextareaRoot.luau +72 -0
- package/out/Textarea/autoResize.d.ts +7 -0
- package/out/Textarea/autoResize.luau +23 -0
- package/out/Textarea/context.d.ts +3 -0
- package/out/Textarea/context.luau +10 -0
- package/out/Textarea/types.d.ts +51 -0
- package/out/Textarea/types.luau +2 -0
- package/out/index.d.ts +14 -0
- package/out/init.luau +18 -0
- package/package.json +23 -0
- package/src/Textarea/TextareaDescription.tsx +32 -0
- package/src/Textarea/TextareaInput.tsx +131 -0
- package/src/Textarea/TextareaLabel.tsx +47 -0
- package/src/Textarea/TextareaMessage.tsx +38 -0
- package/src/Textarea/TextareaRoot.tsx +61 -0
- package/src/Textarea/autoResize.ts +27 -0
- package/src/Textarea/context.ts +6 -0
- package/src/Textarea/types.ts +58 -0
- package/src/index.ts +25 -0
- package/tsconfig.json +16 -0
- package/tsconfig.typecheck.json +35 -0
package/README.md
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# @lattice-ui/textarea
|
|
2
|
+
|
|
3
|
+
Headless multi-line text input primitives for Roblox UI with optional auto-resize behavior.
|
|
4
|
+
|
|
5
|
+
## Exports
|
|
6
|
+
|
|
7
|
+
- `Textarea`
|
|
8
|
+
- `Textarea.Root`
|
|
9
|
+
- `Textarea.Input`
|
|
10
|
+
- `Textarea.Label`
|
|
11
|
+
- `Textarea.Description`
|
|
12
|
+
- `Textarea.Message`
|
|
13
|
+
|
|
14
|
+
## Notes
|
|
15
|
+
|
|
16
|
+
- Supports controlled/uncontrolled `value`.
|
|
17
|
+
- `autoResize` is enabled by default and respects `minRows`/`maxRows`.
|
|
18
|
+
- `onValueCommit` fires on `FocusLost` commit moments.
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
-- Compiled with roblox-ts v3.0.0
|
|
2
|
+
local TS = _G[script]
|
|
3
|
+
local _core = TS.import(script, TS.getModule(script, "@lattice-ui", "core").out)
|
|
4
|
+
local React = _core.React
|
|
5
|
+
local Slot = _core.Slot
|
|
6
|
+
local useTextareaContext = TS.import(script, script.Parent, "context").useTextareaContext
|
|
7
|
+
local function TextareaDescription(props)
|
|
8
|
+
local textareaContext = useTextareaContext()
|
|
9
|
+
if props.asChild then
|
|
10
|
+
local child = props.children
|
|
11
|
+
if not child then
|
|
12
|
+
error("[TextareaDescription] `asChild` requires a child element.")
|
|
13
|
+
end
|
|
14
|
+
return React.createElement(Slot, {
|
|
15
|
+
Name = "TextareaDescription",
|
|
16
|
+
Text = "Description",
|
|
17
|
+
}, child)
|
|
18
|
+
end
|
|
19
|
+
return React.createElement("textlabel", {
|
|
20
|
+
BackgroundTransparency = 1,
|
|
21
|
+
BorderSizePixel = 0,
|
|
22
|
+
Size = UDim2.fromOffset(300, 20),
|
|
23
|
+
Text = "Description",
|
|
24
|
+
TextColor3 = if textareaContext.disabled then Color3.fromRGB(132, 139, 154) else Color3.fromRGB(170, 179, 195),
|
|
25
|
+
TextSize = 13,
|
|
26
|
+
TextXAlignment = Enum.TextXAlignment.Left,
|
|
27
|
+
})
|
|
28
|
+
end
|
|
29
|
+
return {
|
|
30
|
+
TextareaDescription = TextareaDescription,
|
|
31
|
+
}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
-- Compiled with roblox-ts v3.0.0
|
|
2
|
+
local TS = _G[script]
|
|
3
|
+
local _core = TS.import(script, TS.getModule(script, "@lattice-ui", "core").out)
|
|
4
|
+
local React = _core.React
|
|
5
|
+
local Slot = _core.Slot
|
|
6
|
+
local resolveTextareaHeight = TS.import(script, script.Parent, "autoResize").resolveTextareaHeight
|
|
7
|
+
local useTextareaContext = TS.import(script, script.Parent, "context").useTextareaContext
|
|
8
|
+
local function toTextBox(instance)
|
|
9
|
+
if not instance or not instance:IsA("TextBox") then
|
|
10
|
+
return nil
|
|
11
|
+
end
|
|
12
|
+
return instance
|
|
13
|
+
end
|
|
14
|
+
local function TextareaInput(props)
|
|
15
|
+
local textareaContext = useTextareaContext()
|
|
16
|
+
local disabled = textareaContext.disabled or props.disabled == true
|
|
17
|
+
local readOnly = textareaContext.readOnly or props.readOnly == true
|
|
18
|
+
local _condition = props.lineHeight
|
|
19
|
+
if _condition == nil then
|
|
20
|
+
_condition = 18
|
|
21
|
+
end
|
|
22
|
+
local lineHeight = _condition
|
|
23
|
+
local setInputRef = React.useCallback(function(instance)
|
|
24
|
+
textareaContext.inputRef.current = toTextBox(instance)
|
|
25
|
+
end, { textareaContext.inputRef })
|
|
26
|
+
local applyAutoResize = React.useCallback(function(textBox)
|
|
27
|
+
if not textareaContext.autoResize then
|
|
28
|
+
return nil
|
|
29
|
+
end
|
|
30
|
+
local height = resolveTextareaHeight(textBox.Text, {
|
|
31
|
+
lineHeight = lineHeight,
|
|
32
|
+
minRows = textareaContext.minRows,
|
|
33
|
+
maxRows = textareaContext.maxRows,
|
|
34
|
+
verticalPadding = 14,
|
|
35
|
+
})
|
|
36
|
+
local currentSize = textBox.Size
|
|
37
|
+
if currentSize.Y.Offset ~= height or currentSize.Y.Scale ~= 0 then
|
|
38
|
+
textBox.Size = UDim2.fromOffset(currentSize.X.Offset, height)
|
|
39
|
+
end
|
|
40
|
+
end, { lineHeight, textareaContext.autoResize, textareaContext.maxRows, textareaContext.minRows })
|
|
41
|
+
local handleTextChanged = React.useCallback(function(textBox)
|
|
42
|
+
if disabled or readOnly then
|
|
43
|
+
if textBox.Text ~= textareaContext.value then
|
|
44
|
+
textBox.Text = textareaContext.value
|
|
45
|
+
end
|
|
46
|
+
applyAutoResize(textBox)
|
|
47
|
+
return nil
|
|
48
|
+
end
|
|
49
|
+
textareaContext.setValue(textBox.Text)
|
|
50
|
+
applyAutoResize(textBox)
|
|
51
|
+
end, { applyAutoResize, disabled, readOnly, textareaContext })
|
|
52
|
+
local handleFocusLost = React.useCallback(function(textBox)
|
|
53
|
+
if disabled then
|
|
54
|
+
return nil
|
|
55
|
+
end
|
|
56
|
+
textareaContext.commitValue(textBox.Text)
|
|
57
|
+
end, { disabled, textareaContext })
|
|
58
|
+
React.useEffect(function()
|
|
59
|
+
local input = textareaContext.inputRef.current
|
|
60
|
+
if not input then
|
|
61
|
+
return nil
|
|
62
|
+
end
|
|
63
|
+
applyAutoResize(input)
|
|
64
|
+
end, { applyAutoResize, textareaContext.inputRef, textareaContext.value })
|
|
65
|
+
local sharedProps = {
|
|
66
|
+
Active = not disabled,
|
|
67
|
+
ClearTextOnFocus = false,
|
|
68
|
+
MultiLine = true,
|
|
69
|
+
Selectable = not disabled,
|
|
70
|
+
Text = textareaContext.value,
|
|
71
|
+
TextEditable = not disabled and not readOnly,
|
|
72
|
+
TextWrapped = true,
|
|
73
|
+
Change = {
|
|
74
|
+
Text = handleTextChanged,
|
|
75
|
+
},
|
|
76
|
+
Event = {
|
|
77
|
+
FocusLost = handleFocusLost,
|
|
78
|
+
},
|
|
79
|
+
ref = setInputRef,
|
|
80
|
+
}
|
|
81
|
+
if props.asChild then
|
|
82
|
+
local child = props.children
|
|
83
|
+
if not child then
|
|
84
|
+
error("[TextareaInput] `asChild` requires a child element.")
|
|
85
|
+
end
|
|
86
|
+
local _attributes = table.clone(sharedProps)
|
|
87
|
+
setmetatable(_attributes, nil)
|
|
88
|
+
return React.createElement(Slot, _attributes, child)
|
|
89
|
+
end
|
|
90
|
+
local _attributes = table.clone(sharedProps)
|
|
91
|
+
setmetatable(_attributes, nil)
|
|
92
|
+
_attributes.BackgroundColor3 = Color3.fromRGB(39, 46, 61)
|
|
93
|
+
_attributes.BorderSizePixel = 0
|
|
94
|
+
_attributes.PlaceholderText = "Type..."
|
|
95
|
+
_attributes.Size = UDim2.fromOffset(240, 68)
|
|
96
|
+
_attributes.TextColor3 = if disabled then Color3.fromRGB(137, 145, 162) else Color3.fromRGB(235, 240, 248)
|
|
97
|
+
_attributes.TextSize = 15
|
|
98
|
+
_attributes.TextXAlignment = Enum.TextXAlignment.Left
|
|
99
|
+
_attributes.TextYAlignment = Enum.TextYAlignment.Top
|
|
100
|
+
return React.createElement("textbox", _attributes, React.createElement("uipadding", {
|
|
101
|
+
PaddingBottom = UDim.new(0, 7),
|
|
102
|
+
PaddingLeft = UDim.new(0, 10),
|
|
103
|
+
PaddingRight = UDim.new(0, 10),
|
|
104
|
+
PaddingTop = UDim.new(0, 7),
|
|
105
|
+
}))
|
|
106
|
+
end
|
|
107
|
+
return {
|
|
108
|
+
TextareaInput = TextareaInput,
|
|
109
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
-- Compiled with roblox-ts v3.0.0
|
|
2
|
+
local TS = _G[script]
|
|
3
|
+
local _core = TS.import(script, TS.getModule(script, "@lattice-ui", "core").out)
|
|
4
|
+
local React = _core.React
|
|
5
|
+
local Slot = _core.Slot
|
|
6
|
+
local useTextareaContext = TS.import(script, script.Parent, "context").useTextareaContext
|
|
7
|
+
local function TextareaLabel(props)
|
|
8
|
+
local textareaContext = useTextareaContext()
|
|
9
|
+
local disabled = textareaContext.disabled
|
|
10
|
+
local handleActivated = React.useCallback(function()
|
|
11
|
+
if disabled then
|
|
12
|
+
return nil
|
|
13
|
+
end
|
|
14
|
+
local _result = textareaContext.inputRef.current
|
|
15
|
+
if _result ~= nil then
|
|
16
|
+
_result:CaptureFocus()
|
|
17
|
+
end
|
|
18
|
+
end, { disabled, textareaContext.inputRef })
|
|
19
|
+
local sharedProps = {
|
|
20
|
+
Active = not disabled,
|
|
21
|
+
Selectable = not disabled,
|
|
22
|
+
Text = "Label",
|
|
23
|
+
Event = {
|
|
24
|
+
Activated = handleActivated,
|
|
25
|
+
},
|
|
26
|
+
}
|
|
27
|
+
if props.asChild then
|
|
28
|
+
local child = props.children
|
|
29
|
+
if not child then
|
|
30
|
+
error("[TextareaLabel] `asChild` requires a child element.")
|
|
31
|
+
end
|
|
32
|
+
local _attributes = table.clone(sharedProps)
|
|
33
|
+
setmetatable(_attributes, nil)
|
|
34
|
+
return React.createElement(Slot, _attributes, child)
|
|
35
|
+
end
|
|
36
|
+
local _attributes = table.clone(sharedProps)
|
|
37
|
+
setmetatable(_attributes, nil)
|
|
38
|
+
_attributes.AutoButtonColor = false
|
|
39
|
+
_attributes.BackgroundTransparency = 1
|
|
40
|
+
_attributes.BorderSizePixel = 0
|
|
41
|
+
_attributes.Size = UDim2.fromOffset(240, 22)
|
|
42
|
+
_attributes.TextColor3 = if disabled then Color3.fromRGB(149, 157, 173) else Color3.fromRGB(225, 231, 241)
|
|
43
|
+
_attributes.TextSize = 14
|
|
44
|
+
_attributes.TextXAlignment = Enum.TextXAlignment.Left
|
|
45
|
+
return React.createElement("textbutton", _attributes)
|
|
46
|
+
end
|
|
47
|
+
return {
|
|
48
|
+
TextareaLabel = TextareaLabel,
|
|
49
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
-- Compiled with roblox-ts v3.0.0
|
|
2
|
+
local TS = _G[script]
|
|
3
|
+
local _core = TS.import(script, TS.getModule(script, "@lattice-ui", "core").out)
|
|
4
|
+
local React = _core.React
|
|
5
|
+
local Slot = _core.Slot
|
|
6
|
+
local useTextareaContext = TS.import(script, script.Parent, "context").useTextareaContext
|
|
7
|
+
local function TextareaMessage(props)
|
|
8
|
+
local textareaContext = useTextareaContext()
|
|
9
|
+
if props.asChild then
|
|
10
|
+
local child = props.children
|
|
11
|
+
if not child then
|
|
12
|
+
error("[TextareaMessage] `asChild` requires a child element.")
|
|
13
|
+
end
|
|
14
|
+
return React.createElement(Slot, {
|
|
15
|
+
Name = "TextareaMessage",
|
|
16
|
+
Text = "Message",
|
|
17
|
+
}, child)
|
|
18
|
+
end
|
|
19
|
+
return React.createElement("textlabel", {
|
|
20
|
+
BackgroundTransparency = 1,
|
|
21
|
+
BorderSizePixel = 0,
|
|
22
|
+
Size = UDim2.fromOffset(300, 20),
|
|
23
|
+
Text = "Message",
|
|
24
|
+
TextColor3 = if textareaContext.invalid == true then Color3.fromRGB(255, 128, 128) elseif textareaContext.disabled then Color3.fromRGB(132, 139, 154) else Color3.fromRGB(170, 179, 195),
|
|
25
|
+
TextSize = 13,
|
|
26
|
+
TextXAlignment = Enum.TextXAlignment.Left,
|
|
27
|
+
})
|
|
28
|
+
end
|
|
29
|
+
return {
|
|
30
|
+
TextareaMessage = TextareaMessage,
|
|
31
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
-- Compiled with roblox-ts v3.0.0
|
|
2
|
+
local TS = _G[script]
|
|
3
|
+
local _core = TS.import(script, TS.getModule(script, "@lattice-ui", "core").out)
|
|
4
|
+
local React = _core.React
|
|
5
|
+
local useControllableState = _core.useControllableState
|
|
6
|
+
local TextareaContextProvider = TS.import(script, script.Parent, "context").TextareaContextProvider
|
|
7
|
+
local function TextareaRoot(props)
|
|
8
|
+
local _object = {
|
|
9
|
+
value = props.value,
|
|
10
|
+
}
|
|
11
|
+
local _left = "defaultValue"
|
|
12
|
+
local _condition = props.defaultValue
|
|
13
|
+
if _condition == nil then
|
|
14
|
+
_condition = ""
|
|
15
|
+
end
|
|
16
|
+
_object[_left] = _condition
|
|
17
|
+
_object.onChange = props.onValueChange
|
|
18
|
+
local _binding = useControllableState(_object)
|
|
19
|
+
local value = _binding[1]
|
|
20
|
+
local setValueState = _binding[2]
|
|
21
|
+
local disabled = props.disabled == true
|
|
22
|
+
local readOnly = props.readOnly == true
|
|
23
|
+
local required = props.required == true
|
|
24
|
+
local invalid = props.invalid == true
|
|
25
|
+
local _condition_1 = props.autoResize
|
|
26
|
+
if _condition_1 == nil then
|
|
27
|
+
_condition_1 = true
|
|
28
|
+
end
|
|
29
|
+
local autoResize = _condition_1
|
|
30
|
+
local _condition_2 = props.minRows
|
|
31
|
+
if _condition_2 == nil then
|
|
32
|
+
_condition_2 = 3
|
|
33
|
+
end
|
|
34
|
+
local minRows = math.max(1, _condition_2)
|
|
35
|
+
local maxRows = if props.maxRows ~= nil then math.max(minRows, props.maxRows) else nil
|
|
36
|
+
local inputRef = React.useRef()
|
|
37
|
+
local setValue = React.useCallback(function(nextValue)
|
|
38
|
+
if disabled or readOnly then
|
|
39
|
+
return nil
|
|
40
|
+
end
|
|
41
|
+
setValueState(nextValue)
|
|
42
|
+
end, { disabled, readOnly, setValueState })
|
|
43
|
+
local commitValue = React.useCallback(function(nextValue)
|
|
44
|
+
local _result = props.onValueCommit
|
|
45
|
+
if _result ~= nil then
|
|
46
|
+
_result(nextValue)
|
|
47
|
+
end
|
|
48
|
+
end, { props.onValueCommit })
|
|
49
|
+
local contextValue = React.useMemo(function()
|
|
50
|
+
return {
|
|
51
|
+
value = value,
|
|
52
|
+
setValue = setValue,
|
|
53
|
+
commitValue = commitValue,
|
|
54
|
+
disabled = disabled,
|
|
55
|
+
readOnly = readOnly,
|
|
56
|
+
required = required,
|
|
57
|
+
invalid = invalid,
|
|
58
|
+
name = props.name,
|
|
59
|
+
autoResize = autoResize,
|
|
60
|
+
minRows = minRows,
|
|
61
|
+
maxRows = maxRows,
|
|
62
|
+
inputRef = inputRef,
|
|
63
|
+
}
|
|
64
|
+
end, { autoResize, commitValue, disabled, invalid, maxRows, minRows, props.name, readOnly, required, setValue, value })
|
|
65
|
+
return React.createElement(TextareaContextProvider, {
|
|
66
|
+
value = contextValue,
|
|
67
|
+
}, props.children)
|
|
68
|
+
end
|
|
69
|
+
return {
|
|
70
|
+
TextareaRoot = TextareaRoot,
|
|
71
|
+
Textarea = TextareaRoot,
|
|
72
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
-- Compiled with roblox-ts v3.0.0
|
|
2
|
+
local function countLines(text)
|
|
3
|
+
if #text == 0 then
|
|
4
|
+
return 1
|
|
5
|
+
end
|
|
6
|
+
return #string.split(text, "\n")
|
|
7
|
+
end
|
|
8
|
+
local function resolveTextareaHeight(text, options)
|
|
9
|
+
local minRows = math.max(1, math.floor(options.minRows))
|
|
10
|
+
local maxRows = if options.maxRows ~= nil then math.max(minRows, math.floor(options.maxRows)) else nil
|
|
11
|
+
local lineHeight = math.max(1, options.lineHeight)
|
|
12
|
+
local _condition = options.verticalPadding
|
|
13
|
+
if _condition == nil then
|
|
14
|
+
_condition = 0
|
|
15
|
+
end
|
|
16
|
+
local verticalPadding = math.max(0, _condition)
|
|
17
|
+
local naturalRows = countLines(text)
|
|
18
|
+
local clampedRows = if maxRows ~= nil then math.clamp(naturalRows, minRows, maxRows) else math.max(minRows, naturalRows)
|
|
19
|
+
return clampedRows * lineHeight + verticalPadding
|
|
20
|
+
end
|
|
21
|
+
return {
|
|
22
|
+
resolveTextareaHeight = resolveTextareaHeight,
|
|
23
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
-- Compiled with roblox-ts v3.0.0
|
|
2
|
+
local TS = _G[script]
|
|
3
|
+
local createStrictContext = TS.import(script, TS.getModule(script, "@lattice-ui", "core").out).createStrictContext
|
|
4
|
+
local _binding = createStrictContext("Textarea")
|
|
5
|
+
local TextareaContextProvider = _binding[1]
|
|
6
|
+
local useTextareaContext = _binding[2]
|
|
7
|
+
return {
|
|
8
|
+
TextareaContextProvider = TextareaContextProvider,
|
|
9
|
+
useTextareaContext = useTextareaContext,
|
|
10
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import type React from "@rbxts/react";
|
|
2
|
+
export type TextareaSetValue = (value: string) => void;
|
|
3
|
+
export type TextareaCommitValue = (value: string) => void;
|
|
4
|
+
export type TextareaContextValue = {
|
|
5
|
+
value: string;
|
|
6
|
+
setValue: TextareaSetValue;
|
|
7
|
+
commitValue: TextareaCommitValue;
|
|
8
|
+
disabled: boolean;
|
|
9
|
+
readOnly: boolean;
|
|
10
|
+
required: boolean;
|
|
11
|
+
invalid: boolean;
|
|
12
|
+
name?: string;
|
|
13
|
+
autoResize: boolean;
|
|
14
|
+
minRows: number;
|
|
15
|
+
maxRows?: number;
|
|
16
|
+
inputRef: React.MutableRefObject<TextBox | undefined>;
|
|
17
|
+
};
|
|
18
|
+
export type TextareaProps = {
|
|
19
|
+
value?: string;
|
|
20
|
+
defaultValue?: string;
|
|
21
|
+
onValueChange?: (value: string) => void;
|
|
22
|
+
onValueCommit?: (value: string) => void;
|
|
23
|
+
disabled?: boolean;
|
|
24
|
+
readOnly?: boolean;
|
|
25
|
+
required?: boolean;
|
|
26
|
+
invalid?: boolean;
|
|
27
|
+
name?: string;
|
|
28
|
+
autoResize?: boolean;
|
|
29
|
+
minRows?: number;
|
|
30
|
+
maxRows?: number;
|
|
31
|
+
children?: React.ReactNode;
|
|
32
|
+
};
|
|
33
|
+
export type TextareaInputProps = {
|
|
34
|
+
asChild?: boolean;
|
|
35
|
+
disabled?: boolean;
|
|
36
|
+
readOnly?: boolean;
|
|
37
|
+
lineHeight?: number;
|
|
38
|
+
children?: React.ReactElement;
|
|
39
|
+
};
|
|
40
|
+
export type TextareaLabelProps = {
|
|
41
|
+
asChild?: boolean;
|
|
42
|
+
children?: React.ReactElement;
|
|
43
|
+
};
|
|
44
|
+
export type TextareaDescriptionProps = {
|
|
45
|
+
asChild?: boolean;
|
|
46
|
+
children?: React.ReactElement;
|
|
47
|
+
};
|
|
48
|
+
export type TextareaMessageProps = {
|
|
49
|
+
asChild?: boolean;
|
|
50
|
+
children?: React.ReactElement;
|
|
51
|
+
};
|
package/out/index.d.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { TextareaDescription } from "./Textarea/TextareaDescription";
|
|
2
|
+
import { TextareaInput } from "./Textarea/TextareaInput";
|
|
3
|
+
import { TextareaLabel } from "./Textarea/TextareaLabel";
|
|
4
|
+
import { TextareaMessage } from "./Textarea/TextareaMessage";
|
|
5
|
+
import { TextareaRoot } from "./Textarea/TextareaRoot";
|
|
6
|
+
export declare const Textarea: {
|
|
7
|
+
readonly Root: typeof TextareaRoot;
|
|
8
|
+
readonly Input: typeof TextareaInput;
|
|
9
|
+
readonly Label: typeof TextareaLabel;
|
|
10
|
+
readonly Description: typeof TextareaDescription;
|
|
11
|
+
readonly Message: typeof TextareaMessage;
|
|
12
|
+
};
|
|
13
|
+
export { resolveTextareaHeight } from "./Textarea/autoResize";
|
|
14
|
+
export type { TextareaCommitValue, TextareaContextValue, TextareaDescriptionProps, TextareaInputProps, TextareaLabelProps, TextareaMessageProps, TextareaProps, TextareaSetValue, } from "./Textarea/types";
|
package/out/init.luau
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
-- Compiled with roblox-ts v3.0.0
|
|
2
|
+
local TS = _G[script]
|
|
3
|
+
local exports = {}
|
|
4
|
+
local TextareaDescription = TS.import(script, script, "Textarea", "TextareaDescription").TextareaDescription
|
|
5
|
+
local TextareaInput = TS.import(script, script, "Textarea", "TextareaInput").TextareaInput
|
|
6
|
+
local TextareaLabel = TS.import(script, script, "Textarea", "TextareaLabel").TextareaLabel
|
|
7
|
+
local TextareaMessage = TS.import(script, script, "Textarea", "TextareaMessage").TextareaMessage
|
|
8
|
+
local TextareaRoot = TS.import(script, script, "Textarea", "TextareaRoot").TextareaRoot
|
|
9
|
+
local Textarea = {
|
|
10
|
+
Root = TextareaRoot,
|
|
11
|
+
Input = TextareaInput,
|
|
12
|
+
Label = TextareaLabel,
|
|
13
|
+
Description = TextareaDescription,
|
|
14
|
+
Message = TextareaMessage,
|
|
15
|
+
}
|
|
16
|
+
exports.resolveTextareaHeight = TS.import(script, script, "Textarea", "autoResize").resolveTextareaHeight
|
|
17
|
+
exports.Textarea = Textarea
|
|
18
|
+
return exports
|
package/package.json
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@lattice-ui/textarea",
|
|
3
|
+
"version": "0.3.0",
|
|
4
|
+
"private": false,
|
|
5
|
+
"main": "out/init.luau",
|
|
6
|
+
"types": "out/index.d.ts",
|
|
7
|
+
"dependencies": {
|
|
8
|
+
"@lattice-ui/core": "0.3.0"
|
|
9
|
+
},
|
|
10
|
+
"devDependencies": {
|
|
11
|
+
"@rbxts/react": "17.3.7-ts.1",
|
|
12
|
+
"@rbxts/react-roblox": "17.3.7-ts.1"
|
|
13
|
+
},
|
|
14
|
+
"peerDependencies": {
|
|
15
|
+
"@rbxts/react": "^17",
|
|
16
|
+
"@rbxts/react-roblox": "^17"
|
|
17
|
+
},
|
|
18
|
+
"scripts": {
|
|
19
|
+
"build": "rbxtsc -p tsconfig.json",
|
|
20
|
+
"typecheck": "tsc -p tsconfig.typecheck.json",
|
|
21
|
+
"watch": "rbxtsc -p tsconfig.json -w"
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { React, Slot } from "@lattice-ui/core";
|
|
2
|
+
import { useTextareaContext } from "./context";
|
|
3
|
+
import type { TextareaDescriptionProps } from "./types";
|
|
4
|
+
|
|
5
|
+
export function TextareaDescription(props: TextareaDescriptionProps) {
|
|
6
|
+
const textareaContext = useTextareaContext();
|
|
7
|
+
|
|
8
|
+
if (props.asChild) {
|
|
9
|
+
const child = props.children;
|
|
10
|
+
if (!child) {
|
|
11
|
+
error("[TextareaDescription] `asChild` requires a child element.");
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
return (
|
|
15
|
+
<Slot Name="TextareaDescription" Text="Description">
|
|
16
|
+
{child}
|
|
17
|
+
</Slot>
|
|
18
|
+
);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
return (
|
|
22
|
+
<textlabel
|
|
23
|
+
BackgroundTransparency={1}
|
|
24
|
+
BorderSizePixel={0}
|
|
25
|
+
Size={UDim2.fromOffset(300, 20)}
|
|
26
|
+
Text="Description"
|
|
27
|
+
TextColor3={textareaContext.disabled ? Color3.fromRGB(132, 139, 154) : Color3.fromRGB(170, 179, 195)}
|
|
28
|
+
TextSize={13}
|
|
29
|
+
TextXAlignment={Enum.TextXAlignment.Left}
|
|
30
|
+
/>
|
|
31
|
+
);
|
|
32
|
+
}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import { React, Slot } from "@lattice-ui/core";
|
|
2
|
+
import { resolveTextareaHeight } from "./autoResize";
|
|
3
|
+
import { useTextareaContext } from "./context";
|
|
4
|
+
import type { TextareaInputProps } from "./types";
|
|
5
|
+
|
|
6
|
+
function toTextBox(instance: Instance | undefined) {
|
|
7
|
+
if (!instance || !instance.IsA("TextBox")) {
|
|
8
|
+
return undefined;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
return instance;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function TextareaInput(props: TextareaInputProps) {
|
|
15
|
+
const textareaContext = useTextareaContext();
|
|
16
|
+
const disabled = textareaContext.disabled || props.disabled === true;
|
|
17
|
+
const readOnly = textareaContext.readOnly || props.readOnly === true;
|
|
18
|
+
const lineHeight = props.lineHeight ?? 18;
|
|
19
|
+
|
|
20
|
+
const setInputRef = React.useCallback(
|
|
21
|
+
(instance: Instance | undefined) => {
|
|
22
|
+
textareaContext.inputRef.current = toTextBox(instance);
|
|
23
|
+
},
|
|
24
|
+
[textareaContext.inputRef],
|
|
25
|
+
);
|
|
26
|
+
|
|
27
|
+
const applyAutoResize = React.useCallback(
|
|
28
|
+
(textBox: TextBox) => {
|
|
29
|
+
if (!textareaContext.autoResize) {
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const height = resolveTextareaHeight(textBox.Text, {
|
|
34
|
+
lineHeight,
|
|
35
|
+
minRows: textareaContext.minRows,
|
|
36
|
+
maxRows: textareaContext.maxRows,
|
|
37
|
+
verticalPadding: 14,
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
const currentSize = textBox.Size;
|
|
41
|
+
if (currentSize.Y.Offset !== height || currentSize.Y.Scale !== 0) {
|
|
42
|
+
textBox.Size = UDim2.fromOffset(currentSize.X.Offset, height);
|
|
43
|
+
}
|
|
44
|
+
},
|
|
45
|
+
[lineHeight, textareaContext.autoResize, textareaContext.maxRows, textareaContext.minRows],
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
const handleTextChanged = React.useCallback(
|
|
49
|
+
(textBox: TextBox) => {
|
|
50
|
+
if (disabled || readOnly) {
|
|
51
|
+
if (textBox.Text !== textareaContext.value) {
|
|
52
|
+
textBox.Text = textareaContext.value;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
applyAutoResize(textBox);
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
textareaContext.setValue(textBox.Text);
|
|
60
|
+
applyAutoResize(textBox);
|
|
61
|
+
},
|
|
62
|
+
[applyAutoResize, disabled, readOnly, textareaContext],
|
|
63
|
+
);
|
|
64
|
+
|
|
65
|
+
const handleFocusLost = React.useCallback(
|
|
66
|
+
(textBox: TextBox) => {
|
|
67
|
+
if (disabled) {
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
textareaContext.commitValue(textBox.Text);
|
|
72
|
+
},
|
|
73
|
+
[disabled, textareaContext],
|
|
74
|
+
);
|
|
75
|
+
|
|
76
|
+
React.useEffect(() => {
|
|
77
|
+
const input = textareaContext.inputRef.current;
|
|
78
|
+
if (!input) {
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
applyAutoResize(input);
|
|
83
|
+
}, [applyAutoResize, textareaContext.inputRef, textareaContext.value]);
|
|
84
|
+
|
|
85
|
+
const sharedProps = {
|
|
86
|
+
Active: !disabled,
|
|
87
|
+
ClearTextOnFocus: false,
|
|
88
|
+
MultiLine: true,
|
|
89
|
+
Selectable: !disabled,
|
|
90
|
+
Text: textareaContext.value,
|
|
91
|
+
TextEditable: !disabled && !readOnly,
|
|
92
|
+
TextWrapped: true,
|
|
93
|
+
Change: {
|
|
94
|
+
Text: handleTextChanged,
|
|
95
|
+
},
|
|
96
|
+
Event: {
|
|
97
|
+
FocusLost: handleFocusLost,
|
|
98
|
+
},
|
|
99
|
+
ref: setInputRef,
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
if (props.asChild) {
|
|
103
|
+
const child = props.children;
|
|
104
|
+
if (!child) {
|
|
105
|
+
error("[TextareaInput] `asChild` requires a child element.");
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
return <Slot {...sharedProps}>{child}</Slot>;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
return (
|
|
112
|
+
<textbox
|
|
113
|
+
{...sharedProps}
|
|
114
|
+
BackgroundColor3={Color3.fromRGB(39, 46, 61)}
|
|
115
|
+
BorderSizePixel={0}
|
|
116
|
+
PlaceholderText="Type..."
|
|
117
|
+
Size={UDim2.fromOffset(240, 68)}
|
|
118
|
+
TextColor3={disabled ? Color3.fromRGB(137, 145, 162) : Color3.fromRGB(235, 240, 248)}
|
|
119
|
+
TextSize={15}
|
|
120
|
+
TextXAlignment={Enum.TextXAlignment.Left}
|
|
121
|
+
TextYAlignment={Enum.TextYAlignment.Top}
|
|
122
|
+
>
|
|
123
|
+
<uipadding
|
|
124
|
+
PaddingBottom={new UDim(0, 7)}
|
|
125
|
+
PaddingLeft={new UDim(0, 10)}
|
|
126
|
+
PaddingRight={new UDim(0, 10)}
|
|
127
|
+
PaddingTop={new UDim(0, 7)}
|
|
128
|
+
/>
|
|
129
|
+
</textbox>
|
|
130
|
+
);
|
|
131
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { React, Slot } from "@lattice-ui/core";
|
|
2
|
+
import { useTextareaContext } from "./context";
|
|
3
|
+
import type { TextareaLabelProps } from "./types";
|
|
4
|
+
|
|
5
|
+
export function TextareaLabel(props: TextareaLabelProps) {
|
|
6
|
+
const textareaContext = useTextareaContext();
|
|
7
|
+
const disabled = textareaContext.disabled;
|
|
8
|
+
|
|
9
|
+
const handleActivated = React.useCallback(() => {
|
|
10
|
+
if (disabled) {
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
textareaContext.inputRef.current?.CaptureFocus();
|
|
15
|
+
}, [disabled, textareaContext.inputRef]);
|
|
16
|
+
|
|
17
|
+
const sharedProps = {
|
|
18
|
+
Active: !disabled,
|
|
19
|
+
Selectable: !disabled,
|
|
20
|
+
Text: "Label",
|
|
21
|
+
Event: {
|
|
22
|
+
Activated: handleActivated,
|
|
23
|
+
},
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
if (props.asChild) {
|
|
27
|
+
const child = props.children;
|
|
28
|
+
if (!child) {
|
|
29
|
+
error("[TextareaLabel] `asChild` requires a child element.");
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
return <Slot {...sharedProps}>{child}</Slot>;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
return (
|
|
36
|
+
<textbutton
|
|
37
|
+
{...sharedProps}
|
|
38
|
+
AutoButtonColor={false}
|
|
39
|
+
BackgroundTransparency={1}
|
|
40
|
+
BorderSizePixel={0}
|
|
41
|
+
Size={UDim2.fromOffset(240, 22)}
|
|
42
|
+
TextColor3={disabled ? Color3.fromRGB(149, 157, 173) : Color3.fromRGB(225, 231, 241)}
|
|
43
|
+
TextSize={14}
|
|
44
|
+
TextXAlignment={Enum.TextXAlignment.Left}
|
|
45
|
+
/>
|
|
46
|
+
);
|
|
47
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { React, Slot } from "@lattice-ui/core";
|
|
2
|
+
import { useTextareaContext } from "./context";
|
|
3
|
+
import type { TextareaMessageProps } from "./types";
|
|
4
|
+
|
|
5
|
+
export function TextareaMessage(props: TextareaMessageProps) {
|
|
6
|
+
const textareaContext = useTextareaContext();
|
|
7
|
+
|
|
8
|
+
if (props.asChild) {
|
|
9
|
+
const child = props.children;
|
|
10
|
+
if (!child) {
|
|
11
|
+
error("[TextareaMessage] `asChild` requires a child element.");
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
return (
|
|
15
|
+
<Slot Name="TextareaMessage" Text="Message">
|
|
16
|
+
{child}
|
|
17
|
+
</Slot>
|
|
18
|
+
);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
return (
|
|
22
|
+
<textlabel
|
|
23
|
+
BackgroundTransparency={1}
|
|
24
|
+
BorderSizePixel={0}
|
|
25
|
+
Size={UDim2.fromOffset(300, 20)}
|
|
26
|
+
Text="Message"
|
|
27
|
+
TextColor3={
|
|
28
|
+
textareaContext.invalid === true
|
|
29
|
+
? Color3.fromRGB(255, 128, 128)
|
|
30
|
+
: textareaContext.disabled
|
|
31
|
+
? Color3.fromRGB(132, 139, 154)
|
|
32
|
+
: Color3.fromRGB(170, 179, 195)
|
|
33
|
+
}
|
|
34
|
+
TextSize={13}
|
|
35
|
+
TextXAlignment={Enum.TextXAlignment.Left}
|
|
36
|
+
/>
|
|
37
|
+
);
|
|
38
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { React, useControllableState } from "@lattice-ui/core";
|
|
2
|
+
import { TextareaContextProvider } from "./context";
|
|
3
|
+
import type { TextareaProps } from "./types";
|
|
4
|
+
|
|
5
|
+
export function TextareaRoot(props: TextareaProps) {
|
|
6
|
+
const [value, setValueState] = useControllableState<string>({
|
|
7
|
+
value: props.value,
|
|
8
|
+
defaultValue: props.defaultValue ?? "",
|
|
9
|
+
onChange: props.onValueChange,
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
const disabled = props.disabled === true;
|
|
13
|
+
const readOnly = props.readOnly === true;
|
|
14
|
+
const required = props.required === true;
|
|
15
|
+
const invalid = props.invalid === true;
|
|
16
|
+
const autoResize = props.autoResize ?? true;
|
|
17
|
+
const minRows = math.max(1, props.minRows ?? 3);
|
|
18
|
+
const maxRows = props.maxRows !== undefined ? math.max(minRows, props.maxRows) : undefined;
|
|
19
|
+
|
|
20
|
+
const inputRef = React.useRef<TextBox>();
|
|
21
|
+
|
|
22
|
+
const setValue = React.useCallback(
|
|
23
|
+
(nextValue: string) => {
|
|
24
|
+
if (disabled || readOnly) {
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
setValueState(nextValue);
|
|
29
|
+
},
|
|
30
|
+
[disabled, readOnly, setValueState],
|
|
31
|
+
);
|
|
32
|
+
|
|
33
|
+
const commitValue = React.useCallback(
|
|
34
|
+
(nextValue: string) => {
|
|
35
|
+
props.onValueCommit?.(nextValue);
|
|
36
|
+
},
|
|
37
|
+
[props.onValueCommit],
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
const contextValue = React.useMemo(
|
|
41
|
+
() => ({
|
|
42
|
+
value,
|
|
43
|
+
setValue,
|
|
44
|
+
commitValue,
|
|
45
|
+
disabled,
|
|
46
|
+
readOnly,
|
|
47
|
+
required,
|
|
48
|
+
invalid,
|
|
49
|
+
name: props.name,
|
|
50
|
+
autoResize,
|
|
51
|
+
minRows,
|
|
52
|
+
maxRows,
|
|
53
|
+
inputRef,
|
|
54
|
+
}),
|
|
55
|
+
[autoResize, commitValue, disabled, invalid, maxRows, minRows, props.name, readOnly, required, setValue, value],
|
|
56
|
+
);
|
|
57
|
+
|
|
58
|
+
return <TextareaContextProvider value={contextValue}>{props.children}</TextareaContextProvider>;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export { TextareaRoot as Textarea };
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export type TextareaAutoResizeOptions = {
|
|
2
|
+
minRows: number;
|
|
3
|
+
maxRows?: number;
|
|
4
|
+
lineHeight: number;
|
|
5
|
+
verticalPadding?: number;
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
function countLines(text: string) {
|
|
9
|
+
if (text.size() === 0) {
|
|
10
|
+
return 1;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
return text.split("\n").size();
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function resolveTextareaHeight(text: string, options: TextareaAutoResizeOptions) {
|
|
17
|
+
const minRows = math.max(1, math.floor(options.minRows));
|
|
18
|
+
const maxRows = options.maxRows !== undefined ? math.max(minRows, math.floor(options.maxRows)) : undefined;
|
|
19
|
+
const lineHeight = math.max(1, options.lineHeight);
|
|
20
|
+
const verticalPadding = math.max(0, options.verticalPadding ?? 0);
|
|
21
|
+
|
|
22
|
+
const naturalRows = countLines(text);
|
|
23
|
+
const clampedRows =
|
|
24
|
+
maxRows !== undefined ? math.clamp(naturalRows, minRows, maxRows) : math.max(minRows, naturalRows);
|
|
25
|
+
|
|
26
|
+
return clampedRows * lineHeight + verticalPadding;
|
|
27
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { createStrictContext } from "@lattice-ui/core";
|
|
2
|
+
import type { TextareaContextValue } from "./types";
|
|
3
|
+
|
|
4
|
+
const [TextareaContextProvider, useTextareaContext] = createStrictContext<TextareaContextValue>("Textarea");
|
|
5
|
+
|
|
6
|
+
export { TextareaContextProvider, useTextareaContext };
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import type React from "@rbxts/react";
|
|
2
|
+
|
|
3
|
+
export type TextareaSetValue = (value: string) => void;
|
|
4
|
+
export type TextareaCommitValue = (value: string) => void;
|
|
5
|
+
|
|
6
|
+
export type TextareaContextValue = {
|
|
7
|
+
value: string;
|
|
8
|
+
setValue: TextareaSetValue;
|
|
9
|
+
commitValue: TextareaCommitValue;
|
|
10
|
+
disabled: boolean;
|
|
11
|
+
readOnly: boolean;
|
|
12
|
+
required: boolean;
|
|
13
|
+
invalid: boolean;
|
|
14
|
+
name?: string;
|
|
15
|
+
autoResize: boolean;
|
|
16
|
+
minRows: number;
|
|
17
|
+
maxRows?: number;
|
|
18
|
+
inputRef: React.MutableRefObject<TextBox | undefined>;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export type TextareaProps = {
|
|
22
|
+
value?: string;
|
|
23
|
+
defaultValue?: string;
|
|
24
|
+
onValueChange?: (value: string) => void;
|
|
25
|
+
onValueCommit?: (value: string) => void;
|
|
26
|
+
disabled?: boolean;
|
|
27
|
+
readOnly?: boolean;
|
|
28
|
+
required?: boolean;
|
|
29
|
+
invalid?: boolean;
|
|
30
|
+
name?: string;
|
|
31
|
+
autoResize?: boolean;
|
|
32
|
+
minRows?: number;
|
|
33
|
+
maxRows?: number;
|
|
34
|
+
children?: React.ReactNode;
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
export type TextareaInputProps = {
|
|
38
|
+
asChild?: boolean;
|
|
39
|
+
disabled?: boolean;
|
|
40
|
+
readOnly?: boolean;
|
|
41
|
+
lineHeight?: number;
|
|
42
|
+
children?: React.ReactElement;
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
export type TextareaLabelProps = {
|
|
46
|
+
asChild?: boolean;
|
|
47
|
+
children?: React.ReactElement;
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
export type TextareaDescriptionProps = {
|
|
51
|
+
asChild?: boolean;
|
|
52
|
+
children?: React.ReactElement;
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
export type TextareaMessageProps = {
|
|
56
|
+
asChild?: boolean;
|
|
57
|
+
children?: React.ReactElement;
|
|
58
|
+
};
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { TextareaDescription } from "./Textarea/TextareaDescription";
|
|
2
|
+
import { TextareaInput } from "./Textarea/TextareaInput";
|
|
3
|
+
import { TextareaLabel } from "./Textarea/TextareaLabel";
|
|
4
|
+
import { TextareaMessage } from "./Textarea/TextareaMessage";
|
|
5
|
+
import { TextareaRoot } from "./Textarea/TextareaRoot";
|
|
6
|
+
|
|
7
|
+
export const Textarea = {
|
|
8
|
+
Root: TextareaRoot,
|
|
9
|
+
Input: TextareaInput,
|
|
10
|
+
Label: TextareaLabel,
|
|
11
|
+
Description: TextareaDescription,
|
|
12
|
+
Message: TextareaMessage,
|
|
13
|
+
} as const;
|
|
14
|
+
|
|
15
|
+
export { resolveTextareaHeight } from "./Textarea/autoResize";
|
|
16
|
+
export type {
|
|
17
|
+
TextareaCommitValue,
|
|
18
|
+
TextareaContextValue,
|
|
19
|
+
TextareaDescriptionProps,
|
|
20
|
+
TextareaInputProps,
|
|
21
|
+
TextareaLabelProps,
|
|
22
|
+
TextareaMessageProps,
|
|
23
|
+
TextareaProps,
|
|
24
|
+
TextareaSetValue,
|
|
25
|
+
} from "./Textarea/types";
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"extends": "../../tsconfig.base.json",
|
|
3
|
+
"compilerOptions": {
|
|
4
|
+
"rootDir": "src",
|
|
5
|
+
"outDir": "out",
|
|
6
|
+
"declaration": true,
|
|
7
|
+
"typeRoots": [
|
|
8
|
+
"./node_modules/@rbxts",
|
|
9
|
+
"../../node_modules/@rbxts",
|
|
10
|
+
"./node_modules/@lattice-ui",
|
|
11
|
+
"../../node_modules/@lattice-ui"
|
|
12
|
+
],
|
|
13
|
+
"types": ["types", "compiler-types"]
|
|
14
|
+
},
|
|
15
|
+
"include": ["src"]
|
|
16
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
{
|
|
2
|
+
"extends": "./tsconfig.json",
|
|
3
|
+
"compilerOptions": {
|
|
4
|
+
"noEmit": true,
|
|
5
|
+
"baseUrl": "..",
|
|
6
|
+
"rootDir": "..",
|
|
7
|
+
"paths": {
|
|
8
|
+
"@lattice-ui/accordion": ["accordion/src/index.ts"],
|
|
9
|
+
"@lattice-ui/avatar": ["avatar/src/index.ts"],
|
|
10
|
+
"@lattice-ui/checkbox": ["checkbox/src/index.ts"],
|
|
11
|
+
"@lattice-ui/combobox": ["combobox/src/index.ts"],
|
|
12
|
+
"@lattice-ui/core": ["core/src/index.ts"],
|
|
13
|
+
"@lattice-ui/dialog": ["dialog/src/index.ts"],
|
|
14
|
+
"@lattice-ui/focus": ["focus/src/index.ts"],
|
|
15
|
+
"@lattice-ui/layer": ["layer/src/index.ts"],
|
|
16
|
+
"@lattice-ui/menu": ["menu/src/index.ts"],
|
|
17
|
+
"@lattice-ui/popover": ["popover/src/index.ts"],
|
|
18
|
+
"@lattice-ui/popper": ["popper/src/index.ts"],
|
|
19
|
+
"@lattice-ui/progress": ["progress/src/index.ts"],
|
|
20
|
+
"@lattice-ui/radio-group": ["radio-group/src/index.ts"],
|
|
21
|
+
"@lattice-ui/scroll-area": ["scroll-area/src/index.ts"],
|
|
22
|
+
"@lattice-ui/select": ["select/src/index.ts"],
|
|
23
|
+
"@lattice-ui/slider": ["slider/src/index.ts"],
|
|
24
|
+
"@lattice-ui/style": ["style/src/index.ts"],
|
|
25
|
+
"@lattice-ui/switch": ["switch/src/index.ts"],
|
|
26
|
+
"@lattice-ui/system": ["system/src/index.ts"],
|
|
27
|
+
"@lattice-ui/tabs": ["tabs/src/index.ts"],
|
|
28
|
+
"@lattice-ui/text-field": ["text-field/src/index.ts"],
|
|
29
|
+
"@lattice-ui/textarea": ["textarea/src/index.ts"],
|
|
30
|
+
"@lattice-ui/toast": ["toast/src/index.ts"],
|
|
31
|
+
"@lattice-ui/toggle-group": ["toggle-group/src/index.ts"],
|
|
32
|
+
"@lattice-ui/tooltip": ["tooltip/src/index.ts"]
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|