@lattice-ui/textarea 0.3.1 → 0.4.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.
@@ -0,0 +1,4 @@
1
+
2
+ > @lattice-ui/textarea@0.4.0 build C:\Users\retur\OneDrive\Desktop\Workspace\rojo\unnamed-ui-package\packages\textarea
3
+ > rbxtsc -p tsconfig.json
4
+
@@ -0,0 +1,4 @@
1
+
2
+ > @lattice-ui/textarea@0.4.0 typecheck /home/runner/work/lattice-ui/lattice-ui/packages/textarea
3
+ > tsc -p tsconfig.typecheck.json
4
+
@@ -11,15 +11,32 @@ local function toTextBox(instance)
11
11
  end
12
12
  return instance
13
13
  end
14
+ local function resolveVerticalPadding(textBox)
15
+ local verticalPadding = 0
16
+ for _, child in textBox:GetChildren() do
17
+ if not child:IsA("UIPadding") then
18
+ continue
19
+ end
20
+ verticalPadding += child.PaddingTop.Offset + child.PaddingBottom.Offset
21
+ verticalPadding += math.floor(child.PaddingTop.Scale * textBox.AbsoluteSize.Y)
22
+ verticalPadding += math.floor(child.PaddingBottom.Scale * textBox.AbsoluteSize.Y)
23
+ end
24
+ return if verticalPadding > 0 then verticalPadding else 14
25
+ end
26
+ local function resolveLineHeight(textBox, explicitLineHeight)
27
+ if explicitLineHeight ~= nil then
28
+ return math.max(1, explicitLineHeight)
29
+ end
30
+ return math.max(1, math.ceil(textBox.TextSize * 1.2))
31
+ end
32
+ local function resolveMeasuredRows(textBox, lineHeight)
33
+ local textBoundsHeight = math.max(lineHeight, textBox.TextBounds.Y)
34
+ return math.max(1, math.ceil(textBoundsHeight / lineHeight))
35
+ end
14
36
  local function TextareaInput(props)
15
37
  local textareaContext = useTextareaContext()
16
38
  local disabled = textareaContext.disabled or props.disabled == true
17
39
  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
40
  local setInputRef = React.useCallback(function(instance)
24
41
  textareaContext.inputRef.current = toTextBox(instance)
25
42
  end, { textareaContext.inputRef })
@@ -27,17 +44,21 @@ local function TextareaInput(props)
27
44
  if not textareaContext.autoResize then
28
45
  return nil
29
46
  end
47
+ local lineHeight = resolveLineHeight(textBox, props.lineHeight)
48
+ local verticalPadding = resolveVerticalPadding(textBox)
49
+ local measuredRows = resolveMeasuredRows(textBox, lineHeight)
30
50
  local height = resolveTextareaHeight(textBox.Text, {
31
51
  lineHeight = lineHeight,
32
52
  minRows = textareaContext.minRows,
33
53
  maxRows = textareaContext.maxRows,
34
- verticalPadding = 14,
54
+ verticalPadding = verticalPadding,
55
+ measuredRows = measuredRows,
35
56
  })
36
57
  local currentSize = textBox.Size
37
58
  if currentSize.Y.Offset ~= height or currentSize.Y.Scale ~= 0 then
38
59
  textBox.Size = UDim2.fromOffset(currentSize.X.Offset, height)
39
60
  end
40
- end, { lineHeight, textareaContext.autoResize, textareaContext.maxRows, textareaContext.minRows })
61
+ end, { props.lineHeight, textareaContext.autoResize, textareaContext.maxRows, textareaContext.minRows })
41
62
  local handleTextChanged = React.useCallback(function(textBox)
42
63
  if disabled or readOnly then
43
64
  if textBox.Text ~= textareaContext.value then
@@ -48,6 +69,11 @@ local function TextareaInput(props)
48
69
  end
49
70
  textareaContext.setValue(textBox.Text)
50
71
  applyAutoResize(textBox)
72
+ task.defer(function()
73
+ if textareaContext.inputRef.current == textBox then
74
+ applyAutoResize(textBox)
75
+ end
76
+ end)
51
77
  end, { applyAutoResize, disabled, readOnly, textareaContext })
52
78
  local handleFocusLost = React.useCallback(function(textBox)
53
79
  if disabled then
@@ -61,6 +87,11 @@ local function TextareaInput(props)
61
87
  return nil
62
88
  end
63
89
  applyAutoResize(input)
90
+ task.defer(function()
91
+ if textareaContext.inputRef.current == input then
92
+ applyAutoResize(input)
93
+ end
94
+ end)
64
95
  end, { applyAutoResize, textareaContext.inputRef, textareaContext.value })
65
96
  local sharedProps = {
66
97
  Active = not disabled,
@@ -3,5 +3,6 @@ export type TextareaAutoResizeOptions = {
3
3
  maxRows?: number;
4
4
  lineHeight: number;
5
5
  verticalPadding?: number;
6
+ measuredRows?: number;
6
7
  };
7
8
  export declare function resolveTextareaHeight(text: string, options: TextareaAutoResizeOptions): number;
@@ -14,7 +14,9 @@ local function resolveTextareaHeight(text, options)
14
14
  _condition = 0
15
15
  end
16
16
  local verticalPadding = math.max(0, _condition)
17
- local naturalRows = countLines(text)
17
+ local newlineRows = countLines(text)
18
+ local measuredRows = if options.measuredRows ~= nil then math.max(1, math.floor(options.measuredRows)) else newlineRows
19
+ local naturalRows = math.max(newlineRows, measuredRows)
18
20
  local clampedRows = if maxRows ~= nil then math.clamp(naturalRows, minRows, maxRows) else math.max(minRows, naturalRows)
19
21
  return clampedRows * lineHeight + verticalPadding
20
22
  end
package/package.json CHANGED
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "name": "@lattice-ui/textarea",
3
- "version": "0.3.1",
3
+ "version": "0.4.0",
4
4
  "private": false,
5
5
  "main": "out/init.luau",
6
6
  "types": "out/index.d.ts",
7
7
  "dependencies": {
8
- "@lattice-ui/core": "0.3.1"
8
+ "@lattice-ui/core": "0.4.0"
9
9
  },
10
10
  "devDependencies": {
11
11
  "@rbxts/react": "17.3.7-ts.1",
@@ -11,11 +11,39 @@ function toTextBox(instance: Instance | undefined) {
11
11
  return instance;
12
12
  }
13
13
 
14
+ function resolveVerticalPadding(textBox: TextBox) {
15
+ let verticalPadding = 0;
16
+
17
+ for (const child of textBox.GetChildren()) {
18
+ if (!child.IsA("UIPadding")) {
19
+ continue;
20
+ }
21
+
22
+ verticalPadding += child.PaddingTop.Offset + child.PaddingBottom.Offset;
23
+ verticalPadding += math.floor(child.PaddingTop.Scale * textBox.AbsoluteSize.Y);
24
+ verticalPadding += math.floor(child.PaddingBottom.Scale * textBox.AbsoluteSize.Y);
25
+ }
26
+
27
+ return verticalPadding > 0 ? verticalPadding : 14;
28
+ }
29
+
30
+ function resolveLineHeight(textBox: TextBox, explicitLineHeight: number | undefined) {
31
+ if (explicitLineHeight !== undefined) {
32
+ return math.max(1, explicitLineHeight);
33
+ }
34
+
35
+ return math.max(1, math.ceil(textBox.TextSize * 1.2));
36
+ }
37
+
38
+ function resolveMeasuredRows(textBox: TextBox, lineHeight: number) {
39
+ const textBoundsHeight = math.max(lineHeight, textBox.TextBounds.Y);
40
+ return math.max(1, math.ceil(textBoundsHeight / lineHeight));
41
+ }
42
+
14
43
  export function TextareaInput(props: TextareaInputProps) {
15
44
  const textareaContext = useTextareaContext();
16
45
  const disabled = textareaContext.disabled || props.disabled === true;
17
46
  const readOnly = textareaContext.readOnly || props.readOnly === true;
18
- const lineHeight = props.lineHeight ?? 18;
19
47
 
20
48
  const setInputRef = React.useCallback(
21
49
  (instance: Instance | undefined) => {
@@ -30,11 +58,16 @@ export function TextareaInput(props: TextareaInputProps) {
30
58
  return;
31
59
  }
32
60
 
61
+ const lineHeight = resolveLineHeight(textBox, props.lineHeight);
62
+ const verticalPadding = resolveVerticalPadding(textBox);
63
+ const measuredRows = resolveMeasuredRows(textBox, lineHeight);
64
+
33
65
  const height = resolveTextareaHeight(textBox.Text, {
34
66
  lineHeight,
35
67
  minRows: textareaContext.minRows,
36
68
  maxRows: textareaContext.maxRows,
37
- verticalPadding: 14,
69
+ verticalPadding,
70
+ measuredRows,
38
71
  });
39
72
 
40
73
  const currentSize = textBox.Size;
@@ -42,7 +75,7 @@ export function TextareaInput(props: TextareaInputProps) {
42
75
  textBox.Size = UDim2.fromOffset(currentSize.X.Offset, height);
43
76
  }
44
77
  },
45
- [lineHeight, textareaContext.autoResize, textareaContext.maxRows, textareaContext.minRows],
78
+ [props.lineHeight, textareaContext.autoResize, textareaContext.maxRows, textareaContext.minRows],
46
79
  );
47
80
 
48
81
  const handleTextChanged = React.useCallback(
@@ -58,6 +91,11 @@ export function TextareaInput(props: TextareaInputProps) {
58
91
 
59
92
  textareaContext.setValue(textBox.Text);
60
93
  applyAutoResize(textBox);
94
+ task.defer(() => {
95
+ if (textareaContext.inputRef.current === textBox) {
96
+ applyAutoResize(textBox);
97
+ }
98
+ });
61
99
  },
62
100
  [applyAutoResize, disabled, readOnly, textareaContext],
63
101
  );
@@ -80,6 +118,11 @@ export function TextareaInput(props: TextareaInputProps) {
80
118
  }
81
119
 
82
120
  applyAutoResize(input);
121
+ task.defer(() => {
122
+ if (textareaContext.inputRef.current === input) {
123
+ applyAutoResize(input);
124
+ }
125
+ });
83
126
  }, [applyAutoResize, textareaContext.inputRef, textareaContext.value]);
84
127
 
85
128
  const sharedProps = {
@@ -3,6 +3,7 @@ export type TextareaAutoResizeOptions = {
3
3
  maxRows?: number;
4
4
  lineHeight: number;
5
5
  verticalPadding?: number;
6
+ measuredRows?: number;
6
7
  };
7
8
 
8
9
  function countLines(text: string) {
@@ -19,7 +20,9 @@ export function resolveTextareaHeight(text: string, options: TextareaAutoResizeO
19
20
  const lineHeight = math.max(1, options.lineHeight);
20
21
  const verticalPadding = math.max(0, options.verticalPadding ?? 0);
21
22
 
22
- const naturalRows = countLines(text);
23
+ const newlineRows = countLines(text);
24
+ const measuredRows = options.measuredRows !== undefined ? math.max(1, math.floor(options.measuredRows)) : newlineRows;
25
+ const naturalRows = math.max(newlineRows, measuredRows);
23
26
  const clampedRows =
24
27
  maxRows !== undefined ? math.clamp(naturalRows, minRows, maxRows) : math.max(minRows, naturalRows);
25
28