161 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
		
		
			
		
	
	
			161 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
|  | import { | ||
|  |   customElement, | ||
|  |   DeesElement, | ||
|  |   property, | ||
|  |   html, | ||
|  |   cssManager, | ||
|  |   unsafeCSS, | ||
|  |   css, | ||
|  |   type TemplateResult, | ||
|  |   domtools, | ||
|  |   query, | ||
|  | } from '@design.estate/dees-element'; | ||
|  | 
 | ||
|  | import * as colors from './00colors.js'; | ||
|  | import { demoFunc } from './dees-searchbar.demo.js'; | ||
|  | 
 | ||
|  | declare global { | ||
|  |   interface HTMLElementTagNameMap { | ||
|  |     'dees-searchbar': DeesSearchbar; | ||
|  |   } | ||
|  | } | ||
|  | 
 | ||
|  | @customElement('dees-searchbar') | ||
|  | export class DeesSearchbar extends DeesElement { | ||
|  |   // DEMO
 | ||
|  |   public static demo = demoFunc; | ||
|  | 
 | ||
|  |   // STATIC
 | ||
|  |   public static styles = [ | ||
|  |     cssManager.defaultStyles, | ||
|  |     css`
 | ||
|  |       :host { | ||
|  |         padding: 40px; | ||
|  |         font-family: Dees Sans; | ||
|  |         display: block; | ||
|  |         background: ${cssManager.bdTheme('#eeeeeb', '#000000')}; | ||
|  |       } | ||
|  | 
 | ||
|  |       .searchboxContainer { | ||
|  |         position: relative; | ||
|  |         margin: auto; | ||
|  |         max-width: 800px; | ||
|  |         background: ${cssManager.bdTheme('#00000015', '#ffffff15')}; | ||
|  |         --boxHeight: 60px; | ||
|  |         height: var(--boxHeight); | ||
|  |         border-radius: var(--boxHeight); | ||
|  |         display: grid; | ||
|  |         grid-template-columns: 1fr 140px; | ||
|  |         justify-content: center; | ||
|  |         align-items: center; | ||
|  |         border-top: 1px solid ${cssManager.bdTheme('#00000015', '#ffffff20')}; | ||
|  |       } | ||
|  | 
 | ||
|  |       input { | ||
|  |         height: 100%; | ||
|  |         width: 100%; | ||
|  |         border: none; | ||
|  |         background: none; | ||
|  |         color: ${cssManager.bdTheme('#000000', '#eeeeeb')}; | ||
|  |         padding-left: 25px; | ||
|  |         margin-right: -8px; | ||
|  |         outline: none; | ||
|  |         font-size: 16px; | ||
|  |       } | ||
|  | 
 | ||
|  |       .searchButton { | ||
|  |         --buttonPadding: 8px; | ||
|  |         background: ${cssManager.bdTheme('#eeeeeb', '#000000')}; | ||
|  |         color: ${cssManager.bdTheme('#000000', '#eeeeeb')}; | ||
|  |         line-height: calc(var(--boxHeight) - (var(--buttonPadding) * 2)); | ||
|  |         border-radius: var(--boxHeight); | ||
|  |         transform: scale(1) ; | ||
|  |         transform-origin: 50% 50%; | ||
|  |         text-align: center; | ||
|  |          | ||
|  |         transition: transform 0.1s, background 0.1s; | ||
|  |         margin-right: var(--buttonPadding); | ||
|  |         user-select: none; | ||
|  |       } | ||
|  | 
 | ||
|  |       .searchButton:hover { | ||
|  |         color: #fff; | ||
|  |         background: ${cssManager.bdTheme(colors.bright.blue, colors.dark.blue)}; | ||
|  |       } | ||
|  | 
 | ||
|  |       .searchButton:active { | ||
|  |         color: #fff; | ||
|  |         background: ${cssManager.bdTheme(colors.bright.blueActive, colors.dark.blueActive)}; | ||
|  |         transform: scale(0.98); | ||
|  |       } | ||
|  | 
 | ||
|  |       .filters { | ||
|  |         margin: auto; | ||
|  |         max-width: 800px; | ||
|  |       } | ||
|  |     `,
 | ||
|  |   ]; | ||
|  | 
 | ||
|  |   // INSTANCE
 | ||
|  | 
 | ||
|  |   @property() | ||
|  |   public filters = []; | ||
|  | 
 | ||
|  | 
 | ||
|  |   @query('input') | ||
|  |   public searchInput!: HTMLInputElement; | ||
|  |   @query('.searchButton') | ||
|  |   public searchButton!: HTMLElement; | ||
|  | 
 | ||
|  |   constructor() { | ||
|  |     super(); | ||
|  |   } | ||
|  | 
 | ||
|  |   public render(): TemplateResult { | ||
|  |     return html`
 | ||
|  |       <div class="searchboxContainer"> | ||
|  |         <input type="text" placeholder="Your Skills (e.g. TypeScript, Rust, Projectmanagement)" /> | ||
|  |         <div class="searchButton">Search -></div> | ||
|  |       </div> | ||
|  |       ${this.filters.length > 0 ? html`
 | ||
|  |         <div class="filters"> | ||
|  |         <dees-heading level="hr-small">Filters</dees-heading> | ||
|  |         <dees-input-dropdown .label=${'location'}></dees-input-dropdown> | ||
|  |       </div>   | ||
|  |       ` : html``}
 | ||
|  |     `;
 | ||
|  |   } | ||
|  |   /** | ||
|  |    * Lifecycle: after first render, wire up events for input and submit actions | ||
|  |    */ | ||
|  |   public firstUpdated(): void { | ||
|  |     // dispatch change on each input
 | ||
|  |     this.searchInput.addEventListener('input', () => { | ||
|  |       this.dispatchEvent(new CustomEvent('search-changed', { | ||
|  |         bubbles: true, | ||
|  |         composed: true, | ||
|  |         detail: { value: this.searchInput.value } | ||
|  |       })); | ||
|  |     }); | ||
|  |     // submit on Enter key
 | ||
|  |     this.searchInput.addEventListener('keydown', (e: KeyboardEvent) => { | ||
|  |       if (e.key === 'Enter') { | ||
|  |         this._dispatchSubmit(); | ||
|  |       } | ||
|  |     }); | ||
|  |     // submit on button click
 | ||
|  |     this.searchButton.addEventListener('click', () => this._dispatchSubmit()); | ||
|  |   } | ||
|  | 
 | ||
|  |   /** | ||
|  |    * Dispatch a submit event with the current search value | ||
|  |    */ | ||
|  |   private _dispatchSubmit(): void { | ||
|  |     this.dispatchEvent(new CustomEvent('search-submit', { | ||
|  |       bubbles: true, | ||
|  |       composed: true, | ||
|  |       detail: { value: this.searchInput.value } | ||
|  |     })); | ||
|  |   } | ||
|  | } |