@rbxts/centurion-ui 1.0.0-dev-284510d → 1.0.0-dev-a7b777e
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 +29 -0
- package/out/app/centurion-app.d.ts +3 -0
- package/out/app/centurion-app.lua +92 -0
- package/out/app/index.d.ts +6 -1
- package/out/app/init.lua +57 -4
- package/out/components/history/history-line.d.ts +5 -5
- package/out/components/history/history-line.lua +51 -27
- package/out/components/history/history-list.d.ts +8 -12
- package/out/components/history/history-list.lua +41 -41
- package/out/components/index.d.ts +1 -0
- package/out/components/init.lua +3 -0
- package/out/components/suggestions/badge.d.ts +11 -11
- package/out/components/suggestions/badge.lua +14 -20
- package/out/components/suggestions/main-suggestion.d.ts +6 -8
- package/out/components/suggestions/main-suggestion.lua +153 -143
- package/out/components/suggestions/suggestion-list.d.ts +5 -5
- package/out/components/suggestions/suggestion-list.lua +70 -49
- package/out/components/suggestions/suggestions.d.ts +2 -1
- package/out/components/suggestions/suggestions.lua +41 -50
- package/out/components/suggestions/util.d.ts +2 -2
- package/out/components/suggestions/util.lua +1 -0
- package/out/components/terminal/index.d.ts +1 -0
- package/out/{store/history → components/terminal}/init.lua +1 -1
- package/out/components/terminal/terminal-text-field.d.ts +11 -0
- package/out/components/terminal/terminal-text-field.lua +319 -0
- package/out/components/terminal/terminal.d.ts +2 -0
- package/out/components/terminal/terminal.lua +240 -0
- package/out/components/ui/frame.d.ts +17 -18
- package/out/components/ui/frame.lua +8 -10
- package/out/components/ui/group.d.ts +13 -15
- package/out/components/ui/group.lua +6 -9
- package/out/components/ui/layer.d.ts +5 -5
- package/out/components/ui/layer.lua +3 -3
- package/out/components/ui/outline.d.ts +13 -12
- package/out/components/ui/outline.lua +64 -54
- package/out/components/ui/padding.d.ts +7 -7
- package/out/components/ui/padding.lua +2 -2
- package/out/components/ui/scrolling-frame.d.ts +11 -12
- package/out/components/ui/scrolling-frame.lua +4 -9
- package/out/components/ui/text-field.d.ts +10 -9
- package/out/components/ui/text-field.lua +15 -13
- package/out/components/ui/text.d.ts +16 -16
- package/out/components/ui/text.lua +39 -38
- package/out/constants/springs.lua +1 -1
- package/out/hooks/use-api.d.ts +3 -0
- package/out/hooks/use-api.lua +18 -0
- package/out/hooks/use-atom.d.ts +2 -0
- package/out/hooks/use-atom.lua +17 -0
- package/out/hooks/use-debounce-source.d.ts +11 -0
- package/out/hooks/use-debounce-source.lua +27 -0
- package/out/hooks/use-event.d.ts +14 -0
- package/out/hooks/use-event.lua +58 -0
- package/out/hooks/use-history.d.ts +2 -0
- package/out/hooks/use-history.lua +56 -0
- package/out/hooks/use-motion.d.ts +4 -4
- package/out/hooks/use-motion.lua +11 -16
- package/out/hooks/use-px.d.ts +13 -1
- package/out/hooks/use-px.lua +52 -39
- package/out/store.d.ts +14 -0
- package/out/store.lua +44 -0
- package/out/types.d.ts +7 -4
- package/out/util/argument.d.ts +2 -1
- package/out/util/argument.lua +25 -0
- package/out/util/suggestion.d.ts +2 -2
- package/out/util/suggestion.lua +9 -14
- package/package.json +14 -14
- package/out/app/app.d.ts +0 -6
- package/out/app/app.lua +0 -83
- package/out/app/terminal-app.d.ts +0 -1
- package/out/app/terminal-app.lua +0 -61
- package/out/components/terminal-text-field.d.ts +0 -11
- package/out/components/terminal-text-field.lua +0 -289
- package/out/components/terminal-window.d.ts +0 -1
- package/out/components/terminal-window.lua +0 -265
- package/out/components/terminal.d.ts +0 -1
- package/out/components/terminal.lua +0 -26
- package/out/components/ui/shortcut-group.d.ts +0 -6
- package/out/components/ui/shortcut-group.lua +0 -100
- package/out/hooks/use-store.d.ts +0 -3
- package/out/hooks/use-store.lua +0 -7
- package/out/providers/api-provider.d.ts +0 -8
- package/out/providers/api-provider.lua +0 -17
- package/out/providers/options-provider.d.ts +0 -13
- package/out/providers/options-provider.lua +0 -39
- package/out/providers/root-provider.d.ts +0 -11
- package/out/providers/root-provider.lua +0 -24
- package/out/store/app/app-selectors.d.ts +0 -2
- package/out/store/app/app-selectors.lua +0 -7
- package/out/store/app/app-slice.d.ts +0 -8
- package/out/store/app/app-slice.lua +0 -17
- package/out/store/app/index.d.ts +0 -2
- package/out/store/app/init.lua +0 -10
- package/out/store/command/command-selectors.d.ts +0 -2
- package/out/store/command/command-selectors.lua +0 -7
- package/out/store/command/command-slice.d.ts +0 -15
- package/out/store/command/command-slice.lua +0 -21
- package/out/store/command/index.d.ts +0 -2
- package/out/store/command/init.lua +0 -10
- package/out/store/history/history-slice.d.ts +0 -11
- package/out/store/history/history-slice.lua +0 -52
- package/out/store/history/index.d.ts +0 -1
- package/out/store/index.d.ts +0 -46
- package/out/store/init.lua +0 -18
- package/out/store/suggestion/index.d.ts +0 -2
- package/out/store/suggestion/init.lua +0 -10
- package/out/store/suggestion/suggestion-selectors.d.ts +0 -2
- package/out/store/suggestion/suggestion-selectors.lua +0 -7
- package/out/store/suggestion/suggestion-slice.d.ts +0 -9
- package/out/store/suggestion/suggestion-slice.lua +0 -15
- package/out/store/text/index.d.ts +0 -2
- package/out/store/text/init.lua +0 -10
- package/out/store/text/text-selectors.d.ts +0 -3
- package/out/store/text/text-selectors.lua +0 -11
- package/out/store/text/text-slice.d.ts +0 -20
- package/out/store/text/text-slice.lua +0 -29
package/out/app/terminal-app.lua
DELETED
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
-- Compiled with roblox-ts v2.3.0-dev-26ec859
|
|
2
|
-
local TS = _G[script]
|
|
3
|
-
local useEventListener = TS.import(script, TS.getModule(script, "@rbxts", "pretty-react-hooks").out).useEventListener
|
|
4
|
-
local _react = TS.import(script, TS.getModule(script, "@rbxts", "react"))
|
|
5
|
-
local React = _react
|
|
6
|
-
local useContext = _react.useContext
|
|
7
|
-
local useMemo = _react.useMemo
|
|
8
|
-
local useSelector = TS.import(script, TS.getModule(script, "@rbxts", "react-reflex")).useSelector
|
|
9
|
-
local UserInputService = TS.import(script, TS.getModule(script, "@rbxts", "services")).UserInputService
|
|
10
|
-
local Terminal = TS.import(script, script.Parent.Parent, "components", "terminal").default
|
|
11
|
-
local Layer = TS.import(script, script.Parent.Parent, "components", "ui", "layer").Layer
|
|
12
|
-
local OptionsContext = TS.import(script, script.Parent.Parent, "providers", "options-provider").OptionsContext
|
|
13
|
-
local store = TS.import(script, script.Parent.Parent, "store").store
|
|
14
|
-
local selectVisible = TS.import(script, script.Parent.Parent, "store", "app").selectVisible
|
|
15
|
-
local function TerminalApp()
|
|
16
|
-
local options = useContext(OptionsContext)
|
|
17
|
-
local visible = useSelector(selectVisible)
|
|
18
|
-
local validKeys = useMemo(function()
|
|
19
|
-
local _set = {}
|
|
20
|
-
for _, _v in options.activationKeys do
|
|
21
|
-
_set[_v] = true
|
|
22
|
-
end
|
|
23
|
-
return _set
|
|
24
|
-
end, { options })
|
|
25
|
-
local mouseInputTypes = useMemo(function()
|
|
26
|
-
return {
|
|
27
|
-
[Enum.UserInputType.MouseButton1] = true,
|
|
28
|
-
[Enum.UserInputType.MouseButton2] = true,
|
|
29
|
-
[Enum.UserInputType.Touch] = true,
|
|
30
|
-
}
|
|
31
|
-
end, {})
|
|
32
|
-
useEventListener(UserInputService.InputBegan, function(input, gameProcessed)
|
|
33
|
-
local _keyCode = input.KeyCode
|
|
34
|
-
local _condition = validKeys[_keyCode] ~= nil
|
|
35
|
-
if _condition then
|
|
36
|
-
_condition = not gameProcessed
|
|
37
|
-
end
|
|
38
|
-
if _condition then
|
|
39
|
-
store.setVisible(not visible)
|
|
40
|
-
else
|
|
41
|
-
local _condition_1 = options.hideOnLostFocus
|
|
42
|
-
if _condition_1 then
|
|
43
|
-
local _userInputType = input.UserInputType
|
|
44
|
-
_condition_1 = mouseInputTypes[_userInputType] ~= nil
|
|
45
|
-
if _condition_1 then
|
|
46
|
-
_condition_1 = not options.isMouseOnGUI
|
|
47
|
-
end
|
|
48
|
-
end
|
|
49
|
-
if _condition_1 then
|
|
50
|
-
store.setVisible(false)
|
|
51
|
-
end
|
|
52
|
-
end
|
|
53
|
-
end)
|
|
54
|
-
return React.createElement(Layer, {
|
|
55
|
-
displayOrder = options.displayOrder,
|
|
56
|
-
visible = visible,
|
|
57
|
-
}, React.createElement(Terminal))
|
|
58
|
-
end
|
|
59
|
-
return {
|
|
60
|
-
TerminalApp = TerminalApp,
|
|
61
|
-
}
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import { BindingOrValue } from "@rbxts/pretty-react-hooks";
|
|
2
|
-
interface TerminalTextFieldProps {
|
|
3
|
-
anchorPoint?: BindingOrValue<Vector2>;
|
|
4
|
-
size?: BindingOrValue<UDim2>;
|
|
5
|
-
position?: BindingOrValue<UDim2>;
|
|
6
|
-
backgroundTransparency?: BindingOrValue<number>;
|
|
7
|
-
onTextChange?: (text: string) => void;
|
|
8
|
-
onSubmit?: (text: string) => void;
|
|
9
|
-
}
|
|
10
|
-
export declare function TerminalTextField({ anchorPoint, size, position, backgroundTransparency, onTextChange, onSubmit, }: TerminalTextFieldProps): JSX.Element;
|
|
11
|
-
export {};
|
|
@@ -1,289 +0,0 @@
|
|
|
1
|
-
-- Compiled with roblox-ts v2.3.0-dev-26ec859
|
|
2
|
-
local TS = _G[script]
|
|
3
|
-
local _string = TS.import(script, TS.getModule(script, "@rbxts", "centurion").out.shared.util.string)
|
|
4
|
-
local endsWithSpace = _string.endsWithSpace
|
|
5
|
-
local formatPartsAsPath = _string.formatPartsAsPath
|
|
6
|
-
local _pretty_react_hooks = TS.import(script, TS.getModule(script, "@rbxts", "pretty-react-hooks").out)
|
|
7
|
-
local getBindingValue = _pretty_react_hooks.getBindingValue
|
|
8
|
-
local useEventListener = _pretty_react_hooks.useEventListener
|
|
9
|
-
local useMountEffect = _pretty_react_hooks.useMountEffect
|
|
10
|
-
local _react = TS.import(script, TS.getModule(script, "@rbxts", "react"))
|
|
11
|
-
local React = _react
|
|
12
|
-
local useBinding = _react.useBinding
|
|
13
|
-
local useCallback = _react.useCallback
|
|
14
|
-
local useContext = _react.useContext
|
|
15
|
-
local useEffect = _react.useEffect
|
|
16
|
-
local useRef = _react.useRef
|
|
17
|
-
local useState = _react.useState
|
|
18
|
-
local useSelector = TS.import(script, TS.getModule(script, "@rbxts", "react-reflex")).useSelector
|
|
19
|
-
local UserInputService = TS.import(script, TS.getModule(script, "@rbxts", "services")).UserInputService
|
|
20
|
-
local usePx = TS.import(script, script.Parent.Parent, "hooks", "use-px").usePx
|
|
21
|
-
local useStore = TS.import(script, script.Parent.Parent, "hooks", "use-store").useStore
|
|
22
|
-
local ApiContext = TS.import(script, script.Parent.Parent, "providers", "api-provider").ApiContext
|
|
23
|
-
local OptionsContext = TS.import(script, script.Parent.Parent, "providers", "options-provider").OptionsContext
|
|
24
|
-
local selectVisible = TS.import(script, script.Parent.Parent, "store", "app").selectVisible
|
|
25
|
-
local selectCommand = TS.import(script, script.Parent.Parent, "store", "command").selectCommand
|
|
26
|
-
local selectSuggestion = TS.import(script, script.Parent.Parent, "store", "suggestion").selectSuggestion
|
|
27
|
-
local selectValid = TS.import(script, script.Parent.Parent, "store", "text").selectValid
|
|
28
|
-
local getArgumentNames = TS.import(script, script.Parent.Parent, "util", "argument").getArgumentNames
|
|
29
|
-
local Frame = TS.import(script, script.Parent, "ui", "frame").Frame
|
|
30
|
-
local Padding = TS.import(script, script.Parent, "ui", "padding").Padding
|
|
31
|
-
local Text = TS.import(script, script.Parent, "ui", "text").Text
|
|
32
|
-
local TextField = TS.import(script, script.Parent, "ui", "text-field").TextField
|
|
33
|
-
local TEXT_SIZE = 22
|
|
34
|
-
local function TerminalTextField(_param)
|
|
35
|
-
local anchorPoint = _param.anchorPoint
|
|
36
|
-
local size = _param.size
|
|
37
|
-
local position = _param.position
|
|
38
|
-
local backgroundTransparency = _param.backgroundTransparency
|
|
39
|
-
local onTextChange = _param.onTextChange
|
|
40
|
-
local onSubmit = _param.onSubmit
|
|
41
|
-
local px = usePx()
|
|
42
|
-
local ref = useRef()
|
|
43
|
-
local api = useContext(ApiContext)
|
|
44
|
-
local options = useContext(OptionsContext)
|
|
45
|
-
local store = useStore()
|
|
46
|
-
local appVisible = useSelector(selectVisible)
|
|
47
|
-
local currentSuggestion = useSelector(selectSuggestion)
|
|
48
|
-
local text, setText = useBinding("")
|
|
49
|
-
local suggestionText, setSuggestionText = useBinding("")
|
|
50
|
-
local valid, setValid = useState(false)
|
|
51
|
-
local traverseHistory = useCallback(function(up)
|
|
52
|
-
local history = store:getState().history.commandHistory
|
|
53
|
-
if #history == 0 then
|
|
54
|
-
return nil
|
|
55
|
-
end
|
|
56
|
-
local historyIndex = store:getState().history.commandHistoryIndex
|
|
57
|
-
if (up and historyIndex == 0) or (not up and historyIndex == -1) then
|
|
58
|
-
return nil
|
|
59
|
-
end
|
|
60
|
-
local newIndex
|
|
61
|
-
if up then
|
|
62
|
-
newIndex = if historyIndex == -1 then #history - 1 else historyIndex - 1
|
|
63
|
-
else
|
|
64
|
-
newIndex = if historyIndex ~= #history - 1 then historyIndex + 1 else -1
|
|
65
|
-
end
|
|
66
|
-
local newText = if newIndex ~= -1 then history[newIndex + 1] else ""
|
|
67
|
-
setText(newText)
|
|
68
|
-
setSuggestionText("")
|
|
69
|
-
store.setCommandHistoryIndex(newIndex)
|
|
70
|
-
if ref.current ~= nil then
|
|
71
|
-
ref.current.CursorPosition = #newText + 1
|
|
72
|
-
end
|
|
73
|
-
end, {})
|
|
74
|
-
useEffect(function()
|
|
75
|
-
if ref.current == nil then
|
|
76
|
-
return nil
|
|
77
|
-
end
|
|
78
|
-
if appVisible then
|
|
79
|
-
ref.current:CaptureFocus()
|
|
80
|
-
else
|
|
81
|
-
ref.current:ReleaseFocus()
|
|
82
|
-
end
|
|
83
|
-
end, { appVisible })
|
|
84
|
-
useMountEffect(function()
|
|
85
|
-
store:subscribe(selectValid, function(valid)
|
|
86
|
-
setValid(valid)
|
|
87
|
-
end)
|
|
88
|
-
store:subscribe(selectCommand, function(command)
|
|
89
|
-
if not store:getState().text.valid then
|
|
90
|
-
return nil
|
|
91
|
-
end
|
|
92
|
-
setValid(command ~= nil)
|
|
93
|
-
end)
|
|
94
|
-
end)
|
|
95
|
-
useEffect(function()
|
|
96
|
-
if currentSuggestion == nil then
|
|
97
|
-
setSuggestionText("")
|
|
98
|
-
return nil
|
|
99
|
-
end
|
|
100
|
-
local state = store:getState()
|
|
101
|
-
local atNextPart = endsWithSpace(state.text.value)
|
|
102
|
-
local suggestionStartIndex = if #state.text.parts > 0 then (if not atNextPart then #state.text.parts[#state.text.parts] else 0) + 1 else -1
|
|
103
|
-
local command = state.command.path
|
|
104
|
-
local argIndex = state.command.argIndex
|
|
105
|
-
if currentSuggestion.main.type == "command" and suggestionStartIndex > -1 then
|
|
106
|
-
setSuggestionText(getBindingValue(text) .. string.sub(currentSuggestion.main.title, suggestionStartIndex))
|
|
107
|
-
return nil
|
|
108
|
-
end
|
|
109
|
-
if currentSuggestion.main.type ~= "argument" or command == nil or argIndex == nil then
|
|
110
|
-
return nil
|
|
111
|
-
end
|
|
112
|
-
local newText = getBindingValue(text)
|
|
113
|
-
local argNames = getArgumentNames(api.registry, command)
|
|
114
|
-
for i = argIndex, #argNames - 1 do
|
|
115
|
-
if i == argIndex and not atNextPart then
|
|
116
|
-
if not (#currentSuggestion.others == 0) then
|
|
117
|
-
newText ..= string.sub(currentSuggestion.others[1], suggestionStartIndex)
|
|
118
|
-
end
|
|
119
|
-
newText ..= " "
|
|
120
|
-
continue
|
|
121
|
-
end
|
|
122
|
-
newText = `{newText}{argNames[i + 1]} `
|
|
123
|
-
end
|
|
124
|
-
setSuggestionText(newText)
|
|
125
|
-
end, { currentSuggestion })
|
|
126
|
-
useEventListener(UserInputService.InputBegan, function(input)
|
|
127
|
-
if ref.current == nil or not ref.current:IsFocused() then
|
|
128
|
-
return nil
|
|
129
|
-
end
|
|
130
|
-
if input.KeyCode == Enum.KeyCode.Up then
|
|
131
|
-
traverseHistory(true)
|
|
132
|
-
elseif input.KeyCode == Enum.KeyCode.Down then
|
|
133
|
-
traverseHistory(false)
|
|
134
|
-
end
|
|
135
|
-
if input.KeyCode ~= Enum.KeyCode.Tab then
|
|
136
|
-
return nil
|
|
137
|
-
end
|
|
138
|
-
local state = store:getState()
|
|
139
|
-
local commandPath = state.command.path
|
|
140
|
-
-- Handle command suggestions
|
|
141
|
-
if commandPath == nil then
|
|
142
|
-
local _suggestionTitle = currentSuggestion
|
|
143
|
-
if _suggestionTitle ~= nil then
|
|
144
|
-
_suggestionTitle = _suggestionTitle.main.title
|
|
145
|
-
end
|
|
146
|
-
local suggestionTitle = _suggestionTitle
|
|
147
|
-
if suggestionTitle == nil then
|
|
148
|
-
return nil
|
|
149
|
-
end
|
|
150
|
-
local currentText = text:getValue()
|
|
151
|
-
local newText = ""
|
|
152
|
-
if endsWithSpace(currentText) then
|
|
153
|
-
newText = currentText .. suggestionTitle
|
|
154
|
-
elseif not (#state.text.parts == 0) then
|
|
155
|
-
local textPartSize = #state.text.parts[#state.text.parts]
|
|
156
|
-
local _arg1 = #currentText - textPartSize
|
|
157
|
-
newText = string.sub(currentText, 0, _arg1) .. suggestionTitle
|
|
158
|
-
end
|
|
159
|
-
local suggestionTextParts = string.split((string.gsub(suggestionText:getValue(), "%s+", " ")), " ")
|
|
160
|
-
local _nextCommand = api.registry:getCommandByString(formatPartsAsPath(suggestionTextParts))
|
|
161
|
-
if _nextCommand ~= nil then
|
|
162
|
-
_nextCommand = _nextCommand.options
|
|
163
|
-
end
|
|
164
|
-
local nextCommand = _nextCommand
|
|
165
|
-
local _condition = nextCommand == nil
|
|
166
|
-
if not _condition then
|
|
167
|
-
local _result = nextCommand.arguments
|
|
168
|
-
if _result ~= nil then
|
|
169
|
-
_result = #_result
|
|
170
|
-
end
|
|
171
|
-
local _condition_1 = _result
|
|
172
|
-
if _condition_1 == nil then
|
|
173
|
-
_condition_1 = 0
|
|
174
|
-
end
|
|
175
|
-
_condition = _condition_1 > 0
|
|
176
|
-
end
|
|
177
|
-
if _condition then
|
|
178
|
-
newText ..= " "
|
|
179
|
-
end
|
|
180
|
-
setSuggestionText("")
|
|
181
|
-
setText(newText)
|
|
182
|
-
ref.current.CursorPosition = #newText + 1
|
|
183
|
-
return nil
|
|
184
|
-
end
|
|
185
|
-
-- Handle argument suggestions
|
|
186
|
-
if commandPath == nil or currentSuggestion == nil or #currentSuggestion.others == 0 then
|
|
187
|
-
return nil
|
|
188
|
-
end
|
|
189
|
-
local argIndex = state.command.argIndex
|
|
190
|
-
local _commandArgs = api.registry:getCommand(commandPath)
|
|
191
|
-
if _commandArgs ~= nil then
|
|
192
|
-
_commandArgs = _commandArgs.options.arguments
|
|
193
|
-
end
|
|
194
|
-
local commandArgs = _commandArgs
|
|
195
|
-
if argIndex == nil or commandArgs == nil then
|
|
196
|
-
return nil
|
|
197
|
-
end
|
|
198
|
-
local newText = getBindingValue(text)
|
|
199
|
-
local parts = state.text.parts
|
|
200
|
-
if not endsWithSpace(newText) and not (#parts == 0) then
|
|
201
|
-
local _newText = newText
|
|
202
|
-
local _arg1 = #newText - #parts[#parts]
|
|
203
|
-
newText = string.sub(_newText, 0, _arg1)
|
|
204
|
-
end
|
|
205
|
-
local suggestion = currentSuggestion.others[1]
|
|
206
|
-
if (string.match(suggestion, "%s")) ~= nil then
|
|
207
|
-
suggestion = `"{suggestion}"`
|
|
208
|
-
end
|
|
209
|
-
newText ..= suggestion
|
|
210
|
-
if argIndex < #commandArgs - 1 then
|
|
211
|
-
newText ..= " "
|
|
212
|
-
end
|
|
213
|
-
setSuggestionText("")
|
|
214
|
-
setText(newText)
|
|
215
|
-
ref.current.CursorPosition = #newText + 1
|
|
216
|
-
end)
|
|
217
|
-
return React.createElement(Frame, {
|
|
218
|
-
anchorPoint = anchorPoint,
|
|
219
|
-
size = size,
|
|
220
|
-
position = position,
|
|
221
|
-
backgroundColor = options.palette.surface,
|
|
222
|
-
backgroundTransparency = backgroundTransparency,
|
|
223
|
-
cornerRadius = UDim.new(0, px(4)),
|
|
224
|
-
}, React.createElement(Padding, {
|
|
225
|
-
all = UDim.new(0, px(8)),
|
|
226
|
-
}), React.createElement(TextField, {
|
|
227
|
-
size = UDim2.fromScale(1, 1),
|
|
228
|
-
placeholderText = "Enter command...",
|
|
229
|
-
text = text,
|
|
230
|
-
textSize = px(TEXT_SIZE),
|
|
231
|
-
textColor = if valid then options.palette.success else options.palette.error,
|
|
232
|
-
placeholderColor = options.palette.subtext,
|
|
233
|
-
textXAlignment = "Left",
|
|
234
|
-
clearTextOnFocus = false,
|
|
235
|
-
font = options.font.medium,
|
|
236
|
-
ref = ref,
|
|
237
|
-
event = {
|
|
238
|
-
FocusLost = function(rbx, enterPressed)
|
|
239
|
-
if not enterPressed then
|
|
240
|
-
return nil
|
|
241
|
-
end
|
|
242
|
-
store.addCommandHistory(rbx.Text, api.options.historyLength)
|
|
243
|
-
store.setCommandHistoryIndex(-1)
|
|
244
|
-
local _result = onSubmit
|
|
245
|
-
if _result ~= nil then
|
|
246
|
-
_result(rbx.Text)
|
|
247
|
-
end
|
|
248
|
-
local _result_1 = ref.current
|
|
249
|
-
if _result_1 ~= nil then
|
|
250
|
-
_result_1:CaptureFocus()
|
|
251
|
-
end
|
|
252
|
-
setText("")
|
|
253
|
-
end,
|
|
254
|
-
},
|
|
255
|
-
change = {
|
|
256
|
-
Text = function(rbx)
|
|
257
|
-
local newText = rbx.Text
|
|
258
|
-
-- Remove line breaks
|
|
259
|
-
if (string.match(newText, "[\n\r]")) ~= nil then
|
|
260
|
-
newText = (string.gsub(newText, "[\n\r]", ""))
|
|
261
|
-
end
|
|
262
|
-
-- Remove all tabs from text input - we use these for autocompletion
|
|
263
|
-
if (string.match(newText, "\t")) ~= nil then
|
|
264
|
-
newText = (string.gsub(newText, "\t", ""))
|
|
265
|
-
end
|
|
266
|
-
-- Reset command history index
|
|
267
|
-
if store:getState().history.commandHistoryIndex ~= -1 then
|
|
268
|
-
store.setCommandHistoryIndex(-1)
|
|
269
|
-
end
|
|
270
|
-
setText(newText)
|
|
271
|
-
local _result = onTextChange
|
|
272
|
-
if _result ~= nil then
|
|
273
|
-
_result(newText)
|
|
274
|
-
end
|
|
275
|
-
end,
|
|
276
|
-
},
|
|
277
|
-
zIndex = 2,
|
|
278
|
-
}), React.createElement(Text, {
|
|
279
|
-
size = UDim2.fromScale(1, 1),
|
|
280
|
-
text = suggestionText,
|
|
281
|
-
textColor = options.palette.subtext,
|
|
282
|
-
textSize = px(TEXT_SIZE),
|
|
283
|
-
textXAlignment = "Left",
|
|
284
|
-
font = options.font.medium,
|
|
285
|
-
}))
|
|
286
|
-
end
|
|
287
|
-
return {
|
|
288
|
-
TerminalTextField = TerminalTextField,
|
|
289
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare function TerminalWindow(): JSX.Element;
|
|
@@ -1,265 +0,0 @@
|
|
|
1
|
-
-- Compiled with roblox-ts v2.3.0-dev-26ec859
|
|
2
|
-
local TS = _G[script]
|
|
3
|
-
local _centurion = TS.import(script, TS.getModule(script, "@rbxts", "centurion").out)
|
|
4
|
-
local ImmutableRegistryPath = _centurion.ImmutableRegistryPath
|
|
5
|
-
local RegistryPath = _centurion.RegistryPath
|
|
6
|
-
local ArrayUtil = TS.import(script, TS.getModule(script, "@rbxts", "centurion").out.shared.util.data).ArrayUtil
|
|
7
|
-
local _string = TS.import(script, TS.getModule(script, "@rbxts", "centurion").out.shared.util.string)
|
|
8
|
-
local endsWithSpace = _string.endsWithSpace
|
|
9
|
-
local formatPartsAsPath = _string.formatPartsAsPath
|
|
10
|
-
local splitString = _string.splitString
|
|
11
|
-
local _pretty_react_hooks = TS.import(script, TS.getModule(script, "@rbxts", "pretty-react-hooks").out)
|
|
12
|
-
local useEventListener = _pretty_react_hooks.useEventListener
|
|
13
|
-
local useLatestCallback = _pretty_react_hooks.useLatestCallback
|
|
14
|
-
local _react = TS.import(script, TS.getModule(script, "@rbxts", "react"))
|
|
15
|
-
local React = _react
|
|
16
|
-
local useContext = _react.useContext
|
|
17
|
-
local useEffect = _react.useEffect
|
|
18
|
-
local useMemo = _react.useMemo
|
|
19
|
-
local useState = _react.useState
|
|
20
|
-
local TextService = TS.import(script, TS.getModule(script, "@rbxts", "services")).TextService
|
|
21
|
-
local HISTORY_TEXT_SIZE = TS.import(script, script.Parent.Parent, "constants", "text").HISTORY_TEXT_SIZE
|
|
22
|
-
local useMotion = TS.import(script, script.Parent.Parent, "hooks", "use-motion").useMotion
|
|
23
|
-
local usePx = TS.import(script, script.Parent.Parent, "hooks", "use-px").usePx
|
|
24
|
-
local useStore = TS.import(script, script.Parent.Parent, "hooks", "use-store").useStore
|
|
25
|
-
local ApiContext = TS.import(script, script.Parent.Parent, "providers", "api-provider").ApiContext
|
|
26
|
-
local OptionsContext = TS.import(script, script.Parent.Parent, "providers", "options-provider").OptionsContext
|
|
27
|
-
local _suggestion = TS.import(script, script.Parent.Parent, "util", "suggestion")
|
|
28
|
-
local getArgumentSuggestion = _suggestion.getArgumentSuggestion
|
|
29
|
-
local getCommandSuggestion = _suggestion.getCommandSuggestion
|
|
30
|
-
local HistoryList = TS.import(script, script.Parent, "history").HistoryList
|
|
31
|
-
local TerminalTextField = TS.import(script, script.Parent, "terminal-text-field").TerminalTextField
|
|
32
|
-
local Frame = TS.import(script, script.Parent, "ui", "frame").Frame
|
|
33
|
-
local Padding = TS.import(script, script.Parent, "ui", "padding").Padding
|
|
34
|
-
local MAX_HEIGHT = HISTORY_TEXT_SIZE * 10
|
|
35
|
-
local TEXT_FIELD_HEIGHT = 40
|
|
36
|
-
local function TerminalWindow()
|
|
37
|
-
local px = usePx()
|
|
38
|
-
local store = useStore()
|
|
39
|
-
local api = useContext(ApiContext)
|
|
40
|
-
local options = useContext(OptionsContext)
|
|
41
|
-
local history, setHistory = useState(api.dispatcher:getHistory())
|
|
42
|
-
local historyData, setHistoryData = useState({
|
|
43
|
-
lines = {},
|
|
44
|
-
height = 0,
|
|
45
|
-
})
|
|
46
|
-
local historyHeight, historyHeightMotion = useMotion(0)
|
|
47
|
-
local textBoundsParams = useMemo(function()
|
|
48
|
-
local params = Instance.new("GetTextBoundsParams")
|
|
49
|
-
params.Width = math.huge
|
|
50
|
-
params.Font = options.font.regular
|
|
51
|
-
return params
|
|
52
|
-
end, {})
|
|
53
|
-
local windowHeightBinding = useMemo(function()
|
|
54
|
-
return historyHeight:map(function(y)
|
|
55
|
-
return UDim2.new(1, 0, 0, math.ceil(px(TEXT_FIELD_HEIGHT + 16) + y))
|
|
56
|
-
end)
|
|
57
|
-
end, { px })
|
|
58
|
-
local checkMissingArgs = useLatestCallback(function(path, command)
|
|
59
|
-
if command.arguments == nil or #command.arguments == 0 then
|
|
60
|
-
return nil
|
|
61
|
-
end
|
|
62
|
-
local storeState = store:getState()
|
|
63
|
-
local lastPartIndex = #storeState.text.parts - path:size() - 1
|
|
64
|
-
local missingArgs = {}
|
|
65
|
-
local index = 0
|
|
66
|
-
for _, arg in command.arguments do
|
|
67
|
-
if arg.optional then
|
|
68
|
-
break
|
|
69
|
-
end
|
|
70
|
-
if index > lastPartIndex then
|
|
71
|
-
local _arg0 = `<b>{arg.name}</b>`
|
|
72
|
-
table.insert(missingArgs, _arg0)
|
|
73
|
-
end
|
|
74
|
-
index += 1
|
|
75
|
-
end
|
|
76
|
-
if #missingArgs == 0 then
|
|
77
|
-
return nil
|
|
78
|
-
end
|
|
79
|
-
local text = "Missing required argument"
|
|
80
|
-
if #missingArgs ~= 1 then
|
|
81
|
-
text ..= "s"
|
|
82
|
-
end
|
|
83
|
-
return `{text}: {table.concat(missingArgs, ", ")}`
|
|
84
|
-
end)
|
|
85
|
-
useEventListener(api.dispatcher.historyUpdated, function(entries)
|
|
86
|
-
local _array = {}
|
|
87
|
-
local _length = #_array
|
|
88
|
-
table.move(entries, 1, #entries, _length + 1, _array)
|
|
89
|
-
setHistory(_array)
|
|
90
|
-
end)
|
|
91
|
-
-- Handle history updates
|
|
92
|
-
useEffect(function()
|
|
93
|
-
local historySize = #history
|
|
94
|
-
local totalHeight = if historySize > 0 then px(8) + (historySize - 1) * px(8) else 0
|
|
95
|
-
textBoundsParams.Size = HISTORY_TEXT_SIZE
|
|
96
|
-
local historyLines = {}
|
|
97
|
-
for _, entry in history do
|
|
98
|
-
textBoundsParams.Text = entry.text
|
|
99
|
-
local textSize = TextService:GetTextBoundsAsync(textBoundsParams)
|
|
100
|
-
local lineHeight = px(textSize.Y + 4)
|
|
101
|
-
totalHeight += lineHeight
|
|
102
|
-
local _arg0 = {
|
|
103
|
-
entry = entry,
|
|
104
|
-
height = lineHeight,
|
|
105
|
-
}
|
|
106
|
-
table.insert(historyLines, _arg0)
|
|
107
|
-
end
|
|
108
|
-
local isClamped = totalHeight > px(MAX_HEIGHT)
|
|
109
|
-
local clampedHeight = if isClamped then px(MAX_HEIGHT) else totalHeight
|
|
110
|
-
historyHeightMotion:spring(clampedHeight, {
|
|
111
|
-
mass = 0.1,
|
|
112
|
-
tension = 300,
|
|
113
|
-
friction = 15,
|
|
114
|
-
})
|
|
115
|
-
setHistoryData({
|
|
116
|
-
lines = historyLines,
|
|
117
|
-
height = totalHeight,
|
|
118
|
-
})
|
|
119
|
-
end, { history, px })
|
|
120
|
-
return React.createElement(Frame, {
|
|
121
|
-
size = windowHeightBinding,
|
|
122
|
-
backgroundColor = options.palette.background,
|
|
123
|
-
backgroundTransparency = options.backgroundTransparency,
|
|
124
|
-
cornerRadius = UDim.new(0, px(8)),
|
|
125
|
-
event = {
|
|
126
|
-
MouseEnter = function()
|
|
127
|
-
return options.setMouseOnGUI(true)
|
|
128
|
-
end,
|
|
129
|
-
MouseLeave = function()
|
|
130
|
-
return options.setMouseOnGUI(false)
|
|
131
|
-
end,
|
|
132
|
-
},
|
|
133
|
-
}, React.createElement(Padding, {
|
|
134
|
-
all = UDim.new(0, px(8)),
|
|
135
|
-
}), React.createElement(HistoryList, {
|
|
136
|
-
size = UDim2.new(1, 0, 1, -px(TEXT_FIELD_HEIGHT + 8)),
|
|
137
|
-
data = historyData,
|
|
138
|
-
maxHeight = px(MAX_HEIGHT),
|
|
139
|
-
}), React.createElement(TerminalTextField, {
|
|
140
|
-
anchorPoint = Vector2.new(0, 1),
|
|
141
|
-
size = UDim2.new(1, 0, 0, px(TEXT_FIELD_HEIGHT)),
|
|
142
|
-
position = UDim2.fromScale(0, 1),
|
|
143
|
-
backgroundTransparency = options.backgroundTransparency,
|
|
144
|
-
onTextChange = function(text)
|
|
145
|
-
local parts = splitString(text, " ")
|
|
146
|
-
store.setText(text, parts)
|
|
147
|
-
if #parts == 0 then
|
|
148
|
-
store.setSuggestion(nil)
|
|
149
|
-
store.setCommand(nil)
|
|
150
|
-
store.setArgIndex(nil)
|
|
151
|
-
return nil
|
|
152
|
-
end
|
|
153
|
-
store:flush()
|
|
154
|
-
-- If the text ends in a space, we want to count that as having traversed
|
|
155
|
-
-- to the next "part" of the text. This means we should include the previous
|
|
156
|
-
-- text part as part of the parent path.
|
|
157
|
-
local atNextPart = endsWithSpace(text)
|
|
158
|
-
local commandPath = store:getState().command.path
|
|
159
|
-
local atCommand = false
|
|
160
|
-
if commandPath ~= nil and formatPartsAsPath(ArrayUtil.slice(parts, 0, commandPath:size())) == commandPath:toString() then
|
|
161
|
-
-- The current path still leads to the command, so it's valid
|
|
162
|
-
atCommand = true
|
|
163
|
-
elseif api.registry:getCommandByString(formatPartsAsPath(parts)) ~= nil then
|
|
164
|
-
atCommand = true
|
|
165
|
-
commandPath = ImmutableRegistryPath.new(parts)
|
|
166
|
-
else
|
|
167
|
-
local currentPath = RegistryPath:empty()
|
|
168
|
-
for _, part in parts do
|
|
169
|
-
currentPath:append(part)
|
|
170
|
-
if api.registry:getCommand(currentPath) ~= nil then
|
|
171
|
-
atCommand = true
|
|
172
|
-
break
|
|
173
|
-
end
|
|
174
|
-
if #api.registry:getChildPaths(currentPath) == 0 then
|
|
175
|
-
atCommand = false
|
|
176
|
-
break
|
|
177
|
-
end
|
|
178
|
-
end
|
|
179
|
-
commandPath = ImmutableRegistryPath:fromPath(currentPath)
|
|
180
|
-
end
|
|
181
|
-
if not atCommand and store:getState().command.path ~= nil then
|
|
182
|
-
store.setCommand(nil)
|
|
183
|
-
store:flush()
|
|
184
|
-
elseif atCommand and commandPath ~= store:getState().command.path then
|
|
185
|
-
store.setCommand(commandPath)
|
|
186
|
-
store:flush()
|
|
187
|
-
end
|
|
188
|
-
local _result
|
|
189
|
-
if commandPath ~= nil then
|
|
190
|
-
local _result_1 = api.registry:getCommand(commandPath)
|
|
191
|
-
if _result_1 ~= nil then
|
|
192
|
-
_result_1 = _result_1.options
|
|
193
|
-
end
|
|
194
|
-
_result = _result_1
|
|
195
|
-
else
|
|
196
|
-
_result = nil
|
|
197
|
-
end
|
|
198
|
-
local command = _result
|
|
199
|
-
if commandPath ~= nil and command ~= nil then
|
|
200
|
-
store.setTextValid(checkMissingArgs(commandPath, command) == nil)
|
|
201
|
-
else
|
|
202
|
-
store.setTextValid(false)
|
|
203
|
-
end
|
|
204
|
-
-- Update suggestions
|
|
205
|
-
local showArgs = atCommand and (atNextPart or (commandPath ~= nil and #parts > commandPath:size()))
|
|
206
|
-
local _result_1
|
|
207
|
-
if showArgs and command ~= nil then
|
|
208
|
-
local _result_2 = command.arguments
|
|
209
|
-
if _result_2 ~= nil then
|
|
210
|
-
_result_2 = #_result_2
|
|
211
|
-
end
|
|
212
|
-
local _condition = _result_2
|
|
213
|
-
if _condition == nil then
|
|
214
|
-
_condition = 0
|
|
215
|
-
end
|
|
216
|
-
_result_1 = _condition
|
|
217
|
-
else
|
|
218
|
-
_result_1 = 0
|
|
219
|
-
end
|
|
220
|
-
local argCount = _result_1
|
|
221
|
-
local currentTextPart = if not atNextPart then parts[#parts] else nil
|
|
222
|
-
local suggestion
|
|
223
|
-
if argCount == 0 then
|
|
224
|
-
local parentPath = if atNextPart then commandPath elseif commandPath:size() ~= 1 then commandPath:parent() else nil
|
|
225
|
-
suggestion = getCommandSuggestion(api.registry, parentPath, currentTextPart)
|
|
226
|
-
elseif commandPath ~= nil then
|
|
227
|
-
-- Handle argument suggestions
|
|
228
|
-
local argIndex = #parts - commandPath:size() - (if atNextPart then 0 else 1)
|
|
229
|
-
if argIndex >= argCount then
|
|
230
|
-
return nil
|
|
231
|
-
end
|
|
232
|
-
store.setArgIndex(argIndex)
|
|
233
|
-
suggestion = getArgumentSuggestion(api.registry, commandPath, argIndex, currentTextPart)
|
|
234
|
-
end
|
|
235
|
-
store.setSuggestion(suggestion)
|
|
236
|
-
end,
|
|
237
|
-
onSubmit = function(text)
|
|
238
|
-
local storeState = store:getState()
|
|
239
|
-
local commandPath = storeState.command.path
|
|
240
|
-
local command = if commandPath ~= nil then api.registry:getCommand(commandPath) else nil
|
|
241
|
-
if commandPath == nil or command == nil then
|
|
242
|
-
api.dispatcher:addHistoryEntry({
|
|
243
|
-
success = false,
|
|
244
|
-
text = "Command not found.",
|
|
245
|
-
sentAt = os.time(),
|
|
246
|
-
})
|
|
247
|
-
return nil
|
|
248
|
-
end
|
|
249
|
-
local argCheckMessage = checkMissingArgs(commandPath, command.options)
|
|
250
|
-
if argCheckMessage ~= nil then
|
|
251
|
-
api.dispatcher:addHistoryEntry({
|
|
252
|
-
success = false,
|
|
253
|
-
text = argCheckMessage,
|
|
254
|
-
sentAt = os.time(),
|
|
255
|
-
})
|
|
256
|
-
return nil
|
|
257
|
-
end
|
|
258
|
-
local args = ArrayUtil.slice(storeState.text.parts, commandPath:size())
|
|
259
|
-
api.dispatcher:run(commandPath, args)
|
|
260
|
-
end,
|
|
261
|
-
}))
|
|
262
|
-
end
|
|
263
|
-
return {
|
|
264
|
-
TerminalWindow = TerminalWindow,
|
|
265
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export default function Terminal(): JSX.Element;
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
-- Compiled with roblox-ts v2.3.0-dev-26ec859
|
|
2
|
-
local TS = _G[script]
|
|
3
|
-
local _react = TS.import(script, TS.getModule(script, "@rbxts", "react"))
|
|
4
|
-
local React = _react
|
|
5
|
-
local useContext = _react.useContext
|
|
6
|
-
local GuiService = TS.import(script, TS.getModule(script, "@rbxts", "services")).GuiService
|
|
7
|
-
local usePx = TS.import(script, script.Parent.Parent, "hooks", "use-px").usePx
|
|
8
|
-
local OptionsContext = TS.import(script, script.Parent.Parent, "providers", "options-provider").OptionsContext
|
|
9
|
-
local Suggestions = TS.import(script, script.Parent, "suggestions").Suggestions
|
|
10
|
-
local TerminalWindow = TS.import(script, script.Parent, "terminal-window").TerminalWindow
|
|
11
|
-
local Group = TS.import(script, script.Parent, "ui", "group").Group
|
|
12
|
-
local function Terminal()
|
|
13
|
-
local px = usePx()
|
|
14
|
-
local options = useContext(OptionsContext)
|
|
15
|
-
return React.createElement(Group, {
|
|
16
|
-
anchorPoint = options.anchorPoint or Vector2.new(0, 0),
|
|
17
|
-
size = options.size or UDim2.new(0, px(1024), 1, 0),
|
|
18
|
-
position = options.position or UDim2.fromOffset(px(16), px(8) + (GuiService:GetGuiInset()).Y),
|
|
19
|
-
}, React.createElement(TerminalWindow), React.createElement(Suggestions), React.createElement("uilistlayout", {
|
|
20
|
-
Padding = UDim.new(0, px(8)),
|
|
21
|
-
SortOrder = "LayoutOrder",
|
|
22
|
-
}))
|
|
23
|
-
end
|
|
24
|
-
return {
|
|
25
|
-
default = Terminal,
|
|
26
|
-
}
|