0
0
mirror of https://github.com/naturalcrit/homebrewery.git synced 2026-01-08 07:32:40 +00:00

create combobox

This commit is contained in:
Gazook89
2022-11-23 22:34:32 -06:00
parent 1818ea1e3b
commit 678c1fb3d8
4 changed files with 118 additions and 80 deletions

View File

@@ -4,65 +4,90 @@ const _ = require('lodash');
const cx = require('classnames'); const cx = require('classnames');
require('./combobox.less'); require('./combobox.less');
const Dropdown = { const Combobox = createClass({
combo : createClass({ displayName : 'Combobox',
displayName : 'Dropdown.combo', getDefaultProps : function() {
getDefaultProps : function() { return {
return { trigger : 'hover',
trigger : 'hover' default : ''
}; };
}, },
getInitialState : function() { getInitialState : function() {
return { return {
showDropdown : false showDropdown : false,
}; value : '',
}, options : [...this.props.options]
componentDidMount : function() { };
if(this.props.trigger == 'click') },
document.addEventListener('click', this.handleClickOutside); componentDidMount : function() {
}, if(this.props.trigger == 'click')
componentWillUnmount : function() { document.addEventListener('click', this.handleClickOutside);
if(this.props.trigger == 'click') this.setState({
document.removeEventListener('click', this.handleClickOutside); value : this.props.default
}, });
handleClickOutside : function(e){ },
// Close dropdown when clicked outside componentWillUnmount : function() {
if(this.refs.dropdown && !this.refs.dropdown.contains(e.target)) { if(this.props.trigger == 'click')
this.handleDropdown(false); document.removeEventListener('click', this.handleClickOutside);
} },
}, handleClickOutside : function(e){
handleDropdown : function(show){ // Close dropdown when clicked outside
this.setState({ if(this.refs.dropdown && !this.refs.dropdown.contains(e.target)) {
showDropdown : show this.handleDropdown(false);
});
},
renderDropdown : function(dropdownChildren){
if(!this.state.showDropdown) return null;
return (
<div className='dropdown-options'>
{dropdownChildren}
</div>
);
},
render : function () {
const dropdownChildren = React.Children.map(this.props.children, (child, i)=>{
// Ignore the first child
if(i < 1) return;
return child;
});
return (
<div className={`dropdown-container ${this.props.className}`}
ref='dropdown'
onMouseEnter={this.props.trigger == 'hover' ? ()=>{this.handleDropdown(true);} : undefined}
onClick= {this.props.trigger == 'click' ? ()=>{this.handleDropdown(true);} : undefined}
onMouseLeave={this.props.trigger == 'hover' ? ()=>{this.handleDropdown(false);} : undefined}>
{this.props.children[0] || this.props.children /*children is not an array when only one child*/}
{this.renderDropdown(dropdownChildren)}
</div>
);
} }
}) },
}; handleDropdown : function(show){
this.setState({
showDropdown : show
});
},
handleInput : function(e){
e.persist();
this.setState({
value : e.target.value
}, ()=>{
// const event = new Event('entry');
// console.log(eevent);
this.props.onEntry(e);
});
},
handleOption : function(e){
this.setState({
value : e.currentTarget.getAttribute('data-value')
}, ()=>{this.props.onSelect(this.state.value);});
;
},
renderTextInput : function(){
return (
<div className='dropdown-input item'
onMouseEnter={this.props.trigger == 'hover' ? ()=>{this.handleDropdown(true);} : undefined}
onClick= {this.props.trigger == 'click' ? ()=>{this.handleDropdown(true);} : undefined}>
<input type='text' onChange={(e)=>this.handleInput(e)} value={this.state.value || ''} />
</div>
);
},
renderDropdown : function(dropdownChildren){
if(!this.state.showDropdown) return null;
return (
<div className='dropdown-options'>
{dropdownChildren}
</div>
);
},
render : function () {
const dropdownChildren = this.state.options.map((child, i)=>{
const clone = React.cloneElement(child, { onClick: (e)=>this.handleOption(e) });
return clone;
});
return (
<div className={`dropdown-container ${this.props.className}`}
ref='dropdown'
onMouseLeave={this.props.trigger == 'hover' ? ()=>{this.handleDropdown(false);} : undefined}>
{this.renderTextInput()}
{this.renderDropdown(dropdownChildren)}
</div>
);
}
});
module.exports = Dropdown; module.exports = Combobox;

View File

@@ -5,13 +5,23 @@
background-color: rgb(227, 227, 227); background-color: rgb(227, 227, 227);
z-index: 100; z-index: 100;
width: 100%; width: 100%;
border: 1px solid #444; border: 1px solid gray;
.item { .item {
font-size: 12px; position:relative;
font-size: 14px;
font-family: OpenSans; font-family: OpenSans;
padding: 5px; padding: 5px;
cursor: default;
&:hover { &:hover {
filter: brightness(120%); filter: brightness(120%);
background-color: rgb(163, 163, 163);
}
.detail {
width:100%;
text-align: right;
color: rgb(124, 124, 124);
font-style:italic;
font-size: 12px;
} }
} }

View File

@@ -6,7 +6,7 @@ const _ = require('lodash');
const cx = require('classnames'); const cx = require('classnames');
const request = require('superagent'); const request = require('superagent');
const Nav = require('naturalcrit/nav/nav.jsx'); const Nav = require('naturalcrit/nav/nav.jsx');
const Dropdown = require('client/components/combobox.jsx'); const Combobox = require('client/components/combobox.jsx');
const StringArrayEditor = require('../stringArrayEditor/stringArrayEditor.jsx'); const StringArrayEditor = require('../stringArrayEditor/stringArrayEditor.jsx');
const Themes = require('themes/themes.json'); const Themes = require('themes/themes.json');
@@ -109,8 +109,8 @@ const MetadataEditor = createClass({
this.props.onChange(this.props.metadata); this.props.onChange(this.props.metadata);
}, },
handleLanguage : function(language){ handleLanguage : function(languageCode){
this.props.metadata.lang = language; this.props.metadata.lang = languageCode;
this.props.onChange(this.props.metadata); this.props.onChange(this.props.metadata);
}, },
@@ -197,20 +197,20 @@ const MetadataEditor = createClass({
if(this.props.metadata.renderer == 'legacy') { if(this.props.metadata.renderer == 'legacy') {
dropdown = dropdown =
<Dropdown.combo className='disabled' trigger='disabled'> <Combobox className='disabled' trigger='disabled'>
<div> <div>
{`Themes are not supported in the Legacy Renderer`} <i className='fas fa-caret-down'></i> {`Themes are not supported in the Legacy Renderer`} <i className='fas fa-caret-down'></i>
</div> </div>
</Dropdown.combo>; </Combobox>;
} else { } else {
dropdown = dropdown =
<Dropdown.combo trigger='click'> <Combobox trigger='click'>
<div> <div>
{`${_.upperFirst(currentTheme.renderer)} : ${currentTheme.name}`} <i className='fas fa-caret-down'></i> {`${_.upperFirst(currentTheme.renderer)} : ${currentTheme.name}`} <i className='fas fa-caret-down'></i>
</div> </div>
{/*listThemes('Legacy')*/} {/*listThemes('Legacy')*/}
{listThemes('V3')} {listThemes('V3')}
</Dropdown.combo>; </Combobox>;
} }
return <div className='field themes'> return <div className='field themes'>
@@ -257,22 +257,22 @@ const MetadataEditor = createClass({
const listLanguages = ()=>{ const listLanguages = ()=>{
return _.map(langCodes.sort(), (code, index)=>{ return _.map(langCodes.sort(), (code, index)=>{
const languageNames = new Intl.DisplayNames([code], { type: 'language' }); const languageNames = new Intl.DisplayNames([code], { type: 'language' });
return <div className='item' title={''} key={index} onClick={()=>this.handleLanguage(code)}>{`${code}`}</div>; return <div className='item' title={''} key={`${index}`} data-value={`${code}`}>
{`${code}`}
<div className='detail'>{`${languageNames.of(code)}`}</div>
</div>;
}); });
}; };
return <div className='field language'> return <div className='field language'>
<label>language</label> <label>language</label>
<Dropdown.combo trigger='hover'> <Combobox trigger='click'
<div className='item'> default={this.props.metadata.lang || ''}
<input type='text' onSelect={(value)=>this.handleLanguage(value)}
defaultValue={this.props.metadata.lang || ''} onEntry={(e)=>{this.handleFieldChange('lang', e);}}
onChange={(e)=>this.handleFieldChange('lang', e)} options={listLanguages()}>
placeholder='en' </Combobox>
/>
</div>
{listLanguages()}
</Dropdown.combo>
</div>; </div>;
}, },

View File

@@ -52,6 +52,9 @@
} }
input[type='text'], textarea { input[type='text'], textarea {
border : 1px solid gray; border : 1px solid gray;
&:focus {
outline: 1px solid #444;
}
} }
&.thumbnail{ &.thumbnail{
height : 1.4em; height : 1.4em;