@rbxts/centurion-ui 1.0.5 → 1.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE.md ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2023 paradox
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/out/app/init.luau CHANGED
@@ -1,9 +1,7 @@
1
1
  -- Compiled with roblox-ts v3.0.0
2
2
  local TS = _G[script]
3
3
  local CenturionType = TS.import(script, TS.getModule(script, "@rbxts", "centurion").out).CenturionType
4
- local _services = TS.import(script, TS.getModule(script, "@rbxts", "services"))
5
- local ContentProvider = _services.ContentProvider
6
- local Players = _services.Players
4
+ local Players = TS.import(script, TS.getModule(script, "@rbxts", "services")).Players
7
5
  local mount = TS.import(script, TS.getModule(script, "@rbxts", "vide").src).mount
8
6
  local DEFAULT_INTERFACE_OPTIONS = TS.import(script, script.Parent, "constants", "options").DEFAULT_INTERFACE_OPTIONS
9
7
  local DefaultPalette = TS.import(script, script.Parent, "palette").DefaultPalette
@@ -14,8 +12,6 @@ local CenturionApp = TS.import(script, script, "centurion-app").CenturionApp
14
12
  local CenturionUI = {}
15
13
  do
16
14
  local _container = CenturionUI
17
- local MAX_PRELOAD_ATTEMPTS = 3
18
- local PRELOAD_ATTEMPT_INTERVAL = 3
19
15
  --[[
20
16
  *
21
17
  * Returns whether the terminal UI is visible.
@@ -77,31 +73,6 @@ do
77
73
  registerCommands(client.registry)
78
74
  end
79
75
  updateOptions(options)
80
- -- Attempt to preload font
81
- task.spawn(function()
82
- local _result = options.font
83
- if _result ~= nil then
84
- _result = _result.regular
85
- end
86
- local _condition = _result
87
- if _condition == nil then
88
- _condition = DEFAULT_INTERFACE_OPTIONS.font.regular
89
- end
90
- local fontFamily = _condition.Family
91
- local attempts = 0
92
- while attempts < MAX_PRELOAD_ATTEMPTS do
93
- ContentProvider:PreloadAsync({ fontFamily }, function(_, status)
94
- if status == Enum.AssetFetchStatus.Success then
95
- attempts = MAX_PRELOAD_ATTEMPTS
96
- end
97
- end)
98
- if attempts == MAX_PRELOAD_ATTEMPTS then
99
- break
100
- end
101
- task.wait(PRELOAD_ATTEMPT_INTERVAL)
102
- attempts += 1
103
- end
104
- end)
105
76
  mount(function()
106
77
  return CenturionApp(client)
107
78
  end, Players.LocalPlayer:WaitForChild("PlayerGui"))
@@ -2,9 +2,8 @@ import { HistoryEntry } from "@rbxts/centurion";
2
2
  import Vide, { Derivable } from "@rbxts/vide";
3
3
  interface HistoryLineProps {
4
4
  data: HistoryEntry;
5
- size?: Derivable<UDim2>;
6
5
  position?: Derivable<UDim2>;
7
6
  order?: Derivable<number>;
8
7
  }
9
- export declare function HistoryLine({ data, size, position, order }: HistoryLineProps): Vide.Node;
8
+ export declare function HistoryLine({ data, position, order }: HistoryLineProps): Vide.Node;
10
9
  export {};
@@ -13,7 +13,6 @@ local Text = TS.import(script, script.Parent.Parent, "ui", "text").Text
13
13
  local TextField = TS.import(script, script.Parent.Parent, "ui", "text-field").TextField
14
14
  local function HistoryLine(_param)
15
15
  local data = _param.data
16
- local size = _param.size
17
16
  local position = _param.position
18
17
  local order = _param.order
19
18
  local date = derive(function()
@@ -22,7 +21,8 @@ local function HistoryLine(_param)
22
21
  return `<b>{dateParts[1]}</b> {dateParts[2]}`
23
22
  end)
24
23
  return Vide.jsx(Group, {
25
- size = size,
24
+ automaticSize = "Y",
25
+ size = UDim2.fromScale(1, 0),
26
26
  position = position,
27
27
  layoutOrder = order,
28
28
  }, Vide.jsx(Frame, {
@@ -58,11 +58,14 @@ local function HistoryLine(_param)
58
58
  return UDim.new(0, px(4))
59
59
  end,
60
60
  })), Vide.jsx(TextField, {
61
+ automaticSize = "Y",
61
62
  anchor = Vector2.new(1, 0),
62
63
  size = function()
63
- return UDim2.new(1, -px(84), 1, 0)
64
+ return UDim2.new(1, -px(84), 0, 0)
65
+ end,
66
+ position = function()
67
+ return UDim2.new(1, 0, 0, px(2))
64
68
  end,
65
- position = UDim2.fromScale(1, 0),
66
69
  text = data.text,
67
70
  textSize = function()
68
71
  return px(HISTORY_TEXT_SIZE)
@@ -1,11 +1,11 @@
1
+ import { HistoryEntry } from "@rbxts/centurion";
1
2
  import Vide, { Derivable } from "@rbxts/vide";
2
- import { HistoryData } from "../../types";
3
3
  interface HistoryListProps {
4
- data: Derivable<HistoryData>;
4
+ entries: Derivable<HistoryEntry[]>;
5
5
  size?: Derivable<UDim2>;
6
6
  position?: Derivable<UDim2>;
7
- maxHeight?: Derivable<number>;
8
7
  scrollingEnabled?: Derivable<boolean>;
8
+ onContentSizeChanged?: (size: Vector2) => void;
9
9
  }
10
- export declare function HistoryList({ data, size, position, maxHeight, }: HistoryListProps): Vide.Node;
10
+ export declare function HistoryList({ entries, size, position, scrollingEnabled, onContentSizeChanged, }: HistoryListProps): Vide.Node;
11
11
  export {};
@@ -2,50 +2,50 @@
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 derive = _vide.derive
6
5
  local For = _vide.For
7
6
  local read = _vide.read
7
+ local source = _vide.source
8
8
  local px = TS.import(script, script.Parent.Parent.Parent, "hooks", "use-px").px
9
9
  local options = TS.import(script, script.Parent.Parent.Parent, "store").options
10
10
  local ScrollingFrame = TS.import(script, script.Parent.Parent, "ui", "scrolling-frame").ScrollingFrame
11
11
  local HistoryLine = TS.import(script, script.Parent, "history-line").HistoryLine
12
12
  local function HistoryList(_param)
13
- local data = _param.data
13
+ local entries = _param.entries
14
14
  local size = _param.size
15
15
  local position = _param.position
16
- local maxHeight = _param.maxHeight
17
- local height = derive(function()
18
- return read(data).height - px(8)
19
- end)
20
- local exceedsMaxHeight = derive(function()
21
- return maxHeight ~= nil and height() > read(maxHeight)
22
- end)
16
+ local scrollingEnabled = _param.scrollingEnabled
17
+ local onContentSizeChanged = _param.onContentSizeChanged
18
+ local ref = source()
23
19
  return Vide.jsx(ScrollingFrame, {
20
+ automaticCanvasSize = "Y",
24
21
  size = size,
25
22
  position = position,
26
- canvasSize = function()
27
- return UDim2.fromOffset(0, height())
28
- end,
29
- canvasPosition = function()
30
- return Vector2.new(0, height())
31
- end,
23
+ canvasSize = UDim2.new(),
24
+ action = ref,
32
25
  scrollBarColor = function()
33
26
  return options().palette.subtext
34
27
  end,
28
+ scrollingEnabled = scrollingEnabled,
35
29
  scrollBarThickness = function()
36
- return if exceedsMaxHeight() then 10 else 0
37
- end,
38
- scrollingEnabled = function()
39
- return exceedsMaxHeight()
30
+ return if read(scrollingEnabled) then 10 else 0
40
31
  end,
32
+ scrollingDirection = "Y",
33
+ native = {
34
+ AbsoluteCanvasSizeChanged = function(rbx)
35
+ local frame = ref()
36
+ if frame == nil then
37
+ return nil
38
+ end
39
+ frame.CanvasPosition = Vector2.new(0, rbx.Y)
40
+ end,
41
+ },
41
42
  }, Vide.jsx(For, {
42
43
  each = function()
43
- return read(data).lines
44
+ return read(entries)
44
45
  end,
45
- }, function(line, index)
46
+ }, function(entry, index)
46
47
  return Vide.jsx(HistoryLine, {
47
- size = UDim2.new(1, 0, 0, line.height),
48
- data = line.entry,
48
+ data = entry,
49
49
  order = index,
50
50
  })
51
51
  end), Vide.jsx("uilistlayout", {
@@ -53,6 +53,13 @@ local function HistoryList(_param)
53
53
  return UDim.new(0, px(8))
54
54
  end,
55
55
  SortOrder = "LayoutOrder",
56
+ AbsoluteContentSizeChanged = function(rbx)
57
+ local _result = onContentSizeChanged
58
+ if _result ~= nil then
59
+ _result = _result(rbx)
60
+ end
61
+ return _result
62
+ end,
56
63
  }))
57
64
  end
58
65
  return {
@@ -3,11 +3,7 @@ import { Suggestion } from "../../types";
3
3
  export interface MainSuggestionProps {
4
4
  suggestion: Derivable<Suggestion | undefined>;
5
5
  currentText?: Derivable<string | undefined>;
6
- size: Derivable<UDim2>;
7
- titleSize: Derivable<UDim2>;
8
- descriptionSize: Derivable<UDim2>;
9
- badgeSize: Derivable<UDim2>;
10
- errorSize: Derivable<UDim2>;
11
6
  action?: (instance: Frame) => void;
7
+ onSizeChanged?: (size: UDim2) => void;
12
8
  }
13
- export declare function MainSuggestion({ suggestion, currentText, size, titleSize, descriptionSize, badgeSize, errorSize, action, }: MainSuggestionProps): Vide.Node;
9
+ export declare function MainSuggestion({ suggestion, currentText, action, onSizeChanged, }: MainSuggestionProps): Vide.Node;
@@ -2,7 +2,9 @@
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 derive = _vide.derive
5
6
  local read = _vide.read
7
+ local source = _vide.source
6
8
  local spring = _vide.spring
7
9
  local _text = TS.import(script, script.Parent.Parent.Parent, "constants", "text")
8
10
  local SUGGESTION_TEXT_SIZE = _text.SUGGESTION_TEXT_SIZE
@@ -14,20 +16,49 @@ local options = _store.options
14
16
  local Frame = TS.import(script, script.Parent.Parent, "ui", "frame").Frame
15
17
  local Padding = TS.import(script, script.Parent.Parent, "ui", "padding").Padding
16
18
  local Text = TS.import(script, script.Parent.Parent, "ui", "text").Text
17
- local Badge = TS.import(script, script.Parent, "badge").Badge
18
19
  local highlightMatching = TS.import(script, script.Parent, "util").highlightMatching
20
+ local MAX_WIDTH = 180
19
21
  local function MainSuggestion(_param)
20
22
  local suggestion = _param.suggestion
21
23
  local currentText = _param.currentText
22
- local size = _param.size
23
- local titleSize = _param.titleSize
24
- local descriptionSize = _param.descriptionSize
25
- local badgeSize = _param.badgeSize
26
- local errorSize = _param.errorSize
27
24
  local action = _param.action
25
+ local onSizeChanged = _param.onSizeChanged
26
+ local titleBounds = source(Vector2.new())
27
+ local descriptionBounds = source(Vector2.new())
28
+ local errorBounds = source(Vector2.new())
29
+ local badgeBounds = source(Vector2.new())
30
+ local errorText = derive(function()
31
+ local currentSuggestion = read(suggestion)
32
+ local _result = currentSuggestion
33
+ if _result ~= nil then
34
+ _result = _result.type
35
+ end
36
+ return if _result == "argument" then currentSuggestion.error else nil
37
+ end)
38
+ local windowSize = derive(function()
39
+ if read(suggestion) == nil then
40
+ local size = UDim2.new()
41
+ local _result = onSizeChanged
42
+ if _result ~= nil then
43
+ _result(size)
44
+ end
45
+ return size
46
+ end
47
+ local titleSize = read(titleBounds)
48
+ local descriptionSize = read(descriptionBounds)
49
+ local errorSize = read(errorBounds)
50
+ local width = math.max(titleSize.X, descriptionSize.X, errorSize.X) + badgeBounds().X
51
+ local height = titleSize.Y + descriptionSize.Y + errorSize.Y
52
+ local size = UDim2.fromOffset(width + px(8) * 2, height + px(8) * 2)
53
+ local _result = onSizeChanged
54
+ if _result ~= nil then
55
+ _result(size)
56
+ end
57
+ return size
58
+ end)
28
59
  return Vide.jsx(Frame, {
29
60
  action = action,
30
- size = size,
61
+ size = spring(windowSize, 0.2),
31
62
  backgroundColor = function()
32
63
  return options().palette.background
33
64
  end,
@@ -53,29 +84,6 @@ local function MainSuggestion(_param)
53
84
  all = function()
54
85
  return UDim.new(0, px(8))
55
86
  end,
56
- }), Vide.jsx(Badge, {
57
- color = function()
58
- return options().palette.highlight
59
- end,
60
- text = function()
61
- local currentSuggestion = read(suggestion)
62
- return if currentSuggestion ~= nil and currentSuggestion.type == "argument" then currentSuggestion.dataType else ""
63
- end,
64
- textColor = function()
65
- return options().palette.surface
66
- end,
67
- textSize = function()
68
- return px(SUGGESTION_TEXT_SIZE)
69
- end,
70
- visible = function()
71
- local currentSuggestion = read(suggestion)
72
- return currentSuggestion ~= nil and currentSuggestion.type == "argument"
73
- 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),
79
87
  }), Vide.jsx(Text, {
80
88
  text = function()
81
89
  local currentSuggestion = read(suggestion)
@@ -108,7 +116,14 @@ local function MainSuggestion(_param)
108
116
  return options().font.bold
109
117
  end,
110
118
  richText = true,
111
- size = titleSize,
119
+ size = function()
120
+ return UDim2.fromOffset(titleBounds().X, px(SUGGESTION_TITLE_TEXT_SIZE))
121
+ end,
122
+ native = {
123
+ TextBoundsChanged = function(bounds)
124
+ return titleBounds(bounds)
125
+ end,
126
+ },
112
127
  }), Vide.jsx(Text, {
113
128
  text = function()
114
129
  local _result = read(suggestion)
@@ -134,21 +149,21 @@ local function MainSuggestion(_param)
134
149
  position = function()
135
150
  return UDim2.fromOffset(0, px(SUGGESTION_TITLE_TEXT_SIZE))
136
151
  end,
137
- size = descriptionSize,
152
+ size = function()
153
+ return UDim2.fromOffset(px(MAX_WIDTH), math.max(descriptionBounds().Y, px(SUGGESTION_TEXT_SIZE)))
154
+ end,
155
+ native = {
156
+ TextBoundsChanged = function(rbx)
157
+ return descriptionBounds(rbx)
158
+ end,
159
+ },
138
160
  }), Vide.jsx(Text, {
139
161
  text = function()
140
- local currentSuggestion = read(suggestion)
141
- local _result
142
- if currentSuggestion ~= nil and currentSuggestion.type == "argument" then
143
- local _condition = currentSuggestion.error
144
- if _condition == nil then
145
- _condition = ""
146
- end
147
- _result = _condition
148
- else
149
- _result = ""
162
+ local _condition = errorText()
163
+ if _condition == nil then
164
+ _condition = ""
150
165
  end
151
- return _result
166
+ return _condition
152
167
  end,
153
168
  textColor = function()
154
169
  return options().palette.error
@@ -157,22 +172,60 @@ local function MainSuggestion(_param)
157
172
  return px(SUGGESTION_TEXT_SIZE)
158
173
  end,
159
174
  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
175
+ return if errorText() ~= nil then 0 else 1
170
176
  end, 0.2),
171
177
  textXAlignment = "Left",
178
+ textWrapped = true,
179
+ automaticSize = "Y",
172
180
  anchor = Vector2.new(0, 1),
173
181
  position = UDim2.fromScale(0, 1),
174
- size = errorSize,
175
- }))
182
+ size = function()
183
+ return UDim2.fromOffset(px(MAX_WIDTH), 0)
184
+ end,
185
+ native = {
186
+ TextBoundsChanged = function(bounds)
187
+ errorBounds(if errorText() ~= nil then bounds else Vector2.zero)
188
+ end,
189
+ },
190
+ }), Vide.jsx(Frame, {
191
+ backgroundColor = function()
192
+ return options().palette.highlight
193
+ end,
194
+ cornerRadius = function()
195
+ return UDim.new(0, px(4))
196
+ end,
197
+ clipsDescendants = true,
198
+ visible = function()
199
+ local currentSuggestion = read(suggestion)
200
+ return currentSuggestion ~= nil and currentSuggestion.type == "argument"
201
+ end,
202
+ anchor = Vector2.new(1, 0),
203
+ position = UDim2.fromScale(1, 0),
204
+ size = spring(function()
205
+ return UDim2.fromOffset(badgeBounds().X + px(4), px(SUGGESTION_TITLE_TEXT_SIZE))
206
+ end, 0.2),
207
+ }, Vide.jsx(Text, {
208
+ text = function()
209
+ local currentSuggestion = read(suggestion)
210
+ return if currentSuggestion ~= nil and currentSuggestion.type == "argument" then currentSuggestion.dataType else ""
211
+ end,
212
+ textColor = function()
213
+ return options().palette.surface
214
+ end,
215
+ textSize = function()
216
+ return px(SUGGESTION_TEXT_SIZE)
217
+ end,
218
+ textXAlignment = "Center",
219
+ font = function()
220
+ return options().font.bold
221
+ end,
222
+ size = UDim2.fromScale(1, 1),
223
+ native = {
224
+ TextBoundsChanged = function(bounds)
225
+ return badgeBounds(bounds)
226
+ end,
227
+ },
228
+ })))
176
229
  end
177
230
  return {
178
231
  MainSuggestion = MainSuggestion,
@@ -7,107 +7,17 @@ local cleanup = _vide.cleanup
7
7
  local derive = _vide.derive
8
8
  local source = _vide.source
9
9
  local spring = _vide.spring
10
- local _text = TS.import(script, script.Parent.Parent.Parent, "constants", "text")
11
- local SUGGESTION_TEXT_SIZE = _text.SUGGESTION_TEXT_SIZE
12
- local SUGGESTION_TITLE_TEXT_SIZE = _text.SUGGESTION_TITLE_TEXT_SIZE
10
+ local SUGGESTION_TEXT_SIZE = TS.import(script, script.Parent.Parent.Parent, "constants", "text").SUGGESTION_TEXT_SIZE
13
11
  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
15
12
  local _store = TS.import(script, script.Parent.Parent.Parent, "store")
16
13
  local currentSuggestion = _store.currentSuggestion
17
14
  local currentTextPart = _store.currentTextPart
18
- local options = _store.options
19
15
  local Group = TS.import(script, script.Parent.Parent, "ui", "group").Group
20
16
  local MainSuggestion = TS.import(script, script.Parent, "main-suggestion").MainSuggestion
21
17
  local SuggestionList = TS.import(script, script.Parent, "suggestion-list").SuggestionList
22
- local MAX_SUGGESTION_WIDTH = 180
23
18
  local PADDING = 8
24
19
  local function Suggestions()
25
- local suggestionRef = source()
26
- local offset = function(boundsState)
27
- return function()
28
- local bounds = boundsState()
29
- return UDim2.new(0, bounds.X, 0, bounds.Y)
30
- end
31
- end
32
- local titleBounds = useTextBounds({
33
- text = function()
34
- local _result = currentSuggestion()
35
- if _result ~= nil then
36
- _result = _result.title
37
- end
38
- return _result
39
- end,
40
- font = function()
41
- return options().font.bold
42
- end,
43
- size = function()
44
- return px(SUGGESTION_TITLE_TEXT_SIZE)
45
- end,
46
- })
47
- local descriptionBounds = useTextBounds({
48
- text = function()
49
- local _result = currentSuggestion()
50
- if _result ~= nil then
51
- _result = _result.description
52
- end
53
- return _result
54
- end,
55
- font = function()
56
- return options().font.regular
57
- end,
58
- size = function()
59
- return px(SUGGESTION_TEXT_SIZE)
60
- end,
61
- width = function()
62
- return px(MAX_SUGGESTION_WIDTH)
63
- end,
64
- })
65
- local typeBadgeBounds = useTextBounds({
66
- text = function()
67
- local suggestion = currentSuggestion()
68
- local _result = suggestion
69
- if _result ~= nil then
70
- _result = _result.type
71
- end
72
- if _result == "command" then
73
- return nil
74
- end
75
- local _result_1 = suggestion
76
- if _result_1 ~= nil then
77
- _result_1 = _result_1.dataType
78
- end
79
- return _result_1
80
- end,
81
- font = function()
82
- return options().font.bold
83
- end,
84
- size = function()
85
- return px(SUGGESTION_TEXT_SIZE)
86
- end,
87
- })
88
- local errorBounds = useTextBounds({
89
- text = function()
90
- local suggestion = currentSuggestion()
91
- local _result = suggestion
92
- if _result ~= nil then
93
- _result = _result.type
94
- end
95
- if _result == "command" then
96
- return nil
97
- end
98
- local _result_1 = suggestion
99
- if _result_1 ~= nil then
100
- _result_1 = _result_1.error
101
- end
102
- return _result_1
103
- end,
104
- font = function()
105
- return options().font.regular
106
- end,
107
- size = function()
108
- return px(SUGGESTION_TEXT_SIZE)
109
- end,
110
- })
20
+ local mainSize = source(UDim2.new())
111
21
  local listBoundsParams = Instance.new("GetTextBoundsParams")
112
22
  listBoundsParams.RichText = true
113
23
  cleanup(listBoundsParams)
@@ -130,39 +40,18 @@ local function Suggestions()
130
40
  local height = #suggestions * px(SUGGESTION_TEXT_SIZE + 6) + (#suggestions - 1) * px(4) + px(8)
131
41
  return Vector2.new(width, height)
132
42
  end)
133
- local windowSize = derive(function()
134
- local width = math.max(titleBounds().X, descriptionBounds().X, errorBounds().X, listBounds().X) + typeBadgeBounds().X
135
- local height = titleBounds().Y + descriptionBounds().Y + errorBounds().Y
136
- local padding = px(PADDING * 2)
137
- if width == 0 or height == 0 then
138
- local _result = suggestionRef()
139
- if _result ~= nil then
140
- _result = _result.AbsoluteSize.Y
141
- end
142
- local _condition = _result
143
- if _condition == nil then
144
- _condition = 0
145
- end
146
- return UDim2.fromOffset(0, _condition)
147
- end
148
- return UDim2.fromOffset(width + padding, height + padding)
149
- end)
150
43
  return Vide.jsx(Group, {
151
- size = UDim2.fromScale(1, 1),
44
+ automaticSize = "XY",
45
+ size = UDim2.fromOffset(0, 0),
152
46
  }, Vide.jsx(MainSuggestion, {
153
47
  suggestion = currentSuggestion,
154
48
  currentText = currentTextPart,
155
- size = spring(windowSize, 0.2),
156
- titleSize = offset(titleBounds),
157
- descriptionSize = offset(descriptionBounds),
158
- badgeSize = offset(typeBadgeBounds),
159
- errorSize = offset(errorBounds),
160
- action = suggestionRef,
49
+ onSizeChanged = mainSize,
161
50
  }), Vide.jsx(SuggestionList, {
162
51
  suggestion = currentSuggestion,
163
52
  currentText = currentTextPart,
164
53
  size = spring(function()
165
- return UDim2.fromOffset(windowSize().X.Offset, listBounds().Y)
54
+ return UDim2.new(0, math.max(listBounds().X, mainSize().X.Offset), 0, listBounds().Y)
166
55
  end, 0.3),
167
56
  }), Vide.jsx("uilistlayout", {
168
57
  Padding = function()
@@ -243,6 +243,14 @@ local function TerminalTextField(_param)
243
243
  _result(value)
244
244
  end
245
245
  end,
246
+ ReturnPressedFromOnScreenKeyboard = function()
247
+ local textBox = ref()
248
+ if textBox == nil then
249
+ return nil
250
+ end
251
+ task.wait()
252
+ textBox:ReleaseFocus(true)
253
+ end,
246
254
  },
247
255
  zIndex = 2,
248
256
  }), Vide.jsx(Text, {
@@ -10,7 +10,7 @@ local source = _vide.source
10
10
  local spring = _vide.spring
11
11
  local HISTORY_TEXT_SIZE = TS.import(script, script.Parent.Parent.Parent, "constants", "text").HISTORY_TEXT_SIZE
12
12
  local useClient = TS.import(script, script.Parent.Parent.Parent, "hooks", "use-client").useClient
13
- local useHistory = TS.import(script, script.Parent.Parent.Parent, "hooks", "use-history").useHistory
13
+ local useEvent = TS.import(script, script.Parent.Parent.Parent, "hooks", "use-event").useEvent
14
14
  local px = TS.import(script, script.Parent.Parent.Parent, "hooks", "use-px").px
15
15
  local _store = TS.import(script, script.Parent.Parent.Parent, "store")
16
16
  local commandArgIndex = _store.commandArgIndex
@@ -41,7 +41,20 @@ local TRAILING_SPACE_PATTERN = "(%s+)$"
41
41
  local function Terminal()
42
42
  local client = useClient()
43
43
  local missingArgs = source({})
44
- local history = useHistory()
44
+ local history = source(client.dispatcher:getHistory())
45
+ local historyHeight = source(0)
46
+ useEvent(client.dispatcher.historyUpdated, function(entries)
47
+ local _array = {}
48
+ local _length = #_array
49
+ table.move(entries, 1, #entries, _length + 1, _array)
50
+ return history(_array)
51
+ end)
52
+ local maxHeight = derive(function()
53
+ return px(MAX_HEIGHT)
54
+ end)
55
+ local scrollingEnabled = derive(function()
56
+ return historyHeight() > maxHeight()
57
+ end)
45
58
  local terminalTextParts = derive(function()
46
59
  return splitString(terminalText(), " ", true)
47
60
  end)
@@ -56,13 +69,11 @@ local function Terminal()
56
69
  end)
57
70
  local terminalHeight = derive(function()
58
71
  local padding = px.ceil(TEXT_FIELD_HEIGHT + 16)
59
- if #history().lines == 0 then
72
+ if #history() == 0 then
60
73
  return padding
61
74
  end
62
- local totalHeight = history().height
63
- local isClamped = totalHeight > px(MAX_HEIGHT)
64
- local clampedHeight = if isClamped then px(MAX_HEIGHT) else totalHeight
65
- return math.ceil(padding + clampedHeight)
75
+ local clampedHeight = if scrollingEnabled() then maxHeight() else historyHeight()
76
+ return math.ceil(padding + clampedHeight + px(8))
66
77
  end)
67
78
  return Vide.jsx(Frame, {
68
79
  size = spring(function()
@@ -97,9 +108,10 @@ local function Terminal()
97
108
  size = function()
98
109
  return UDim2.new(1, 0, 1, -px(TEXT_FIELD_HEIGHT + 8))
99
110
  end,
100
- data = history,
101
- maxHeight = function()
102
- return px(MAX_HEIGHT)
111
+ entries = history,
112
+ scrollingEnabled = scrollingEnabled,
113
+ onContentSizeChanged = function(size)
114
+ historyHeight(size.Y)
103
115
  end,
104
116
  }), Vide.jsx(TerminalTextField, {
105
117
  anchor = Vector2.new(0, 1),
@@ -28,6 +28,7 @@ local function ScrollingFrame(props)
28
28
  _attributes.ZIndex = props.zIndex
29
29
  _attributes.LayoutOrder = props.layoutOrder
30
30
  _attributes.BorderSizePixel = 0
31
+ _attributes.action = props.action
31
32
  local _attribute = props.native
32
33
  if _attribute then
33
34
  for _k, _v in _attribute do
@@ -25,7 +25,7 @@ local function TextField(props)
25
25
  TextYAlignment = props.textYAlignment,
26
26
  TextScaled = props.textScaled,
27
27
  RichText = props.richText,
28
- AutomaticSize = props.textAutoResize,
28
+ AutomaticSize = props.automaticSize,
29
29
  AutoLocalize = function()
30
30
  return options().autoLocalize
31
31
  end,
@@ -12,7 +12,6 @@ export interface TextProps<T extends Instance = TextLabel> extends FrameProps<T>
12
12
  textTruncate?: InferEnumNames<Enum.TextTruncate>;
13
13
  textScaled?: Derivable<boolean>;
14
14
  textHeight?: Derivable<number>;
15
- textAutoResize?: "X" | "Y" | "XY";
16
15
  richText?: Derivable<boolean>;
17
16
  }
18
17
  export declare function Text(props: TextProps): Vide.Node;
@@ -28,7 +28,7 @@ local function Text(props)
28
28
  LineHeight = props.textHeight,
29
29
  RichText = props.richText,
30
30
  Size = props.size,
31
- AutomaticSize = props.textAutoResize,
31
+ AutomaticSize = props.automaticSize,
32
32
  AutoLocalize = function()
33
33
  return options().autoLocalize
34
34
  end,
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.5",
4
+ "version": "1.0.7",
5
5
  "author": "paradoxuum",
6
6
  "license": "MIT",
7
7
  "main": "out/init.lua",
@@ -26,25 +26,24 @@
26
26
  "publishConfig": {
27
27
  "access": "public"
28
28
  },
29
- "scripts": {
30
- "prepack": "yarn build",
31
- "build": "shx rm -rf out && rbxtsc --verbose",
32
- "dev": "shx rm -rf out && rbxtsc -w"
33
- },
34
29
  "devDependencies": {
35
- "@rbxts/centurion": "^1.0.1",
36
30
  "@rbxts/compiler-types": "3.0.0-types.0",
37
31
  "@rbxts/types": "^1.0.813",
38
32
  "roblox-ts": "3.0.0",
39
33
  "shx": "^0.3.4",
40
- "typescript": "5.5.3"
34
+ "typescript": "5.5.3",
35
+ "@rbxts/centurion": "^1.0.1"
41
36
  },
42
37
  "dependencies": {
43
38
  "@rbxts/services": "^1.5.5",
44
39
  "@rbxts/set-timeout": "^1.1.2",
45
- "@rbxts/vide": "^0.5.0"
40
+ "@rbxts/vide": "^0.5.3"
46
41
  },
47
42
  "peerDependencies": {
48
43
  "@rbxts/centurion": "^1.0.1"
44
+ },
45
+ "scripts": {
46
+ "build": "shx rm -rf out && rbxtsc --verbose",
47
+ "dev": "shx rm -rf out && rbxtsc -w"
49
48
  }
50
49
  }
@@ -1,2 +0,0 @@
1
- import { HistoryData } from "../types";
2
- export declare function useHistory(): () => HistoryData;
@@ -1,54 +0,0 @@
1
- -- Compiled with roblox-ts v3.0.0
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 source = _vide.source
8
- local HISTORY_TEXT_SIZE = TS.import(script, script.Parent.Parent, "constants", "text").HISTORY_TEXT_SIZE
9
- local options = TS.import(script, script.Parent.Parent, "store").options
10
- local useClient = TS.import(script, script.Parent, "use-client").useClient
11
- local useEvent = TS.import(script, script.Parent, "use-event").useEvent
12
- local px = TS.import(script, script.Parent, "use-px").px
13
- local function useHistory()
14
- local client = useClient()
15
- local history = source(client.dispatcher:getHistory())
16
- useEvent(client.dispatcher.historyUpdated, function(entries)
17
- local _array = {}
18
- local _length = #_array
19
- table.move(entries, 1, #entries, _length + 1, _array)
20
- return history(_array)
21
- end)
22
- local textBoundsParams = Instance.new("GetTextBoundsParams")
23
- textBoundsParams.Width = math.huge
24
- textBoundsParams.RichText = true
25
- cleanup(function()
26
- textBoundsParams:Destroy()
27
- end)
28
- return derive(function()
29
- local entries = history()
30
- local historySize = #entries
31
- local totalHeight = if historySize > 0 then px(8) + (historySize - 1) * px(8) else 0
32
- textBoundsParams.Size = HISTORY_TEXT_SIZE
33
- textBoundsParams.Font = options().font.regular
34
- local historyLines = {}
35
- for _, entry in entries do
36
- textBoundsParams.Text = entry.text
37
- local textSize = TextService:GetTextBoundsAsync(textBoundsParams)
38
- local lineHeight = px(textSize.Y + 4)
39
- totalHeight += lineHeight
40
- local _arg0 = {
41
- entry = entry,
42
- height = lineHeight,
43
- }
44
- table.insert(historyLines, _arg0)
45
- end
46
- return {
47
- lines = historyLines,
48
- height = totalHeight,
49
- }
50
- end)
51
- end
52
- return {
53
- useHistory = useHistory,
54
- }
@@ -1,9 +0,0 @@
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 {};
@@ -1,50 +0,0 @@
1
- -- Compiled with roblox-ts v3.0.0
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 effect = _vide.effect
7
- local read = _vide.read
8
- local source = _vide.source
9
- local getBounds = TS.Promise.promisify(function(params)
10
- return TextService:GetTextBoundsAsync(params)
11
- end)
12
- local function useTextBounds(_param)
13
- local text = _param.text
14
- local font = _param.font
15
- local size = _param.size
16
- local width = _param.width
17
- local bounds = source(Vector2.zero)
18
- local params = Instance.new("GetTextBoundsParams")
19
- params.RichText = true
20
- cleanup(params)
21
- effect(function()
22
- local textValue = read(text)
23
- if textValue == nil then
24
- bounds(Vector2.zero)
25
- return nil
26
- end
27
- params.Text = textValue
28
- local fontValue = read(font)
29
- local sizeValue = read(size)
30
- local widthValue = read(width)
31
- if fontValue ~= nil then
32
- params.Font = fontValue
33
- end
34
- if sizeValue ~= nil then
35
- params.Size = sizeValue
36
- end
37
- if widthValue ~= nil then
38
- params.Width = widthValue
39
- end
40
- getBounds(params):andThen(function(value)
41
- return bounds(value)
42
- end):catch(function()
43
- return bounds(Vector2.zero)
44
- end)
45
- end)
46
- return bounds
47
- end
48
- return {
49
- useTextBounds = useTextBounds,
50
- }