@rbxts/centurion-ui 1.0.0-dev-9b382c9 → 1.0.0-dev-d64d6ec
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/out/app/centurion-app.lua +2 -2
- package/out/components/history/history-line.lua +1 -1
- package/out/components/suggestions/badge.d.ts +4 -4
- package/out/components/suggestions/badge.lua +24 -28
- package/out/components/suggestions/main-suggestion.d.ts +5 -3
- package/out/components/suggestions/main-suggestion.lua +39 -50
- package/out/components/suggestions/suggestion-list.lua +8 -6
- package/out/components/suggestions/suggestions.lua +127 -59
- package/out/components/terminal/terminal-text-field.d.ts +2 -2
- package/out/components/terminal/terminal-text-field.lua +39 -39
- package/out/components/terminal/terminal.lua +20 -19
- package/out/components/ui/frame.d.ts +3 -5
- package/out/components/ui/frame.lua +11 -6
- package/out/components/ui/group.d.ts +4 -5
- package/out/components/ui/group.lua +16 -9
- package/out/components/ui/scrolling-frame.lua +7 -1
- package/out/components/ui/text-field.d.ts +0 -2
- package/out/components/ui/text-field.lua +10 -3
- package/out/components/ui/text.d.ts +0 -2
- package/out/components/ui/text.lua +10 -3
- package/out/constants/options.lua +2 -1
- package/out/hooks/use-px.d.ts +8 -24
- package/out/hooks/use-px.lua +28 -20
- package/out/hooks/use-text-bounds.d.ts +9 -0
- package/out/hooks/use-text-bounds.lua +39 -0
- package/out/types.d.ts +3 -2
- package/package.json +2 -2
|
@@ -66,8 +66,8 @@ local function CenturionApp(client)
|
|
|
66
66
|
end,
|
|
67
67
|
visible = visible,
|
|
68
68
|
}, Vide.jsx(Group, {
|
|
69
|
-
|
|
70
|
-
return options().
|
|
69
|
+
anchor = function()
|
|
70
|
+
return options().anchor
|
|
71
71
|
end,
|
|
72
72
|
size = function()
|
|
73
73
|
local size = options().size
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import Vide, { Derivable } from "@rbxts/vide";
|
|
1
|
+
import Vide, { Derivable, InstanceAttributes } from "@rbxts/vide";
|
|
2
2
|
interface BadgeProps {
|
|
3
|
-
|
|
3
|
+
anchor?: Derivable<Vector2>;
|
|
4
4
|
size?: Derivable<UDim2>;
|
|
5
5
|
position?: Derivable<UDim2>;
|
|
6
6
|
color?: Derivable<Color3>;
|
|
@@ -8,9 +8,9 @@ interface BadgeProps {
|
|
|
8
8
|
textColor?: Derivable<Color3>;
|
|
9
9
|
textSize?: Derivable<number>;
|
|
10
10
|
visible?: Derivable<boolean>;
|
|
11
|
-
onTextBoundsChange?: (textBounds: Vector2) => void;
|
|
12
11
|
children?: Vide.Node;
|
|
13
12
|
backgroundTransparency?: number;
|
|
13
|
+
native?: InstanceAttributes<TextLabel>;
|
|
14
14
|
}
|
|
15
|
-
export declare function Badge(
|
|
15
|
+
export declare function Badge(props: BadgeProps): Vide.Node;
|
|
16
16
|
export {};
|
|
@@ -6,40 +6,36 @@ local px = TS.import(script, script.Parent.Parent.Parent, "hooks", "use-px").px
|
|
|
6
6
|
local interfaceOptions = TS.import(script, script.Parent.Parent.Parent, "store").interfaceOptions
|
|
7
7
|
local Frame = TS.import(script, script.Parent.Parent, "ui", "frame").Frame
|
|
8
8
|
local Text = TS.import(script, script.Parent.Parent, "ui", "text").Text
|
|
9
|
-
local function Badge(
|
|
10
|
-
local anchorPoint = _param.anchorPoint
|
|
11
|
-
local size = _param.size
|
|
12
|
-
local position = _param.position
|
|
13
|
-
local color = _param.color
|
|
14
|
-
local text = _param.text
|
|
15
|
-
local textColor = _param.textColor
|
|
16
|
-
local textSize = _param.textSize
|
|
17
|
-
local visible = _param.visible
|
|
18
|
-
local onTextBoundsChange = _param.onTextBoundsChange
|
|
19
|
-
local children = _param.children
|
|
20
|
-
local backgroundTransparency = _param.backgroundTransparency
|
|
9
|
+
local function Badge(props)
|
|
21
10
|
local options = useAtom(interfaceOptions)
|
|
11
|
+
local _attributes = {
|
|
12
|
+
text = props.text,
|
|
13
|
+
textColor = props.textColor,
|
|
14
|
+
textSize = props.textSize,
|
|
15
|
+
textXAlignment = "Center",
|
|
16
|
+
size = UDim2.fromScale(1, 1),
|
|
17
|
+
font = function()
|
|
18
|
+
return options().font.bold
|
|
19
|
+
end,
|
|
20
|
+
}
|
|
21
|
+
local _attribute = props.native
|
|
22
|
+
if _attribute then
|
|
23
|
+
for _k, _v in _attribute do
|
|
24
|
+
_attributes[_k] = _v
|
|
25
|
+
end
|
|
26
|
+
end
|
|
22
27
|
return Vide.jsx(Frame, {
|
|
23
|
-
|
|
24
|
-
size = size,
|
|
25
|
-
position = position,
|
|
26
|
-
backgroundColor = color,
|
|
28
|
+
backgroundColor = props.color,
|
|
27
29
|
cornerRadius = function()
|
|
28
30
|
return UDim.new(0, px(4))
|
|
29
31
|
end,
|
|
30
|
-
|
|
32
|
+
backgroundTransparency = props.backgroundTransparency,
|
|
31
33
|
clipsDescendants = true,
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
size = UDim2.fromScale(1, 1),
|
|
38
|
-
font = function()
|
|
39
|
-
return options().font.bold
|
|
40
|
-
end,
|
|
41
|
-
textBoundsChanged = onTextBoundsChange,
|
|
42
|
-
}), children)
|
|
34
|
+
anchor = props.anchor,
|
|
35
|
+
position = props.position,
|
|
36
|
+
size = props.size,
|
|
37
|
+
visible = props.visible,
|
|
38
|
+
}, Vide.jsx(Text, _attributes, props.children))
|
|
43
39
|
end
|
|
44
40
|
return {
|
|
45
41
|
Badge = Badge,
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import Vide, { Derivable } from "@rbxts/vide";
|
|
2
2
|
import { Suggestion } from "../../types";
|
|
3
|
-
import { SuggestionTextBounds } from "./types";
|
|
4
3
|
export interface MainSuggestionProps {
|
|
5
4
|
suggestion: Derivable<Suggestion | undefined>;
|
|
6
5
|
currentText?: Derivable<string | undefined>;
|
|
7
6
|
size: Derivable<UDim2>;
|
|
8
|
-
|
|
7
|
+
titleSize: Derivable<UDim2>;
|
|
8
|
+
descriptionSize: Derivable<UDim2>;
|
|
9
|
+
badgeSize: Derivable<UDim2>;
|
|
10
|
+
errorSize: Derivable<UDim2>;
|
|
9
11
|
}
|
|
10
|
-
export declare function MainSuggestion({ suggestion, currentText, size,
|
|
12
|
+
export declare function MainSuggestion({ suggestion, currentText, size, titleSize, descriptionSize, badgeSize, errorSize, }: MainSuggestionProps): Vide.Node;
|
|
@@ -2,14 +2,12 @@
|
|
|
2
2
|
local TS = _G[script]
|
|
3
3
|
local _vide = TS.import(script, TS.getModule(script, "@rbxts", "vide").src)
|
|
4
4
|
local Vide = _vide
|
|
5
|
-
local effect = _vide.effect
|
|
6
5
|
local read = _vide.read
|
|
7
|
-
local
|
|
6
|
+
local spring = _vide.spring
|
|
8
7
|
local _text = TS.import(script, script.Parent.Parent.Parent, "constants", "text")
|
|
9
8
|
local SUGGESTION_TEXT_SIZE = _text.SUGGESTION_TEXT_SIZE
|
|
10
9
|
local SUGGESTION_TITLE_TEXT_SIZE = _text.SUGGESTION_TITLE_TEXT_SIZE
|
|
11
10
|
local useAtom = TS.import(script, script.Parent.Parent.Parent, "hooks", "use-atom").useAtom
|
|
12
|
-
local useMotion = TS.import(script, script.Parent.Parent.Parent, "hooks", "use-motion").useMotion
|
|
13
11
|
local px = TS.import(script, script.Parent.Parent.Parent, "hooks", "use-px").px
|
|
14
12
|
local _store = TS.import(script, script.Parent.Parent.Parent, "store")
|
|
15
13
|
local interfaceOptions = _store.interfaceOptions
|
|
@@ -23,17 +21,11 @@ local function MainSuggestion(_param)
|
|
|
23
21
|
local suggestion = _param.suggestion
|
|
24
22
|
local currentText = _param.currentText
|
|
25
23
|
local size = _param.size
|
|
26
|
-
local
|
|
24
|
+
local titleSize = _param.titleSize
|
|
25
|
+
local descriptionSize = _param.descriptionSize
|
|
26
|
+
local badgeSize = _param.badgeSize
|
|
27
|
+
local errorSize = _param.errorSize
|
|
27
28
|
local options = useAtom(interfaceOptions)
|
|
28
|
-
local titleHeight, titleHeightMotion = useMotion(0)
|
|
29
|
-
local badgeWidth, badgeWidthMotion = useMotion(0)
|
|
30
|
-
effect(function()
|
|
31
|
-
local _result = read(suggestion)
|
|
32
|
-
if _result ~= nil then
|
|
33
|
-
_result = _result.description
|
|
34
|
-
end
|
|
35
|
-
titleHeightMotion:spring(if _result ~= nil then 1 else 0, springs.responsive)
|
|
36
|
-
end)
|
|
37
29
|
return Vide.jsx(Frame, {
|
|
38
30
|
size = size,
|
|
39
31
|
backgroundColor = function()
|
|
@@ -49,23 +41,19 @@ local function MainSuggestion(_param)
|
|
|
49
41
|
cornerRadius = function()
|
|
50
42
|
return UDim.new(0, px(8))
|
|
51
43
|
end,
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
44
|
+
native = {
|
|
45
|
+
MouseEnter = function()
|
|
46
|
+
return mouseOverInterface(true)
|
|
47
|
+
end,
|
|
48
|
+
MouseLeave = function()
|
|
49
|
+
return mouseOverInterface(false)
|
|
50
|
+
end,
|
|
51
|
+
},
|
|
59
52
|
}, Vide.jsx(Padding, {
|
|
60
53
|
all = function()
|
|
61
54
|
return UDim.new(0, px(8))
|
|
62
55
|
end,
|
|
63
56
|
}), Vide.jsx(Badge, {
|
|
64
|
-
anchorPoint = Vector2.new(1, 0),
|
|
65
|
-
size = function()
|
|
66
|
-
return UDim2.fromOffset(badgeWidth(), px(24))
|
|
67
|
-
end,
|
|
68
|
-
position = UDim2.fromScale(1, 0),
|
|
69
57
|
color = function()
|
|
70
58
|
return options().palette.highlight
|
|
71
59
|
end,
|
|
@@ -83,19 +71,12 @@ local function MainSuggestion(_param)
|
|
|
83
71
|
local currentSuggestion = read(suggestion)
|
|
84
72
|
return currentSuggestion ~= nil and currentSuggestion.type == "argument"
|
|
85
73
|
end,
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
end,
|
|
74
|
+
anchor = Vector2.new(1, 0),
|
|
75
|
+
position = UDim2.fromScale(1, 0),
|
|
76
|
+
size = spring(function()
|
|
77
|
+
return UDim2.fromOffset(read(badgeSize).X.Offset + px(4), px(SUGGESTION_TITLE_TEXT_SIZE))
|
|
78
|
+
end, 0.2),
|
|
92
79
|
}), Vide.jsx(Text, {
|
|
93
|
-
size = function()
|
|
94
|
-
return read(sizes).title
|
|
95
|
-
end,
|
|
96
|
-
position = function()
|
|
97
|
-
return UDim2.fromOffset(0, 0):Lerp(UDim2.fromOffset(0, px(-4)), titleHeight())
|
|
98
|
-
end,
|
|
99
80
|
text = function()
|
|
100
81
|
local currentSuggestion = read(suggestion)
|
|
101
82
|
local _result = currentSuggestion
|
|
@@ -123,17 +104,12 @@ local function MainSuggestion(_param)
|
|
|
123
104
|
end,
|
|
124
105
|
textXAlignment = "Left",
|
|
125
106
|
textYAlignment = "Top",
|
|
126
|
-
richText = true,
|
|
127
107
|
font = function()
|
|
128
108
|
return options().font.bold
|
|
129
109
|
end,
|
|
110
|
+
richText = true,
|
|
111
|
+
size = titleSize,
|
|
130
112
|
}), Vide.jsx(Text, {
|
|
131
|
-
size = function()
|
|
132
|
-
return read(sizes).description
|
|
133
|
-
end,
|
|
134
|
-
position = function()
|
|
135
|
-
return UDim2.fromOffset(0, px(SUGGESTION_TITLE_TEXT_SIZE))
|
|
136
|
-
end,
|
|
137
113
|
text = function()
|
|
138
114
|
local _result = read(suggestion)
|
|
139
115
|
if _result ~= nil then
|
|
@@ -155,12 +131,11 @@ local function MainSuggestion(_param)
|
|
|
155
131
|
textYAlignment = "Top",
|
|
156
132
|
textWrapped = true,
|
|
157
133
|
richText = true,
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
size = function()
|
|
161
|
-
return UDim2.new(1, 0, 0, read(sizes).errorTextHeight)
|
|
134
|
+
position = function()
|
|
135
|
+
return UDim2.fromOffset(0, px(SUGGESTION_TITLE_TEXT_SIZE))
|
|
162
136
|
end,
|
|
163
|
-
|
|
137
|
+
size = descriptionSize,
|
|
138
|
+
}), Vide.jsx(Text, {
|
|
164
139
|
text = function()
|
|
165
140
|
local currentSuggestion = read(suggestion)
|
|
166
141
|
local _result
|
|
@@ -181,8 +156,22 @@ local function MainSuggestion(_param)
|
|
|
181
156
|
textSize = function()
|
|
182
157
|
return px(SUGGESTION_TEXT_SIZE)
|
|
183
158
|
end,
|
|
184
|
-
|
|
159
|
+
textTransparency = spring(function()
|
|
160
|
+
local currentSuggestion = read(suggestion)
|
|
161
|
+
local _result = currentSuggestion
|
|
162
|
+
if _result ~= nil then
|
|
163
|
+
_result = _result.type
|
|
164
|
+
end
|
|
165
|
+
local _condition = _result == "argument"
|
|
166
|
+
if _condition then
|
|
167
|
+
_condition = currentSuggestion.error ~= nil
|
|
168
|
+
end
|
|
169
|
+
return if _condition then 0 else 1
|
|
170
|
+
end, 0.2),
|
|
185
171
|
textXAlignment = "Left",
|
|
172
|
+
anchor = Vector2.new(0, 1),
|
|
173
|
+
position = UDim2.fromScale(0, 1),
|
|
174
|
+
size = errorSize,
|
|
186
175
|
}))
|
|
187
176
|
end
|
|
188
177
|
return {
|
|
@@ -36,12 +36,14 @@ local function SuggestionList(_param)
|
|
|
36
36
|
end)
|
|
37
37
|
return Vide.jsx(Group, {
|
|
38
38
|
size = size,
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
39
|
+
native = {
|
|
40
|
+
MouseEnter = function()
|
|
41
|
+
return mouseOverInterface(true)
|
|
42
|
+
end,
|
|
43
|
+
MouseLeave = function()
|
|
44
|
+
return mouseOverInterface(false)
|
|
45
|
+
end,
|
|
46
|
+
},
|
|
45
47
|
}, Vide.jsx("uilistlayout", {
|
|
46
48
|
SortOrder = "LayoutOrder",
|
|
47
49
|
Padding = function()
|
|
@@ -4,15 +4,14 @@ local TextService = TS.import(script, TS.getModule(script, "@rbxts", "services")
|
|
|
4
4
|
local _vide = TS.import(script, TS.getModule(script, "@rbxts", "vide").src)
|
|
5
5
|
local Vide = _vide
|
|
6
6
|
local cleanup = _vide.cleanup
|
|
7
|
-
local
|
|
8
|
-
local
|
|
9
|
-
local springs = TS.import(script, script.Parent.Parent.Parent, "constants", "springs").springs
|
|
7
|
+
local derive = _vide.derive
|
|
8
|
+
local spring = _vide.spring
|
|
10
9
|
local _text = TS.import(script, script.Parent.Parent.Parent, "constants", "text")
|
|
11
10
|
local SUGGESTION_TEXT_SIZE = _text.SUGGESTION_TEXT_SIZE
|
|
12
11
|
local SUGGESTION_TITLE_TEXT_SIZE = _text.SUGGESTION_TITLE_TEXT_SIZE
|
|
13
12
|
local useAtom = TS.import(script, script.Parent.Parent.Parent, "hooks", "use-atom").useAtom
|
|
14
|
-
local useMotion = TS.import(script, script.Parent.Parent.Parent, "hooks", "use-motion").useMotion
|
|
15
13
|
local px = TS.import(script, script.Parent.Parent.Parent, "hooks", "use-px").px
|
|
14
|
+
local useTextBounds = TS.import(script, script.Parent.Parent.Parent, "hooks", "use-text-bounds").useTextBounds
|
|
16
15
|
local _store = TS.import(script, script.Parent.Parent.Parent, "store")
|
|
17
16
|
local currentSuggestion = _store.currentSuggestion
|
|
18
17
|
local currentTextPart = _store.currentTextPart
|
|
@@ -20,69 +19,122 @@ local interfaceOptions = _store.interfaceOptions
|
|
|
20
19
|
local Group = TS.import(script, script.Parent.Parent, "ui", "group").Group
|
|
21
20
|
local MainSuggestion = TS.import(script, script.Parent, "main-suggestion").MainSuggestion
|
|
22
21
|
local SuggestionList = TS.import(script, script.Parent, "suggestion-list").SuggestionList
|
|
23
|
-
local getSuggestionTextBounds = TS.import(script, script.Parent, "util").getSuggestionTextBounds
|
|
24
22
|
local MAX_SUGGESTION_WIDTH = 180
|
|
25
23
|
local MAX_BADGE_WIDTH = 80
|
|
26
24
|
local PADDING = 8
|
|
27
25
|
local function Suggestions()
|
|
28
26
|
local options = useAtom(interfaceOptions)
|
|
29
27
|
local textPart = useAtom(currentTextPart)
|
|
30
|
-
local textBoundsParams = Instance.new("GetTextBoundsParams")
|
|
31
|
-
textBoundsParams.RichText = true
|
|
32
|
-
cleanup(function()
|
|
33
|
-
textBoundsParams:Destroy()
|
|
34
|
-
end)
|
|
35
|
-
-- Suggestions
|
|
36
28
|
local suggestion = useAtom(currentSuggestion)
|
|
37
|
-
local
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
29
|
+
local titleBounds = useTextBounds({
|
|
30
|
+
text = function()
|
|
31
|
+
local _result = suggestion()
|
|
32
|
+
if _result ~= nil then
|
|
33
|
+
_result = _result.title
|
|
34
|
+
end
|
|
35
|
+
return _result
|
|
36
|
+
end,
|
|
37
|
+
font = function()
|
|
38
|
+
return options().font.bold
|
|
39
|
+
end,
|
|
40
|
+
size = function()
|
|
41
|
+
return px(SUGGESTION_TITLE_TEXT_SIZE)
|
|
42
|
+
end,
|
|
42
43
|
})
|
|
43
|
-
local
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
44
|
+
local descriptionBounds = useTextBounds({
|
|
45
|
+
text = function()
|
|
46
|
+
local _result = suggestion()
|
|
47
|
+
if _result ~= nil then
|
|
48
|
+
_result = _result.description
|
|
49
|
+
end
|
|
50
|
+
return _result
|
|
51
|
+
end,
|
|
52
|
+
font = function()
|
|
53
|
+
return options().font.regular
|
|
54
|
+
end,
|
|
55
|
+
size = function()
|
|
56
|
+
return px(SUGGESTION_TEXT_SIZE)
|
|
57
|
+
end,
|
|
58
|
+
width = function()
|
|
59
|
+
return px(MAX_SUGGESTION_WIDTH)
|
|
60
|
+
end,
|
|
61
|
+
})
|
|
62
|
+
local typeBadgeBounds = useTextBounds({
|
|
63
|
+
text = function()
|
|
64
|
+
local currentSuggestion = suggestion()
|
|
65
|
+
local _result = currentSuggestion
|
|
66
|
+
if _result ~= nil then
|
|
67
|
+
_result = _result.type
|
|
68
|
+
end
|
|
69
|
+
if _result == "command" then
|
|
70
|
+
return nil
|
|
71
|
+
end
|
|
72
|
+
local _result_1 = currentSuggestion
|
|
73
|
+
if _result_1 ~= nil then
|
|
74
|
+
_result_1 = _result_1.dataType
|
|
75
|
+
end
|
|
76
|
+
return _result_1
|
|
77
|
+
end,
|
|
78
|
+
font = function()
|
|
79
|
+
return options().font.bold
|
|
80
|
+
end,
|
|
81
|
+
size = function()
|
|
82
|
+
return px(SUGGESTION_TEXT_SIZE)
|
|
83
|
+
end,
|
|
84
|
+
})
|
|
85
|
+
local errorBounds = useTextBounds({
|
|
86
|
+
text = function()
|
|
87
|
+
local current = suggestion()
|
|
88
|
+
local _result = current
|
|
89
|
+
if _result ~= nil then
|
|
90
|
+
_result = _result.type
|
|
91
|
+
end
|
|
92
|
+
if _result == "command" then
|
|
93
|
+
return nil
|
|
94
|
+
end
|
|
95
|
+
local _result_1 = current
|
|
96
|
+
if _result_1 ~= nil then
|
|
97
|
+
_result_1 = _result_1.error
|
|
98
|
+
end
|
|
99
|
+
return _result_1
|
|
100
|
+
end,
|
|
101
|
+
font = function()
|
|
102
|
+
return options().font.regular
|
|
103
|
+
end,
|
|
104
|
+
size = function()
|
|
105
|
+
return px(SUGGESTION_TEXT_SIZE)
|
|
106
|
+
end,
|
|
107
|
+
})
|
|
108
|
+
local listBoundsParams = Instance.new("GetTextBoundsParams")
|
|
109
|
+
listBoundsParams.RichText = true
|
|
110
|
+
cleanup(listBoundsParams)
|
|
111
|
+
local listBounds = derive(function()
|
|
112
|
+
local width = 0
|
|
113
|
+
local _result = suggestion()
|
|
114
|
+
if _result ~= nil then
|
|
115
|
+
_result = _result.others
|
|
56
116
|
end
|
|
57
|
-
local
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
local windowHeight = textBounds.title.Y.Offset + textBounds.description.Y.Offset + textBounds.errorTextHeight + px(PADDING * 2)
|
|
61
|
-
if textBounds.typeBadgeWidth > 0 then
|
|
62
|
-
windowWidth += textBounds.typeBadgeWidth + px(16)
|
|
117
|
+
local _condition = _result
|
|
118
|
+
if _condition == nil then
|
|
119
|
+
_condition = {}
|
|
63
120
|
end
|
|
64
|
-
|
|
65
|
-
|
|
121
|
+
local suggestions = _condition
|
|
122
|
+
for _, value in suggestions do
|
|
123
|
+
listBoundsParams.Text = value
|
|
124
|
+
local suggestionBounds = TextService:GetTextBoundsAsync(listBoundsParams)
|
|
125
|
+
width = math.max(width, suggestionBounds.X)
|
|
66
126
|
end
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
local suggestionBounds = TextService:GetTextBoundsAsync(textBoundsParams)
|
|
77
|
-
if suggestionBounds.X > maxSuggestionWidth then
|
|
78
|
-
maxSuggestionWidth = suggestionBounds.X
|
|
79
|
-
end
|
|
80
|
-
end
|
|
81
|
-
otherHeight = #otherSuggestions * px(SUGGESTION_TEXT_SIZE + 6) + (#otherSuggestions - 1) * px(4) + px(8)
|
|
82
|
-
windowWidth = math.max(windowWidth, maxSuggestionWidth)
|
|
83
|
-
otherSuggestionSizeMotion:spring(UDim2.fromOffset(windowWidth, otherHeight), springs.gentle)
|
|
127
|
+
local height = #suggestions * px(SUGGESTION_TEXT_SIZE + 6) + (#suggestions - 1) * px(4) + px(8)
|
|
128
|
+
return Vector2.new(width, height)
|
|
129
|
+
end)
|
|
130
|
+
local windowSize = derive(function()
|
|
131
|
+
local width = math.max(titleBounds().X, descriptionBounds().X, errorBounds().X, listBounds().X) + typeBadgeBounds().X
|
|
132
|
+
local height = titleBounds().Y + descriptionBounds().Y + errorBounds().Y
|
|
133
|
+
local padding = px(PADDING * 2)
|
|
134
|
+
if width == 0 or height == 0 then
|
|
135
|
+
return UDim2.fromOffset(0, px(SUGGESTION_TITLE_TEXT_SIZE) + padding)
|
|
84
136
|
end
|
|
85
|
-
|
|
137
|
+
return UDim2.fromOffset(width + padding, height + padding)
|
|
86
138
|
end)
|
|
87
139
|
return Vide.jsx(Group, {
|
|
88
140
|
size = UDim2.fromScale(1, 1),
|
|
@@ -90,14 +142,30 @@ local function Suggestions()
|
|
|
90
142
|
}, Vide.jsx(MainSuggestion, {
|
|
91
143
|
suggestion = suggestion,
|
|
92
144
|
currentText = textPart,
|
|
93
|
-
size =
|
|
94
|
-
|
|
145
|
+
size = spring(windowSize, 0.2),
|
|
146
|
+
titleSize = function()
|
|
147
|
+
local bounds = titleBounds()
|
|
148
|
+
return UDim2.fromOffset(bounds.X, bounds.Y)
|
|
149
|
+
end,
|
|
150
|
+
descriptionSize = function()
|
|
151
|
+
local bounds = descriptionBounds()
|
|
152
|
+
return UDim2.fromOffset(bounds.X, bounds.Y)
|
|
153
|
+
end,
|
|
154
|
+
badgeSize = function()
|
|
155
|
+
local bounds = typeBadgeBounds()
|
|
156
|
+
return UDim2.fromOffset(bounds.X, bounds.Y)
|
|
157
|
+
end,
|
|
158
|
+
errorSize = function()
|
|
159
|
+
local bounds = errorBounds()
|
|
160
|
+
return UDim2.fromOffset(bounds.X, bounds.Y)
|
|
161
|
+
end,
|
|
95
162
|
}), Vide.jsx(SuggestionList, {
|
|
96
163
|
suggestion = suggestion,
|
|
97
164
|
currentText = textPart,
|
|
98
|
-
size =
|
|
165
|
+
size = spring(function()
|
|
166
|
+
return UDim2.fromOffset(windowSize().X.Offset, listBounds().Y)
|
|
167
|
+
end, 0.3),
|
|
99
168
|
}), Vide.jsx("uilistlayout", {
|
|
100
|
-
SortOrder = "LayoutOrder",
|
|
101
169
|
Padding = function()
|
|
102
170
|
return UDim.new(0, px(PADDING))
|
|
103
171
|
end,
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import Vide, { Derivable } from "@rbxts/vide";
|
|
2
2
|
interface TerminalTextFieldProps {
|
|
3
|
-
|
|
3
|
+
anchor?: Derivable<Vector2>;
|
|
4
4
|
size?: Derivable<UDim2>;
|
|
5
5
|
position?: Derivable<UDim2>;
|
|
6
6
|
backgroundTransparency?: Derivable<number>;
|
|
7
7
|
onTextChange?: (text: string) => void;
|
|
8
8
|
onSubmit?: (text: string) => void;
|
|
9
9
|
}
|
|
10
|
-
export declare function TerminalTextField({
|
|
10
|
+
export declare function TerminalTextField({ anchor, size, position, backgroundTransparency, onTextChange, onSubmit, }: TerminalTextFieldProps): Vide.Node;
|
|
11
11
|
export {};
|
|
@@ -31,7 +31,7 @@ local formatPartsAsPath = _command.formatPartsAsPath
|
|
|
31
31
|
local getArgumentNames = _command.getArgumentNames
|
|
32
32
|
local TEXT_SIZE = 22
|
|
33
33
|
local function TerminalTextField(_param)
|
|
34
|
-
local
|
|
34
|
+
local anchor = _param.anchor
|
|
35
35
|
local size = _param.size
|
|
36
36
|
local position = _param.position
|
|
37
37
|
local backgroundTransparency = _param.backgroundTransparency
|
|
@@ -41,7 +41,7 @@ local function TerminalTextField(_param)
|
|
|
41
41
|
local options = useAtom(interfaceOptions)
|
|
42
42
|
local visible = useAtom(interfaceVisible)
|
|
43
43
|
local valid = useAtom(terminalTextValid)
|
|
44
|
-
local ref = source(
|
|
44
|
+
local ref = source()
|
|
45
45
|
local commandHistory = source({})
|
|
46
46
|
local commandHistoryIndex = source(nil)
|
|
47
47
|
local text = source("")
|
|
@@ -266,7 +266,7 @@ local function TerminalTextField(_param)
|
|
|
266
266
|
textBox.CursorPosition = #newText + 1
|
|
267
267
|
end)
|
|
268
268
|
return Vide.jsx(Frame, {
|
|
269
|
-
|
|
269
|
+
anchor = anchor,
|
|
270
270
|
size = size,
|
|
271
271
|
position = position,
|
|
272
272
|
backgroundColor = function()
|
|
@@ -281,9 +281,7 @@ local function TerminalTextField(_param)
|
|
|
281
281
|
return UDim.new(0, px(8))
|
|
282
282
|
end,
|
|
283
283
|
}), Vide.jsx(TextField, {
|
|
284
|
-
action =
|
|
285
|
-
return ref(instance)
|
|
286
|
-
end,
|
|
284
|
+
action = ref,
|
|
287
285
|
size = UDim2.fromScale(1, 1),
|
|
288
286
|
text = function()
|
|
289
287
|
local value = text()
|
|
@@ -316,40 +314,42 @@ local function TerminalTextField(_param)
|
|
|
316
314
|
return options().font.medium
|
|
317
315
|
end,
|
|
318
316
|
clearTextOnFocus = false,
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
local _result = onSubmit
|
|
340
|
-
if _result ~= nil then
|
|
341
|
-
_result(currentText)
|
|
342
|
-
end
|
|
343
|
-
textBox:CaptureFocus()
|
|
344
|
-
text("")
|
|
345
|
-
end,
|
|
346
|
-
textChanged = function(currentText)
|
|
347
|
-
local historyIndex = commandHistoryIndex()
|
|
348
|
-
if historyIndex ~= nil and currentText ~= commandHistory()[historyIndex + 1] then
|
|
317
|
+
native = {
|
|
318
|
+
FocusLost = function(enterPressed)
|
|
319
|
+
if not enterPressed then
|
|
320
|
+
return nil
|
|
321
|
+
end
|
|
322
|
+
local textBox = ref()
|
|
323
|
+
if textBox == nil then
|
|
324
|
+
return nil
|
|
325
|
+
end
|
|
326
|
+
local currentText = textBox.Text
|
|
327
|
+
local history = commandHistory()
|
|
328
|
+
if currentText ~= "" and (#history == 0 or history[#history] ~= currentText) then
|
|
329
|
+
local _array = {}
|
|
330
|
+
local _length = #_array
|
|
331
|
+
local _historyLength = #history
|
|
332
|
+
table.move(history, 1, _historyLength, _length + 1, _array)
|
|
333
|
+
_length += _historyLength
|
|
334
|
+
_array[_length + 1] = textBox.Text
|
|
335
|
+
commandHistory(_array)
|
|
336
|
+
end
|
|
349
337
|
commandHistoryIndex(nil)
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
338
|
+
local _result = onSubmit
|
|
339
|
+
if _result ~= nil then
|
|
340
|
+
_result(currentText)
|
|
341
|
+
end
|
|
342
|
+
textBox:CaptureFocus()
|
|
343
|
+
text("")
|
|
344
|
+
end,
|
|
345
|
+
TextChanged = function(currentText)
|
|
346
|
+
local historyIndex = commandHistoryIndex()
|
|
347
|
+
if historyIndex ~= nil and currentText ~= commandHistory()[historyIndex + 1] then
|
|
348
|
+
commandHistoryIndex(nil)
|
|
349
|
+
end
|
|
350
|
+
text(currentText)
|
|
351
|
+
end,
|
|
352
|
+
},
|
|
353
353
|
zIndex = 2,
|
|
354
354
|
}), Vide.jsx(Text, {
|
|
355
355
|
size = UDim2.fromScale(1, 1),
|
|
@@ -5,13 +5,13 @@ local ArrayUtil = TS.import(script, TS.getModule(script, "@rbxts", "centurion").
|
|
|
5
5
|
local splitString = TS.import(script, TS.getModule(script, "@rbxts", "centurion").out.shared.util.string).splitString
|
|
6
6
|
local _vide = TS.import(script, TS.getModule(script, "@rbxts", "vide").src)
|
|
7
7
|
local Vide = _vide
|
|
8
|
-
local
|
|
8
|
+
local derive = _vide.derive
|
|
9
9
|
local source = _vide.source
|
|
10
|
+
local spring = _vide.spring
|
|
10
11
|
local HISTORY_TEXT_SIZE = TS.import(script, script.Parent.Parent.Parent, "constants", "text").HISTORY_TEXT_SIZE
|
|
11
12
|
local useAtom = TS.import(script, script.Parent.Parent.Parent, "hooks", "use-atom").useAtom
|
|
12
13
|
local useClient = TS.import(script, script.Parent.Parent.Parent, "hooks", "use-client").useClient
|
|
13
14
|
local useHistory = TS.import(script, script.Parent.Parent.Parent, "hooks", "use-history").useHistory
|
|
14
|
-
local useMotion = TS.import(script, script.Parent.Parent.Parent, "hooks", "use-motion").useMotion
|
|
15
15
|
local px = TS.import(script, script.Parent.Parent.Parent, "hooks", "use-px").px
|
|
16
16
|
local _store = TS.import(script, script.Parent.Parent.Parent, "store")
|
|
17
17
|
local commandArgIndex = _store.commandArgIndex
|
|
@@ -41,21 +41,20 @@ local function Terminal()
|
|
|
41
41
|
local options = useAtom(interfaceOptions)
|
|
42
42
|
local missingArgs = source({})
|
|
43
43
|
local history = useHistory()
|
|
44
|
-
local
|
|
45
|
-
|
|
44
|
+
local terminalHeight = derive(function()
|
|
45
|
+
local padding = px.ceil(TEXT_FIELD_HEIGHT + 16)
|
|
46
|
+
if #history().lines == 0 then
|
|
47
|
+
return padding
|
|
48
|
+
end
|
|
46
49
|
local totalHeight = history().height
|
|
47
50
|
local isClamped = totalHeight > px(MAX_HEIGHT)
|
|
48
51
|
local clampedHeight = if isClamped then px(MAX_HEIGHT) else totalHeight
|
|
49
|
-
|
|
50
|
-
mass = 0.1,
|
|
51
|
-
tension = 300,
|
|
52
|
-
friction = 15,
|
|
53
|
-
})
|
|
52
|
+
return math.ceil(padding + clampedHeight)
|
|
54
53
|
end)
|
|
55
54
|
return Vide.jsx(Frame, {
|
|
56
|
-
size = function()
|
|
57
|
-
return UDim2.new(1, 0, 0,
|
|
58
|
-
end,
|
|
55
|
+
size = spring(function()
|
|
56
|
+
return UDim2.new(1, 0, 0, terminalHeight())
|
|
57
|
+
end, 0.2),
|
|
59
58
|
backgroundColor = function()
|
|
60
59
|
return options().palette.background
|
|
61
60
|
end,
|
|
@@ -69,12 +68,14 @@ local function Terminal()
|
|
|
69
68
|
cornerRadius = function()
|
|
70
69
|
return UDim.new(0, px(8))
|
|
71
70
|
end,
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
71
|
+
native = {
|
|
72
|
+
MouseEnter = function()
|
|
73
|
+
return mouseOverInterface(true)
|
|
74
|
+
end,
|
|
75
|
+
MouseLeave = function()
|
|
76
|
+
return mouseOverInterface(false)
|
|
77
|
+
end,
|
|
78
|
+
},
|
|
78
79
|
}, Vide.jsx(Padding, {
|
|
79
80
|
all = function()
|
|
80
81
|
return UDim.new(0, px(8))
|
|
@@ -88,7 +89,7 @@ local function Terminal()
|
|
|
88
89
|
return px(MAX_HEIGHT)
|
|
89
90
|
end,
|
|
90
91
|
}), Vide.jsx(TerminalTextField, {
|
|
91
|
-
|
|
92
|
+
anchor = Vector2.new(0, 1),
|
|
92
93
|
size = function()
|
|
93
94
|
return UDim2.new(1, 0, 0, px(TEXT_FIELD_HEIGHT))
|
|
94
95
|
end,
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import Vide, { ActionAttributes, Derivable, InferEnumNames } from "@rbxts/vide";
|
|
1
|
+
import Vide, { ActionAttributes, Derivable, InferEnumNames, InstanceAttributes } from "@rbxts/vide";
|
|
2
2
|
export interface FrameProps<T extends Instance = Frame> extends ActionAttributes<T> {
|
|
3
3
|
size?: Derivable<UDim2>;
|
|
4
4
|
position?: Derivable<UDim2>;
|
|
5
|
-
|
|
5
|
+
anchor?: Derivable<Vector2>;
|
|
6
6
|
rotation?: Derivable<number>;
|
|
7
7
|
backgroundColor?: Derivable<Color3>;
|
|
8
8
|
backgroundTransparency?: Derivable<number>;
|
|
@@ -12,8 +12,6 @@ export interface FrameProps<T extends Instance = Frame> extends ActionAttributes
|
|
|
12
12
|
layoutOrder?: Derivable<number>;
|
|
13
13
|
cornerRadius?: Derivable<UDim>;
|
|
14
14
|
automaticSize?: InferEnumNames<Enum.AutomaticSize>;
|
|
15
|
-
|
|
16
|
-
mouseEnter?: () => void;
|
|
17
|
-
mouseLeave?: () => void;
|
|
15
|
+
native?: InstanceAttributes<T>;
|
|
18
16
|
}
|
|
19
17
|
export declare function Frame(props: FrameProps): Vide.Node;
|
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
local TS = _G[script]
|
|
3
3
|
local Vide = TS.import(script, TS.getModule(script, "@rbxts", "vide").src)
|
|
4
4
|
local function Frame(props)
|
|
5
|
-
|
|
5
|
+
local _attributes = {
|
|
6
6
|
AutomaticSize = props.automaticSize,
|
|
7
7
|
Size = props.size,
|
|
8
8
|
Position = props.position,
|
|
9
|
-
AnchorPoint = props.
|
|
9
|
+
AnchorPoint = props.anchor,
|
|
10
10
|
Rotation = props.rotation,
|
|
11
11
|
BackgroundColor3 = props.backgroundColor,
|
|
12
12
|
BackgroundTransparency = props.backgroundTransparency,
|
|
@@ -14,11 +14,16 @@ local function Frame(props)
|
|
|
14
14
|
Visible = props.visible,
|
|
15
15
|
ZIndex = props.zIndex,
|
|
16
16
|
LayoutOrder = props.layoutOrder,
|
|
17
|
-
BorderSizePixel = 0,
|
|
18
|
-
MouseEnter = props.mouseEnter,
|
|
19
|
-
MouseLeave = props.mouseLeave,
|
|
20
17
|
action = props.action,
|
|
21
|
-
|
|
18
|
+
BorderSizePixel = 0,
|
|
19
|
+
}
|
|
20
|
+
local _attribute = props.native
|
|
21
|
+
if _attribute then
|
|
22
|
+
for _k, _v in _attribute do
|
|
23
|
+
_attributes[_k] = _v
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
return Vide.jsx("frame", _attributes, props.cornerRadius and Vide.jsx("uicorner", {
|
|
22
27
|
CornerRadius = props.cornerRadius,
|
|
23
28
|
}), props.children)
|
|
24
29
|
end
|
|
@@ -1,16 +1,15 @@
|
|
|
1
1
|
import Vide, { Derivable } from "@rbxts/vide";
|
|
2
|
-
|
|
2
|
+
import { FrameProps } from "./frame";
|
|
3
|
+
interface GroupProps extends Omit<FrameProps, "backgroundTransparency" | "backgroundColor"> {
|
|
3
4
|
name?: Derivable<string>;
|
|
4
|
-
|
|
5
|
+
anchor?: Derivable<Vector2>;
|
|
5
6
|
position?: Derivable<UDim2>;
|
|
6
|
-
|
|
7
|
+
size?: Derivable<UDim2>;
|
|
7
8
|
rotation?: Derivable<number>;
|
|
8
9
|
clipsDescendants?: Derivable<boolean>;
|
|
9
10
|
layoutOrder?: Derivable<number>;
|
|
10
11
|
visible?: Derivable<boolean>;
|
|
11
12
|
zIndex?: Derivable<number>;
|
|
12
|
-
mouseEnter?: () => void;
|
|
13
|
-
mouseLeave?: () => void;
|
|
14
13
|
}
|
|
15
14
|
export declare function Group(props: GroupProps): Vide.Node;
|
|
16
15
|
export {};
|
|
@@ -2,20 +2,27 @@
|
|
|
2
2
|
local TS = _G[script]
|
|
3
3
|
local Vide = TS.import(script, TS.getModule(script, "@rbxts", "vide").src)
|
|
4
4
|
local function Group(props)
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
local _attributes = {
|
|
6
|
+
AutomaticSize = props.automaticSize,
|
|
7
|
+
AnchorPoint = props.anchor,
|
|
8
8
|
Position = props.position,
|
|
9
|
-
|
|
9
|
+
Size = props.size or UDim2.fromScale(1, 1),
|
|
10
10
|
Rotation = props.rotation,
|
|
11
|
+
BackgroundTransparency = 1,
|
|
11
12
|
ClipsDescendants = props.clipsDescendants,
|
|
12
|
-
LayoutOrder = props.layoutOrder,
|
|
13
13
|
Visible = props.visible,
|
|
14
14
|
ZIndex = props.zIndex,
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
}
|
|
15
|
+
LayoutOrder = props.layoutOrder,
|
|
16
|
+
action = props.action,
|
|
17
|
+
BorderSizePixel = 0,
|
|
18
|
+
}
|
|
19
|
+
local _attribute = props.native
|
|
20
|
+
if _attribute then
|
|
21
|
+
for _k, _v in _attribute do
|
|
22
|
+
_attributes[_k] = _v
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
return Vide.jsx("frame", _attributes, props.children)
|
|
19
26
|
end
|
|
20
27
|
return {
|
|
21
28
|
Group = Group,
|
|
@@ -14,7 +14,7 @@ local function ScrollingFrame(props)
|
|
|
14
14
|
CanvasPosition = props.canvasPosition,
|
|
15
15
|
Size = props.size,
|
|
16
16
|
Position = props.position,
|
|
17
|
-
AnchorPoint = props.
|
|
17
|
+
AnchorPoint = props.anchor,
|
|
18
18
|
Rotation = props.rotation,
|
|
19
19
|
BackgroundColor3 = props.backgroundColor,
|
|
20
20
|
}
|
|
@@ -28,6 +28,12 @@ local function ScrollingFrame(props)
|
|
|
28
28
|
_attributes.ZIndex = props.zIndex
|
|
29
29
|
_attributes.LayoutOrder = props.layoutOrder
|
|
30
30
|
_attributes.BorderSizePixel = 0
|
|
31
|
+
local _attribute = props.native
|
|
32
|
+
if _attribute then
|
|
33
|
+
for _k, _v in _attribute do
|
|
34
|
+
_attributes[_k] = _v
|
|
35
|
+
end
|
|
36
|
+
end
|
|
31
37
|
return Vide.jsx("scrollingframe", _attributes, props.cornerRadius and Vide.jsx("uicorner", {
|
|
32
38
|
CornerRadius = props.cornerRadius,
|
|
33
39
|
}), props.children)
|
|
@@ -7,8 +7,6 @@ interface TextFieldProps extends TextProps<TextBox> {
|
|
|
7
7
|
clearTextOnFocus?: Derivable<boolean>;
|
|
8
8
|
multiLine?: Derivable<boolean>;
|
|
9
9
|
textEditable?: Derivable<boolean>;
|
|
10
|
-
focusLost?: (enterPressed: boolean) => void;
|
|
11
|
-
textChanged?: (text: string) => void;
|
|
12
10
|
}
|
|
13
11
|
export declare function TextField(props: TextFieldProps): Vide.Node;
|
|
14
12
|
export {};
|
|
@@ -28,9 +28,12 @@ local function TextField(props)
|
|
|
28
28
|
TextScaled = props.textScaled,
|
|
29
29
|
RichText = props.richText,
|
|
30
30
|
AutomaticSize = props.textAutoResize,
|
|
31
|
+
AutoLocalize = function()
|
|
32
|
+
return options().autoLocalize
|
|
33
|
+
end,
|
|
31
34
|
Size = props.size,
|
|
32
35
|
Position = props.position,
|
|
33
|
-
AnchorPoint = props.
|
|
36
|
+
AnchorPoint = props.anchor,
|
|
34
37
|
BackgroundColor3 = props.backgroundColor,
|
|
35
38
|
}
|
|
36
39
|
local _condition = props.backgroundTransparency
|
|
@@ -43,9 +46,13 @@ local function TextField(props)
|
|
|
43
46
|
_attributes.ZIndex = props.zIndex
|
|
44
47
|
_attributes.LayoutOrder = props.layoutOrder
|
|
45
48
|
_attributes.BorderSizePixel = 0
|
|
46
|
-
_attributes.FocusLost = props.focusLost
|
|
47
|
-
_attributes.TextChanged = props.textChanged
|
|
48
49
|
_attributes.action = props.action
|
|
50
|
+
local _attribute = props.native
|
|
51
|
+
if _attribute then
|
|
52
|
+
for _k, _v in _attribute do
|
|
53
|
+
_attributes[_k] = _v
|
|
54
|
+
end
|
|
55
|
+
end
|
|
49
56
|
return Vide.jsx("textbox", _attributes, props.cornerRadius and Vide.jsx("uicorner", {
|
|
50
57
|
CornerRadius = props.cornerRadius,
|
|
51
58
|
}), props.children)
|
|
@@ -14,7 +14,5 @@ export interface TextProps<T extends Instance = TextLabel> extends FrameProps<T>
|
|
|
14
14
|
textHeight?: Derivable<number>;
|
|
15
15
|
textAutoResize?: "X" | "Y" | "XY";
|
|
16
16
|
richText?: Derivable<boolean>;
|
|
17
|
-
maxVisibleGraphemes?: Derivable<number>;
|
|
18
|
-
textBoundsChanged?: (textBounds: Vector2) => void;
|
|
19
17
|
}
|
|
20
18
|
export declare function Text(props: TextProps): Vide.Node;
|
|
@@ -29,11 +29,13 @@ local function Text(props)
|
|
|
29
29
|
TextScaled = props.textScaled,
|
|
30
30
|
LineHeight = props.textHeight,
|
|
31
31
|
RichText = props.richText,
|
|
32
|
-
MaxVisibleGraphemes = props.maxVisibleGraphemes,
|
|
33
32
|
Size = props.size,
|
|
34
33
|
AutomaticSize = props.textAutoResize,
|
|
34
|
+
AutoLocalize = function()
|
|
35
|
+
return options().autoLocalize
|
|
36
|
+
end,
|
|
35
37
|
Position = props.position,
|
|
36
|
-
AnchorPoint = props.
|
|
38
|
+
AnchorPoint = props.anchor,
|
|
37
39
|
BackgroundColor3 = props.backgroundColor,
|
|
38
40
|
}
|
|
39
41
|
local _condition = props.backgroundTransparency
|
|
@@ -46,7 +48,12 @@ local function Text(props)
|
|
|
46
48
|
_attributes.ZIndex = props.zIndex
|
|
47
49
|
_attributes.LayoutOrder = props.layoutOrder
|
|
48
50
|
_attributes.action = props.action
|
|
49
|
-
|
|
51
|
+
local _attribute = props.native
|
|
52
|
+
if _attribute then
|
|
53
|
+
for _k, _v in _attribute do
|
|
54
|
+
_attributes[_k] = _v
|
|
55
|
+
end
|
|
56
|
+
end
|
|
50
57
|
return Vide.jsx("textlabel", _attributes, props.cornerRadius and Vide.jsx("uicorner", {
|
|
51
58
|
CornerRadius = props.cornerRadius,
|
|
52
59
|
}), props.children)
|
|
@@ -3,7 +3,7 @@ local TS = _G[script]
|
|
|
3
3
|
local GuiService = TS.import(script, TS.getModule(script, "@rbxts", "services")).GuiService
|
|
4
4
|
local DefaultPalette = TS.import(script, script.Parent.Parent, "palette").DefaultPalette
|
|
5
5
|
local DEFAULT_INTERFACE_OPTIONS = {
|
|
6
|
-
|
|
6
|
+
anchor = Vector2.new(),
|
|
7
7
|
position = function(px)
|
|
8
8
|
return UDim2.fromOffset(px(16), px(8) + (GuiService:GetGuiInset()).Y)
|
|
9
9
|
end,
|
|
@@ -20,6 +20,7 @@ local DEFAULT_INTERFACE_OPTIONS = {
|
|
|
20
20
|
bold = Font.new("rbxassetid://16658221428", Enum.FontWeight.Bold),
|
|
21
21
|
},
|
|
22
22
|
palette = DefaultPalette.mocha,
|
|
23
|
+
autoLocalize = false,
|
|
23
24
|
}
|
|
24
25
|
return {
|
|
25
26
|
DEFAULT_INTERFACE_OPTIONS = DEFAULT_INTERFACE_OPTIONS,
|
package/out/hooks/use-px.d.ts
CHANGED
|
@@ -1,25 +1,3 @@
|
|
|
1
|
-
export interface ScaleFunction {
|
|
2
|
-
/**
|
|
3
|
-
* Scales `pixels` based on the current viewport size and rounds the result.
|
|
4
|
-
*/
|
|
5
|
-
(pixels: number): number;
|
|
6
|
-
/**
|
|
7
|
-
* Scales `pixels` and rounds the result to the nearest even number.
|
|
8
|
-
*/
|
|
9
|
-
even: (pixels: number) => number;
|
|
10
|
-
/**
|
|
11
|
-
* Scales a number based on the current viewport size without rounding.
|
|
12
|
-
*/
|
|
13
|
-
scale: (percent: number) => number;
|
|
14
|
-
/**
|
|
15
|
-
* Scales `pixels` and rounds the result down.
|
|
16
|
-
*/
|
|
17
|
-
floor: (pixels: number) => number;
|
|
18
|
-
/**
|
|
19
|
-
* Scales `pixels` and rounds the result up.
|
|
20
|
-
*/
|
|
21
|
-
ceil: (pixels: number) => number;
|
|
22
|
-
}
|
|
23
1
|
/**
|
|
24
2
|
* Rounds and scales a number to the current `px` unit. Includes additional
|
|
25
3
|
* methods for edge cases.
|
|
@@ -27,9 +5,15 @@ export interface ScaleFunction {
|
|
|
27
5
|
* @param value The number to scale.
|
|
28
6
|
* @returns A number in scaled `px` units.
|
|
29
7
|
*/
|
|
30
|
-
export declare const px:
|
|
8
|
+
export declare const px: ((value: number) => number) & {
|
|
9
|
+
even: (value: number) => number;
|
|
10
|
+
scale: (value: number) => number;
|
|
11
|
+
floor: (value: number) => number;
|
|
12
|
+
ceil: (value: number) => number;
|
|
13
|
+
};
|
|
14
|
+
export type ScaleFunction = typeof px;
|
|
31
15
|
/**
|
|
32
16
|
* Scales the current `px` unit based on the current viewport size. Should be
|
|
33
|
-
* called once
|
|
17
|
+
* called once when mounting the app.
|
|
34
18
|
*/
|
|
35
19
|
export declare function usePx(): void;
|
package/out/hooks/use-px.lua
CHANGED
|
@@ -1,15 +1,30 @@
|
|
|
1
1
|
-- Compiled with roblox-ts v2.3.0-dev-26ec859
|
|
2
2
|
local TS = _G[script]
|
|
3
3
|
local Workspace = TS.import(script, TS.getModule(script, "@rbxts", "services")).Workspace
|
|
4
|
-
local debounce = TS.import(script, TS.getModule(script, "@rbxts", "set-timeout").out).debounce
|
|
5
4
|
local _vide = TS.import(script, TS.getModule(script, "@rbxts", "vide").src)
|
|
6
5
|
local cleanup = _vide.cleanup
|
|
7
6
|
local source = _vide.source
|
|
8
|
-
local useEvent = TS.import(script, script.Parent, "use-event").useEvent
|
|
9
7
|
local BASE_RESOLUTION = Vector2.new(1280, 832)
|
|
10
|
-
local MIN_SCALE = 0.
|
|
8
|
+
local MIN_SCALE = 0.5
|
|
11
9
|
local DOMINANT_AXIS = 0.5
|
|
12
10
|
local scale = source(1)
|
|
11
|
+
--[[
|
|
12
|
+
*
|
|
13
|
+
* Assigns a call signature to an object.
|
|
14
|
+
*
|
|
15
|
+
* @param callback The function to assign.
|
|
16
|
+
* @param object The object to assign the function to.
|
|
17
|
+
* @returns A callable object.
|
|
18
|
+
|
|
19
|
+
]]
|
|
20
|
+
local function callable(callback, object)
|
|
21
|
+
return setmetatable(object, {
|
|
22
|
+
__call = function(_, ...)
|
|
23
|
+
local args = { ... }
|
|
24
|
+
return callback(unpack(args))
|
|
25
|
+
end,
|
|
26
|
+
})
|
|
27
|
+
end
|
|
13
28
|
--[[
|
|
14
29
|
*
|
|
15
30
|
* Rounds and scales a number to the current `px` unit. Includes additional
|
|
@@ -19,7 +34,9 @@ local scale = source(1)
|
|
|
19
34
|
* @returns A number in scaled `px` units.
|
|
20
35
|
|
|
21
36
|
]]
|
|
22
|
-
local px =
|
|
37
|
+
local px = callable(function(value)
|
|
38
|
+
return math.round(value * scale())
|
|
39
|
+
end, {
|
|
23
40
|
even = function(value)
|
|
24
41
|
return math.round(value * scale() * 0.5) * 2
|
|
25
42
|
end,
|
|
@@ -32,36 +49,27 @@ local px = setmetatable({
|
|
|
32
49
|
ceil = function(value)
|
|
33
50
|
return math.ceil(value * scale())
|
|
34
51
|
end,
|
|
35
|
-
}, {
|
|
36
|
-
__call = function(_, value)
|
|
37
|
-
return math.round(value * scale())
|
|
38
|
-
end,
|
|
39
52
|
})
|
|
40
53
|
--[[
|
|
41
54
|
*
|
|
42
55
|
* Scales the current `px` unit based on the current viewport size. Should be
|
|
43
|
-
* called once
|
|
56
|
+
* called once when mounting the app.
|
|
44
57
|
|
|
45
58
|
]]
|
|
46
59
|
local function usePx()
|
|
47
60
|
local camera = Workspace.CurrentCamera
|
|
48
61
|
local _arg0 = camera ~= nil
|
|
49
62
|
assert(_arg0, "CurrentCamera is not set")
|
|
50
|
-
local updateScale =
|
|
51
|
-
local
|
|
52
|
-
local
|
|
53
|
-
local height = math.log(viewport.Y / BASE_RESOLUTION.Y, 2)
|
|
63
|
+
local updateScale = function()
|
|
64
|
+
local width = math.log(camera.ViewportSize.X / BASE_RESOLUTION.X, 2)
|
|
65
|
+
local height = math.log(camera.ViewportSize.Y / BASE_RESOLUTION.Y, 2)
|
|
54
66
|
local centered = width + (height - width) * DOMINANT_AXIS
|
|
55
67
|
scale(math.max(2 ^ centered, MIN_SCALE))
|
|
56
|
-
end
|
|
57
|
-
|
|
58
|
-
})
|
|
59
|
-
cleanup(function()
|
|
60
|
-
updateScale.cancel()
|
|
61
|
-
end)
|
|
62
|
-
useEvent(camera:GetPropertyChangedSignal("ViewportSize"), function()
|
|
68
|
+
end
|
|
69
|
+
local connection = camera:GetPropertyChangedSignal("ViewportSize"):Connect(function()
|
|
63
70
|
updateScale()
|
|
64
71
|
end)
|
|
72
|
+
cleanup(connection)
|
|
65
73
|
updateScale()
|
|
66
74
|
end
|
|
67
75
|
return {
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { Derivable } from "@rbxts/vide";
|
|
2
|
+
interface TextBoundsProps {
|
|
3
|
+
text: Derivable<string | undefined>;
|
|
4
|
+
font?: Derivable<Font>;
|
|
5
|
+
size?: Derivable<number>;
|
|
6
|
+
width?: Derivable<number>;
|
|
7
|
+
}
|
|
8
|
+
export declare function useTextBounds({ text, font, size, width }: TextBoundsProps): () => Vector2;
|
|
9
|
+
export {};
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
-- Compiled with roblox-ts v2.3.0-dev-26ec859
|
|
2
|
+
local TS = _G[script]
|
|
3
|
+
local TextService = TS.import(script, TS.getModule(script, "@rbxts", "services")).TextService
|
|
4
|
+
local _vide = TS.import(script, TS.getModule(script, "@rbxts", "vide").src)
|
|
5
|
+
local cleanup = _vide.cleanup
|
|
6
|
+
local derive = _vide.derive
|
|
7
|
+
local read = _vide.read
|
|
8
|
+
local function useTextBounds(_param)
|
|
9
|
+
local text = _param.text
|
|
10
|
+
local font = _param.font
|
|
11
|
+
local size = _param.size
|
|
12
|
+
local width = _param.width
|
|
13
|
+
local params = Instance.new("GetTextBoundsParams")
|
|
14
|
+
params.RichText = true
|
|
15
|
+
cleanup(params)
|
|
16
|
+
return derive(function()
|
|
17
|
+
local textValue = read(text)
|
|
18
|
+
if textValue == nil then
|
|
19
|
+
return Vector2.zero
|
|
20
|
+
end
|
|
21
|
+
params.Text = textValue
|
|
22
|
+
local fontValue = read(font)
|
|
23
|
+
local sizeValue = read(size)
|
|
24
|
+
local widthValue = read(width)
|
|
25
|
+
if fontValue ~= nil then
|
|
26
|
+
params.Font = fontValue
|
|
27
|
+
end
|
|
28
|
+
if sizeValue ~= nil then
|
|
29
|
+
params.Size = sizeValue
|
|
30
|
+
end
|
|
31
|
+
if widthValue ~= nil then
|
|
32
|
+
params.Width = widthValue
|
|
33
|
+
end
|
|
34
|
+
return TextService:GetTextBoundsAsync(params)
|
|
35
|
+
end)
|
|
36
|
+
end
|
|
37
|
+
return {
|
|
38
|
+
useTextBounds = useTextBounds,
|
|
39
|
+
}
|
package/out/types.d.ts
CHANGED
|
@@ -2,9 +2,9 @@ import { CommandShortcut, HistoryEntry } from "@rbxts/centurion";
|
|
|
2
2
|
import { ScaleFunction } from "./hooks/use-px";
|
|
3
3
|
import { InterfacePalette } from "./palette";
|
|
4
4
|
export interface InterfaceOptions {
|
|
5
|
-
|
|
6
|
-
size: UDim2 | ((px: ScaleFunction) => UDim2);
|
|
5
|
+
anchor: Vector2;
|
|
7
6
|
position: UDim2 | ((px: ScaleFunction) => UDim2);
|
|
7
|
+
size: UDim2 | ((px: ScaleFunction) => UDim2);
|
|
8
8
|
displayOrder: number;
|
|
9
9
|
backgroundTransparency: number;
|
|
10
10
|
hideOnLostFocus: boolean;
|
|
@@ -15,6 +15,7 @@ export interface InterfaceOptions {
|
|
|
15
15
|
bold: Font;
|
|
16
16
|
};
|
|
17
17
|
palette: InterfacePalette;
|
|
18
|
+
autoLocalize: boolean;
|
|
18
19
|
}
|
|
19
20
|
export interface HistoryLineData {
|
|
20
21
|
entry: HistoryEntry;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rbxts/centurion-ui",
|
|
3
3
|
"description": "Terminal UI for the Centurion command framework",
|
|
4
|
-
"version": "1.0.0-dev-
|
|
4
|
+
"version": "1.0.0-dev-d64d6ec",
|
|
5
5
|
"author": "paradoxuum",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"main": "out/init.lua",
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
"dev": "shx rm -rf out && rbxtsc -w"
|
|
33
33
|
},
|
|
34
34
|
"devDependencies": {
|
|
35
|
-
"@rbxts/centurion": "^1.0.0-dev-
|
|
35
|
+
"@rbxts/centurion": "^1.0.0-dev-d64d6ec",
|
|
36
36
|
"@rbxts/compiler-types": "2.3.0-types.1",
|
|
37
37
|
"@rbxts/types": "^1.0.794",
|
|
38
38
|
"roblox-ts": "2.3.0-dev-26ec859",
|