0
0
mirror of https://github.com/naturalcrit/homebrewery.git synced 2025-12-24 20:42:43 +00:00

Use ComboBox component for Theme Selector

This commit is contained in:
Trevor Buckner
2025-02-10 22:20:54 -05:00
parent c080e5b191
commit 1aed753911
2 changed files with 94 additions and 128 deletions

View File

@@ -49,12 +49,8 @@ const MetadataEditor = createClass({
},
getInitialState : function(){
mergedThemes = _.merge(Themes, this.props.userThemes);
return {
showThumbnail : true,
showThemeWritein : mergedThemes[this.props.metadata.renderer][this.props.metadata.theme] ? false : true,
lastThemePulldown : mergedThemes[this.props.metadata.renderer][this.props.metadata.theme] ? mergedThemes[this.props.metadata.renderer][this.props.metadata.theme].path : '',
lastThemeWriteIn : mergedThemes[this.props.metadata.renderer][this.props.metadata.theme] ? '' : this.props.metadata.theme
showThumbnail : true
};
},
@@ -64,15 +60,6 @@ const MetadataEditor = createClass({
});
},
toggleThemeWritein : function(){
if(!this.state.showThemeWritein) this.props.metadata.theme = this.state.lastThemeWriteIn;
else this.props.metadata.theme = this.state.lastThemePulldown;
this.props.onChange(this.props.metadata, 'theme');
this.setState({
showThemeWritein : !this.state.showThemeWritein
});
},
renderThumbnail : function(){
if(!this.state.showThumbnail) return;
return <img className='thumbnail-preview' src={this.props.metadata.thumbnail || homebreweryThumbnail}></img>;
@@ -128,21 +115,15 @@ const MetadataEditor = createClass({
handleTheme : function(theme){
this.props.metadata.renderer = theme.renderer;
this.props.metadata.theme = theme.path;
this.setState({
lastThemePulldown : theme.path
});
this.props.onChange(this.props.metadata, 'theme');
},
handleThemeWritein : function(e) {
this.props.metadata.renderer = 'V3';
this.props.metadata.theme = e.target.value;
this.setState({
lastThemeWriteIn : e.target.value
});
this.props.onChange(this.props.metadata, 'renderer');
this.props.onChange(this.props.metadata, 'theme');
},
@@ -224,12 +205,14 @@ const MetadataEditor = createClass({
renderThemeDropdown : function(){
if(!global.enable_themes) return;
const mergedThemes = _.merge(Themes, this.props.userThemes);
const listThemes = (renderer)=>{
return _.map(_.values(mergedThemes[renderer]), (theme)=>{
if(theme.path == this.props.metadata.shareId) return;
const preview = theme.thumbnail || `/themes/${theme.renderer}/${theme.path}/dropdownPreview.png`;
const texture = theme.thumbnail || `/themes/${theme.renderer}/${theme.path}/dropdownTexture.png`;
return <div className='item' key={`${renderer}_${theme.name}`} onClick={()=>this.handleTheme(theme)} title={''}>
return <div className='item' key={`${renderer}_${theme.name}`} value={`${theme.author ?? renderer} : ${theme.name}`} data={theme} title={''}>
{theme.author ?? renderer} : {theme.name}
<div className='texture-container'>
<img src={texture}/>
@@ -242,45 +225,45 @@ const MetadataEditor = createClass({
});
};
console.log(this.props.themeBundle);
const currentRenderer = this.props.metadata.renderer;
const currentTheme = mergedThemes[`${_.upperFirst(this.props.metadata.renderer)}`][this.props.metadata.theme]
?? { name: `${this.props.themeBundle?.path || ''}`, author: '!!!' };
?? { name: `${this.props.themeBundle?.name || ''}`, author: `${this.props.themeBundle?.author || ''}` };
let dropdown;
if(currentRenderer == 'legacy') {
dropdown =
<Nav.dropdown className='disabled value' trigger='disabled'>
<div> {`Themes are not supported in the Legacy Renderer`} <i className='fas fa-caret-down'></i> </div>
</Nav.dropdown>;
<div className='disabled value' trigger='disabled'>
<div> Themes are not supported in the Legacy Renderer </div>
</div>;
} else {
dropdown =
<Nav.dropdown className='value' trigger='click'>
<div> {currentTheme.author ?? _.upperFirst(currentRenderer)} : {currentTheme.name} <i className='fas fa-caret-down'></i> </div>
{listThemes(currentRenderer)}
</Nav.dropdown>;
<div className='value'>
<Combobox trigger='click'
className='themes-dropdown'
default={`${currentTheme.author ?? _.upperFirst(currentRenderer)} : ${currentTheme.name}`}
placeholder='Enter the Share URL or ID of any brew with the meta:theme tag'
onSelect={(value)=>this.handleTheme(value)}
onEntry={(e)=>{
e.target.setCustomValidity(''); //Clear the validation popup while typing
//debouncedHandleFieldChange('theme', e);
this.handleThemeWritein(e);
}}
options={listThemes(currentRenderer)}
autoSuggest={{
suggestMethod : 'includes',
clearAutoSuggestOnClick : true,
filterOn : ['value', 'title']
}}
/>
<small>Select from the list below (built-in themes and brews you have tagged "meta:theme"), or paste in the Share URL or Share ID of any brew.</small>
</div>;
}
return <div className='field themes'>
<label>theme</label>
{!this.state.showThemeWritein?dropdown:''}
<button className='display writeIn' onClick={this.toggleThemeWritein}>
{`${this.state.showThemeWritein ? 'Theme List' : 'Use Brew Theme'}`}
</button>
{this.renderThemeWritein()}
</div>;
},
renderThemeWritein : function(){
if(!this.state.showThemeWritein) return;
return <div>
<input type='text'
default=''
placeholder='Enter share id'
className='value'
defaultValue={this.state.lastThemeWriteIn || this.props.metadata.theme}
onChange={(e)=>this.handleThemeWritein(e)} />
<span class='userThemeName'>{`${this.state.lastThemeWriteIn ? this.props.themeBundle?.path || '' : ''}`}</span>
{dropdown}
</div>;
},
@@ -317,8 +300,7 @@ const MetadataEditor = createClass({
clearAutoSuggestOnClick : true,
filterOn : ['value', 'detail', 'title']
}}
>
</Combobox>
/>
<small>Sets the HTML Lang property for your brew. May affect hyphenation or spellcheck.</small>
</div>

View File

@@ -171,89 +171,73 @@
}
.themes.field {
.navDropdownContainer {
& .dropdown-container {
position : relative;
z-index : 100;
background-color : white;
&.disabled {
font-style : italic;
color : dimgray;
background-color : darkgray;
}
& > div:first-child {
padding : 3px 3px;
background-color : inherit;
border : 1px solid gray;
i { float : right; }
&:hover {
color : white;
background-color : @blue;
}
& .dropdown-options {
overflow-y : visible;
}
.disabled {
font-style : italic;
color : dimgray;
background-color : darkgray;
}
.item {
position : relative;
padding : 3px 3px;
overflow : visible;
background-color : white;
border-top : 1px solid rgb(118, 118, 118);
.preview {
position : absolute;
top : 0;
right : 0;
z-index : 1;
display : flex;
flex-direction : column;
width : 200px;
overflow : hidden;
color : black;
background : #CCCCCC;
border-radius : 5px;
box-shadow : 0 0 5px black;
opacity : 0;
transition : opacity 250ms ease;
h6 {
padding-block : 0.5em;
padding-inline : 1em;
font-weight : 900;
border-bottom : 2px solid hsl(0,0%,40%);
}
}
.navDropdown .item > p {
width : 45%;
height : 1.1em;
overflow : hidden;
text-overflow : ellipsis;
white-space : nowrap;
}
.navDropdown {
position : absolute;
width : 100%;
box-shadow : 0px 5px 10px rgba(0, 0, 0, 0.3);
.item {
position : relative;
padding : 3px 3px;
overflow : visible;
background-color : white;
border-top : 1px solid rgb(118, 118, 118);
.preview {
position : absolute;
top : 0;
right : 0;
z-index : 1;
display : flex;
flex-direction : column;
width : 200px;
overflow : hidden;
color : black;
background : #CCCCCC;
border-radius : 5px;
box-shadow : 0 0 5px black;
opacity : 0;
transition : opacity 250ms ease;
h6 {
padding-block : 0.5em;
padding-inline : 1em;
font-weight : 900;
border-bottom : 2px solid hsl(0,0%,40%);
}
}
&:hover {
color : white;
background-color : @blue;
}
&:hover > .preview { opacity : 1; }
.texture-container {
position : absolute;
top : 0;
left : 0;
width : 100%;
height : 100%;
min-height : 100%;
overflow : hidden;
> img {
position : absolute;
top : 0px;
right : 0;
width : 50%;
min-height : 100%;
-webkit-mask-image : linear-gradient(90deg, transparent, black 20%);
mask-image : linear-gradient(90deg, transparent, black 20%);
}
}
.texture-container {
position : absolute;
top : 0;
left : 0;
width : 100%;
height : 100%;
min-height : 100%;
overflow : hidden;
> img {
position : absolute;
top : 0;
right : 0;
width : 50%;
min-height : 100%;
-webkit-mask-image : linear-gradient(90deg, transparent, black 20%);
mask-image : linear-gradient(90deg, transparent, black 20%);
}
}
&:hover {
color : white;
background-color : @blue;
filter : unset;
}
&:hover > .preview { opacity : 1; }
}
}