@@ -10,6 +10,7 @@ import Dropdown from 'components/Dropdown/Dropdown.react';
1010import Field from 'components/Field/Field.react' ;
1111import FileInput from 'components/FileInput/FileInput.react' ;
1212import GeoPointInput from 'components/GeoPointInput/GeoPointInput.react' ;
13+ import Icon from 'components/Icon/Icon.react' ;
1314import Label from 'components/Label/Label.react' ;
1415import Modal from 'components/Modal/Modal.react' ;
1516import NonPrintableHighlighter , { hasNonPrintableChars , getNonPrintableCharsFromJson , hasNonAlphanumericChars , getNonAlphanumericCharsFromJson , getRegexValidation , getRegexValidationFromJson } from 'components/NonPrintableHighlighter/NonPrintableHighlighter.react' ;
@@ -18,6 +19,8 @@ import Parse from 'parse';
1819import React from 'react' ;
1920import TextInput from 'components/TextInput/TextInput.react' ;
2021import Toggle from 'components/Toggle/Toggle.react' ;
22+ import Popover from 'components/Popover/Popover.react' ;
23+ import Position from 'lib/Position' ;
2124import Button from 'components/Button/Button.react' ;
2225import JsonEditor from 'components/JsonEditor/JsonEditor.react' ;
2326import validateNumeric from 'lib/validateNumeric' ;
@@ -120,6 +123,7 @@ export default class ConfigDialog extends React.Component {
120123
121124 constructor ( props ) {
122125 super ( ) ;
126+ this . optionsRef = React . createRef ( ) ;
123127 this . state = {
124128 value : null ,
125129 type : 'String' ,
@@ -129,6 +133,7 @@ export default class ConfigDialog extends React.Component {
129133 wordWrap : false ,
130134 showDiff : false ,
131135 confirmOverride : false ,
136+ optionsMenuOpen : false ,
132137 error : null ,
133138 syntaxColors : null ,
134139 } ;
@@ -335,6 +340,14 @@ export default class ConfigDialog extends React.Component {
335340 } ) ;
336341 }
337342
343+ updateOptionsMenuPos = ( ) => {
344+ if ( this . optionsRef . current ) {
345+ const pos = Position . inWindow ( this . optionsRef . current ) ;
346+ pos . y -= 4 ;
347+ this . setState ( { optionsMenuPos : pos } ) ;
348+ }
349+ } ;
350+
338351 formatValue ( ) {
339352 const { value, error } = ConfigDialog . formatJSON ( this . state . value ) ;
340353 this . setState ( { value, error } ) ;
@@ -566,37 +579,58 @@ export default class ConfigDialog extends React.Component {
566579 onClick = { this . compactValue . bind ( this ) }
567580 disabled = { ! this . canFormatValue ( ) }
568581 />
569- < label style = { { display : 'flex' , alignItems : 'center' , gap : '4px' , cursor : 'pointer' } } >
570- < Toggle
571- type = { Toggle . Types . HIDE_LABELS }
572- value = { this . state . wordWrap }
573- onChange = { wordWrap => this . setState ( { wordWrap } ) }
574- additionalStyles = { { margin : '0px' } }
575- colorLeft = "#cbcbcb"
576- colorRight = "#00db7c"
577- />
578- < span style = { { color : this . state . wordWrap ? '#333' : '#999' } } > Wrap</ span >
579- </ label >
580582 { this . state . error && (
581583 < span style = { { color : '#d73a49' , fontSize : '13px' } } > { this . state . error } </ span >
582584 ) }
583585 </ >
584586 ) }
585- { isDiffableType && isExistingParam && (
586- < label style = { { display : 'flex' , alignItems : 'center' , gap : '4px' , cursor : 'pointer' } } >
587- < Toggle
588- type = { Toggle . Types . HIDE_LABELS }
589- value = { this . state . showDiff }
590- onChange = { showDiff => this . setState ( { showDiff } ) }
591- additionalStyles = { { margin : '0px' } }
592- colorLeft = "#cbcbcb"
593- colorRight = "#00db7c"
587+ { ( isJsonType || ( isDiffableType && isExistingParam ) ) && (
588+ < div ref = { this . optionsRef } >
589+ < Button
590+ value = "Options ▾"
591+ onClick = { ( ) => {
592+ const node = this . optionsRef . current ;
593+ const pos = Position . inWindow ( node ) ;
594+ pos . y -= 4 ; // small gap above button
595+ this . setState ( { optionsMenuOpen : ! this . state . optionsMenuOpen , optionsMenuPos : pos } ) ;
596+ } }
594597 />
595- < span style = { { color : this . state . showDiff ? '#333' : '#999' } } > Diff</ span >
596- </ label >
598+ { this . state . optionsMenuOpen && this . state . optionsMenuPos && (
599+ < Popover
600+ fixed = { true }
601+ position = { this . state . optionsMenuPos }
602+ onExternalClick = { ( ) => { document . activeElement ?. blur ( ) ; this . setState ( { optionsMenuOpen : false } ) ; } }
603+ >
604+ < div style = { { background : '#fff' , border : '1px solid #e1e4e8' , borderRadius : '4px' , boxShadow : '0 3px 12px rgba(0,0,0,0.15)' , padding : '4px 0' , minWidth : '130px' , transform : 'translateY(-100%)' } } >
605+ { isJsonType && (
606+ < div
607+ onClick = { ( ) => { document . activeElement ?. blur ( ) ; this . setState ( { wordWrap : ! this . state . wordWrap , optionsMenuOpen : false } ) ; } }
608+ style = { { display : 'flex' , alignItems : 'center' , padding : '8px 12px' , cursor : 'pointer' , fontSize : '14px' , color : '#333' , gap : '8px' } }
609+ onMouseEnter = { e => e . currentTarget . style . background = '#f6f8fa' }
610+ onMouseLeave = { e => e . currentTarget . style . background = 'transparent' }
611+ >
612+ < span style = { { width : '12px' , display : 'inline-block' } } > { this . state . wordWrap && < Icon name = "check" width = { 12 } height = { 12 } fill = "#00db7c" /> } </ span >
613+ < span > Word wrap</ span >
614+ </ div >
615+ ) }
616+ { isDiffableType && isExistingParam && (
617+ < div
618+ onClick = { ( ) => { document . activeElement ?. blur ( ) ; this . setState ( { showDiff : ! this . state . showDiff , optionsMenuOpen : false } ) ; } }
619+ style = { { display : 'flex' , alignItems : 'center' , padding : '8px 12px' , cursor : 'pointer' , fontSize : '14px' , color : '#333' , gap : '8px' } }
620+ onMouseEnter = { e => e . currentTarget . style . background = '#f6f8fa' }
621+ onMouseLeave = { e => e . currentTarget . style . background = 'transparent' }
622+ >
623+ < span style = { { width : '12px' , display : 'inline-block' } } > { this . state . showDiff && < Icon name = "check" width = { 12 } height = { 12 } fill = "#00db7c" /> } </ span >
624+ < span > Diff view</ span >
625+ </ div >
626+ ) }
627+ </ div >
628+ </ Popover >
629+ ) }
630+ </ div >
597631 ) }
598632 </ div >
599- < div style = { { display : 'flex' , gap : '12px' , marginLeft : '20px' } } >
633+ < div style = { { display : 'flex' , gap : '12px' } } >
600634 < Button value = "Cancel" onClick = { this . props . onCancel } />
601635 < Button
602636 primary = { true }
0 commit comments