@@ -12,12 +12,21 @@ import { default as Space } from "antd/es/space";
12
12
import { default as Flex } from "antd/es/flex" ;
13
13
import type { InputRef } from 'antd' ;
14
14
import { default as DownOutlined } from "@ant-design/icons/DownOutlined" ;
15
- import { BaseSection } from "lowcoder-design" ;
15
+ import { BaseSection , Dropdown } from "lowcoder-design" ;
16
16
import { EditorContext } from "comps/editorState" ;
17
17
import { message } from "antd" ;
18
18
import { CustomDropdown } from "./styled" ;
19
- import { generateComponentActionItems , getComponentCategories } from "./utils" ;
19
+ import {
20
+ generateComponentActionItems ,
21
+ getComponentCategories ,
22
+ getEditorComponentInfo ,
23
+ getLayoutItemsOrder
24
+ } from "./utils" ;
20
25
import { actionRegistry , getAllActionItems } from "./actionConfigs" ;
26
+ import { getThemeList } from "@lowcoder-ee/redux/selectors/commonSettingSelectors" ;
27
+ import { useSelector } from "react-redux" ;
28
+ import { ActionOptions } from "comps/controls/actionSelector/actionSelectorControl" ;
29
+ import { eventToShortcut , readableShortcut } from "util/keyUtils" ;
21
30
22
31
export function ActionInputSection ( ) {
23
32
const [ actionValue , setActionValue ] = useState < string > ( "" ) ;
@@ -31,8 +40,22 @@ export function ActionInputSection() {
31
40
const [ showStylingInput , setShowStylingInput ] = useState < boolean > ( false ) ;
32
41
const [ selectedEditorComponent , setSelectedEditorComponent ] = useState < string | null > ( null ) ;
33
42
const [ validationError , setValidationError ] = useState < string | null > ( null ) ;
43
+ const [ showDynamicLayoutDropdown , setShowDynamicLayoutDropdown ] = useState < boolean > ( false ) ;
44
+ const [ selectedDynamicLayoutIndex , setSelectedDynamicLayoutIndex ] = useState < string | null > ( null ) ;
45
+ const [ showThemeDropdown , setShowThemeDropdown ] = useState < boolean > ( false ) ;
46
+ const [ selectedTheme , setSelectedTheme ] = useState < string | null > ( null ) ;
47
+ const [ showCustomShortcutsActionDropdown , setShowCustomShortcutsActionDropdown ] = useState < boolean > ( false ) ;
48
+ const [ selectedCustomShortcutAction , setSelectedCustomShortcutAction ] = useState < string | null > ( null ) ;
34
49
const inputRef = useRef < InputRef > ( null ) ;
35
50
const editorState = useContext ( EditorContext ) ;
51
+ const themeList = useSelector ( getThemeList ) || [ ] ;
52
+
53
+ const THEME_OPTIONS = useMemo ( ( ) => {
54
+ return themeList . map ( ( theme ) => ( {
55
+ label : theme . name ,
56
+ value : theme . id + "" ,
57
+ } ) ) ;
58
+ } , [ themeList ] ) ;
36
59
37
60
const categories = useMemo ( ( ) => {
38
61
return getComponentCategories ( ) ;
@@ -56,6 +79,25 @@ export function ActionInputSection() {
56
79
} ) ) ;
57
80
} , [ editorState ] ) ;
58
81
82
+ const simpleLayoutItems = useMemo ( ( ) => {
83
+ if ( ! editorComponents ) return [ ] ;
84
+
85
+ const editorComponentInfo = getEditorComponentInfo ( editorState ) ;
86
+ if ( ! editorComponentInfo ) return [ ] ;
87
+
88
+ const currentLayout = editorComponentInfo . currentLayout ;
89
+ const items = editorComponentInfo . items ;
90
+
91
+ return Object . keys ( currentLayout ) . map ( ( key ) => {
92
+ const item = items ? items [ key ] : null ;
93
+ const componentName = item ? ( item as any ) . children . name . getView ( ) : key ;
94
+ return {
95
+ label : componentName ,
96
+ key : componentName
97
+ } ;
98
+ } ) ;
99
+ } , [ editorState ] ) ;
100
+
59
101
const currentAction = useMemo ( ( ) => {
60
102
return selectedActionKey ? actionRegistry . get ( selectedActionKey ) : null ;
61
103
} , [ selectedActionKey ] ) ;
@@ -81,8 +123,14 @@ export function ActionInputSection() {
81
123
setSelectedEditorComponent ( null ) ;
82
124
setIsNestedComponent ( false ) ;
83
125
setSelectedNestComponent ( null ) ;
126
+ setShowDynamicLayoutDropdown ( false ) ;
84
127
setActionValue ( "" ) ;
85
-
128
+ setSelectedDynamicLayoutIndex ( null ) ;
129
+ setShowThemeDropdown ( false ) ;
130
+ setSelectedTheme ( null ) ;
131
+ setShowCustomShortcutsActionDropdown ( false ) ;
132
+ setSelectedCustomShortcutAction ( null ) ;
133
+
86
134
if ( action . requiresComponentSelection ) {
87
135
setShowComponentDropdown ( true ) ;
88
136
setPlaceholderText ( "Select a component to add" ) ;
@@ -103,6 +151,15 @@ export function ActionInputSection() {
103
151
if ( action . isNested ) {
104
152
setIsNestedComponent ( true ) ;
105
153
}
154
+ if ( action . dynamicLayout ) {
155
+ setShowDynamicLayoutDropdown ( true ) ;
156
+ }
157
+ if ( action . isTheme ) {
158
+ setShowThemeDropdown ( true ) ;
159
+ }
160
+ if ( action . isCustomShortcuts ) {
161
+ setShowCustomShortcutsActionDropdown ( true ) ;
162
+ }
106
163
} , [ ] ) ;
107
164
108
165
const handleComponentSelection = useCallback ( ( key : string ) => {
@@ -168,13 +225,26 @@ export function ActionInputSection() {
168
225
return ;
169
226
}
170
227
228
+ if ( currentAction . isTheme && ! selectedTheme ) {
229
+ message . error ( 'Please select a theme' ) ;
230
+ return ;
231
+ }
232
+
233
+ if ( currentAction . isCustomShortcuts && ! selectedCustomShortcutAction ) {
234
+ message . error ( 'Please select a custom shortcut action' ) ;
235
+ return ;
236
+ }
237
+
171
238
try {
172
239
await currentAction . execute ( {
173
240
actionKey : selectedActionKey ,
174
241
actionValue,
175
242
selectedComponent,
176
243
selectedEditorComponent,
177
244
selectedNestComponent,
245
+ selectedDynamicLayoutIndex,
246
+ selectedTheme,
247
+ selectedCustomShortcutAction,
178
248
editorState
179
249
} ) ;
180
250
@@ -189,7 +259,12 @@ export function ActionInputSection() {
189
259
setValidationError ( null ) ;
190
260
setIsNestedComponent ( false ) ;
191
261
setSelectedNestComponent ( null ) ;
192
-
262
+ setShowDynamicLayoutDropdown ( false ) ;
263
+ setSelectedDynamicLayoutIndex ( null ) ;
264
+ setShowThemeDropdown ( false ) ;
265
+ setSelectedTheme ( null ) ;
266
+ setShowCustomShortcutsActionDropdown ( false ) ;
267
+ setSelectedCustomShortcutAction ( null ) ;
193
268
} catch ( error ) {
194
269
console . error ( 'Error executing action:' , error ) ;
195
270
message . error ( 'Failed to execute action. Please try again.' ) ;
@@ -200,6 +275,9 @@ export function ActionInputSection() {
200
275
selectedComponent ,
201
276
selectedEditorComponent ,
202
277
selectedNestComponent ,
278
+ selectedDynamicLayoutIndex ,
279
+ selectedTheme ,
280
+ selectedCustomShortcutAction ,
203
281
editorState ,
204
282
currentAction ,
205
283
validateInput
@@ -213,7 +291,16 @@ export function ActionInputSection() {
213
291
if ( currentAction . requiresInput && ! actionValue . trim ( ) ) return true ;
214
292
215
293
return false ;
216
- } , [ selectedActionKey , currentAction , selectedComponent , selectedEditorComponent , actionValue ] ) ;
294
+ } , [
295
+ selectedActionKey ,
296
+ currentAction ,
297
+ selectedComponent ,
298
+ selectedEditorComponent ,
299
+ actionValue ,
300
+ selectedCustomShortcutAction ,
301
+ selectedTheme ,
302
+ selectedNestComponent
303
+ ] ) ;
217
304
218
305
const shouldShowInput = useMemo ( ( ) => {
219
306
if ( ! currentAction ) return false ;
@@ -299,7 +386,7 @@ export function ActionInputSection() {
299
386
popupRender = { ( ) => (
300
387
< Menu
301
388
items = { editorComponents }
302
- onClick = { ( { key } ) => {
389
+ onClick = { ( { key} ) => {
303
390
handleEditorComponentSelection ( key ) ;
304
391
} }
305
392
/>
@@ -314,24 +401,111 @@ export function ActionInputSection() {
314
401
</ CustomDropdown >
315
402
) }
316
403
317
- { shouldShowInput && (
318
- showStylingInput ? (
319
- < Input . TextArea
320
- ref = { inputRef }
321
- value = { actionValue }
322
- onChange = { handleInputChange }
323
- placeholder = { placeholderText }
324
- status = { validationError ? 'error' : undefined }
325
- autoSize = { { minRows : 1 } }
404
+ { showDynamicLayoutDropdown && (
405
+ < CustomDropdown
406
+ overlayStyle = { {
407
+ maxHeight : '400px' ,
408
+ overflow : 'auto' ,
409
+ zIndex : 9999
410
+ } }
411
+ popupRender = { ( ) => (
412
+ < Menu
413
+ items = { simpleLayoutItems }
414
+ onClick = { ( { key} ) => {
415
+ handleEditorComponentSelection ( key ) ;
416
+ } }
326
417
/>
327
- ) : (
418
+ ) }
419
+ >
420
+ < Button size = { "small" } >
421
+ < Space >
422
+ { selectedEditorComponent ? selectedEditorComponent : 'Layout' }
423
+ < DownOutlined />
424
+ </ Space >
425
+ </ Button >
426
+ </ CustomDropdown >
427
+ ) }
428
+
429
+ { showDynamicLayoutDropdown && (
430
+ < Dropdown
431
+ options = { getLayoutItemsOrder ( simpleLayoutItems ) }
432
+ onChange = { ( value ) => {
433
+ setSelectedDynamicLayoutIndex ( value ) ;
434
+ } }
435
+ >
436
+ < Button size = { "small" } >
437
+ < Space >
438
+ { selectedEditorComponent ? selectedEditorComponent : 'Layout' }
439
+ < DownOutlined />
440
+ </ Space >
441
+ </ Button >
442
+ </ Dropdown >
443
+ ) }
444
+
445
+ { showThemeDropdown && (
446
+ < Dropdown
447
+ options = { THEME_OPTIONS }
448
+ onChange = { ( value ) => {
449
+ setSelectedTheme ( value ) ;
450
+ } }
451
+ >
452
+ < Button size = { "small" } >
453
+ < Space >
454
+ { selectedTheme ? selectedTheme : 'Select Theme' }
455
+ </ Space >
456
+ </ Button >
457
+ </ Dropdown >
458
+ ) }
459
+
460
+ { showCustomShortcutsActionDropdown && (
461
+ < Dropdown
462
+ options = { ActionOptions }
463
+ onChange = { ( value ) => {
464
+ setSelectedCustomShortcutAction ( value ) ;
465
+ } }
466
+ >
467
+ < Button size = { "small" } >
468
+ < Space >
469
+ { selectedCustomShortcutAction ? selectedCustomShortcutAction : 'Select Action' }
470
+ </ Space >
471
+ </ Button >
472
+ </ Dropdown >
473
+ ) }
474
+
475
+ { shouldShowInput && (
476
+ currentAction ?. isCustomShortcuts ? (
328
477
< Input
329
478
ref = { inputRef }
330
- value = { actionValue }
331
- onChange = { handleInputChange }
479
+ value = { readableShortcut ( actionValue ) }
332
480
placeholder = { placeholderText }
333
481
status = { validationError ? 'error' : undefined }
482
+ onKeyDownCapture = { ( e ) => {
483
+ setActionValue ( eventToShortcut ( e ) ) ;
484
+ e . preventDefault ( ) ;
485
+ e . stopPropagation ( ) ;
486
+ } }
487
+ onChange = { ( ) => { } }
488
+ readOnly
334
489
/>
490
+ ) : (
491
+ showStylingInput ? (
492
+ < Input . TextArea
493
+ ref = { inputRef }
494
+ value = { actionValue }
495
+ onChange = { handleInputChange }
496
+ placeholder = { placeholderText }
497
+ status = { validationError ? 'error' : undefined }
498
+ autoSize = { { minRows : 1 } }
499
+ />
500
+ ) : (
501
+ < Input
502
+ ref = { inputRef }
503
+ value = { actionValue }
504
+ onChange = { handleInputChange }
505
+ placeholder = { placeholderText }
506
+ status = { validationError ? 'error' : undefined }
507
+ />
508
+ )
335
509
)
336
510
) }
337
511
0 commit comments