@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.
Files changed (115) hide show
  1. package/README.md +29 -0
  2. package/out/app/centurion-app.d.ts +3 -0
  3. package/out/app/centurion-app.lua +92 -0
  4. package/out/app/index.d.ts +6 -1
  5. package/out/app/init.lua +57 -4
  6. package/out/components/history/history-line.d.ts +5 -5
  7. package/out/components/history/history-line.lua +51 -27
  8. package/out/components/history/history-list.d.ts +8 -12
  9. package/out/components/history/history-list.lua +41 -41
  10. package/out/components/index.d.ts +1 -0
  11. package/out/components/init.lua +3 -0
  12. package/out/components/suggestions/badge.d.ts +11 -11
  13. package/out/components/suggestions/badge.lua +14 -20
  14. package/out/components/suggestions/main-suggestion.d.ts +6 -8
  15. package/out/components/suggestions/main-suggestion.lua +153 -143
  16. package/out/components/suggestions/suggestion-list.d.ts +5 -5
  17. package/out/components/suggestions/suggestion-list.lua +70 -49
  18. package/out/components/suggestions/suggestions.d.ts +2 -1
  19. package/out/components/suggestions/suggestions.lua +41 -50
  20. package/out/components/suggestions/util.d.ts +2 -2
  21. package/out/components/suggestions/util.lua +1 -0
  22. package/out/components/terminal/index.d.ts +1 -0
  23. package/out/{store/history → components/terminal}/init.lua +1 -1
  24. package/out/components/terminal/terminal-text-field.d.ts +11 -0
  25. package/out/components/terminal/terminal-text-field.lua +319 -0
  26. package/out/components/terminal/terminal.d.ts +2 -0
  27. package/out/components/terminal/terminal.lua +240 -0
  28. package/out/components/ui/frame.d.ts +17 -18
  29. package/out/components/ui/frame.lua +8 -10
  30. package/out/components/ui/group.d.ts +13 -15
  31. package/out/components/ui/group.lua +6 -9
  32. package/out/components/ui/layer.d.ts +5 -5
  33. package/out/components/ui/layer.lua +3 -3
  34. package/out/components/ui/outline.d.ts +13 -12
  35. package/out/components/ui/outline.lua +64 -54
  36. package/out/components/ui/padding.d.ts +7 -7
  37. package/out/components/ui/padding.lua +2 -2
  38. package/out/components/ui/scrolling-frame.d.ts +11 -12
  39. package/out/components/ui/scrolling-frame.lua +4 -9
  40. package/out/components/ui/text-field.d.ts +10 -9
  41. package/out/components/ui/text-field.lua +15 -13
  42. package/out/components/ui/text.d.ts +16 -16
  43. package/out/components/ui/text.lua +39 -38
  44. package/out/constants/springs.lua +1 -1
  45. package/out/hooks/use-api.d.ts +3 -0
  46. package/out/hooks/use-api.lua +18 -0
  47. package/out/hooks/use-atom.d.ts +2 -0
  48. package/out/hooks/use-atom.lua +17 -0
  49. package/out/hooks/use-debounce-source.d.ts +11 -0
  50. package/out/hooks/use-debounce-source.lua +27 -0
  51. package/out/hooks/use-event.d.ts +14 -0
  52. package/out/hooks/use-event.lua +58 -0
  53. package/out/hooks/use-history.d.ts +2 -0
  54. package/out/hooks/use-history.lua +56 -0
  55. package/out/hooks/use-motion.d.ts +4 -4
  56. package/out/hooks/use-motion.lua +11 -16
  57. package/out/hooks/use-px.d.ts +13 -1
  58. package/out/hooks/use-px.lua +52 -39
  59. package/out/store.d.ts +14 -0
  60. package/out/store.lua +44 -0
  61. package/out/types.d.ts +7 -4
  62. package/out/util/argument.d.ts +2 -1
  63. package/out/util/argument.lua +25 -0
  64. package/out/util/suggestion.d.ts +2 -2
  65. package/out/util/suggestion.lua +9 -14
  66. package/package.json +14 -14
  67. package/out/app/app.d.ts +0 -6
  68. package/out/app/app.lua +0 -83
  69. package/out/app/terminal-app.d.ts +0 -1
  70. package/out/app/terminal-app.lua +0 -61
  71. package/out/components/terminal-text-field.d.ts +0 -11
  72. package/out/components/terminal-text-field.lua +0 -289
  73. package/out/components/terminal-window.d.ts +0 -1
  74. package/out/components/terminal-window.lua +0 -265
  75. package/out/components/terminal.d.ts +0 -1
  76. package/out/components/terminal.lua +0 -26
  77. package/out/components/ui/shortcut-group.d.ts +0 -6
  78. package/out/components/ui/shortcut-group.lua +0 -100
  79. package/out/hooks/use-store.d.ts +0 -3
  80. package/out/hooks/use-store.lua +0 -7
  81. package/out/providers/api-provider.d.ts +0 -8
  82. package/out/providers/api-provider.lua +0 -17
  83. package/out/providers/options-provider.d.ts +0 -13
  84. package/out/providers/options-provider.lua +0 -39
  85. package/out/providers/root-provider.d.ts +0 -11
  86. package/out/providers/root-provider.lua +0 -24
  87. package/out/store/app/app-selectors.d.ts +0 -2
  88. package/out/store/app/app-selectors.lua +0 -7
  89. package/out/store/app/app-slice.d.ts +0 -8
  90. package/out/store/app/app-slice.lua +0 -17
  91. package/out/store/app/index.d.ts +0 -2
  92. package/out/store/app/init.lua +0 -10
  93. package/out/store/command/command-selectors.d.ts +0 -2
  94. package/out/store/command/command-selectors.lua +0 -7
  95. package/out/store/command/command-slice.d.ts +0 -15
  96. package/out/store/command/command-slice.lua +0 -21
  97. package/out/store/command/index.d.ts +0 -2
  98. package/out/store/command/init.lua +0 -10
  99. package/out/store/history/history-slice.d.ts +0 -11
  100. package/out/store/history/history-slice.lua +0 -52
  101. package/out/store/history/index.d.ts +0 -1
  102. package/out/store/index.d.ts +0 -46
  103. package/out/store/init.lua +0 -18
  104. package/out/store/suggestion/index.d.ts +0 -2
  105. package/out/store/suggestion/init.lua +0 -10
  106. package/out/store/suggestion/suggestion-selectors.d.ts +0 -2
  107. package/out/store/suggestion/suggestion-selectors.lua +0 -7
  108. package/out/store/suggestion/suggestion-slice.d.ts +0 -9
  109. package/out/store/suggestion/suggestion-slice.lua +0 -15
  110. package/out/store/text/index.d.ts +0 -2
  111. package/out/store/text/init.lua +0 -10
  112. package/out/store/text/text-selectors.d.ts +0 -3
  113. package/out/store/text/text-selectors.lua +0 -11
  114. package/out/store/text/text-slice.d.ts +0 -20
  115. package/out/store/text/text-slice.lua +0 -29
@@ -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
- }
@@ -1,6 +0,0 @@
1
- import { CommandShortcut } from "@rbxts/centurion";
2
- interface ShortcutGroupProps {
3
- shortcuts?: CommandShortcut[];
4
- }
5
- export declare function ShortcutGroup(props: ShortcutGroupProps): JSX.Element;
6
- export {};