| 
									
										
										
										
											2021-10-08 16:07:40 +02:00
										 |  |  | import { | 
					
						
							|  |  |  |   customElement, | 
					
						
							|  |  |  |   html, | 
					
						
							|  |  |  |   DeesElement, | 
					
						
							|  |  |  |   property, | 
					
						
							| 
									
										
										
										
											2023-08-07 20:02:18 +02:00
										 |  |  |   type TemplateResult, | 
					
						
							| 
									
										
										
										
											2021-10-08 16:07:40 +02:00
										 |  |  |   cssManager, | 
					
						
							|  |  |  |   css, | 
					
						
							| 
									
										
										
										
											2023-08-08 01:10:02 +02:00
										 |  |  |   type CSSResult, | 
					
						
							| 
									
										
										
										
											2021-10-08 16:07:40 +02:00
										 |  |  |   unsafeCSS, | 
					
						
							| 
									
										
										
										
											2023-08-07 19:13:29 +02:00
										 |  |  | } from '@design.estate/dees-element'; | 
					
						
							| 
									
										
										
										
											2021-10-08 16:07:40 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-07 19:13:29 +02:00
										 |  |  | import * as domtools from '@design.estate/dees-domtools'; | 
					
						
							| 
									
										
										
										
											2023-10-23 21:23:18 +02:00
										 |  |  | import { demoFunc } from './dees-chips.demo.js'; | 
					
						
							| 
									
										
										
										
											2021-10-08 16:07:40 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | declare global { | 
					
						
							|  |  |  |   interface HTMLElementTagNameMap { | 
					
						
							|  |  |  |     'dees-chips': DeesChips; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-31 13:44:18 +01:00
										 |  |  | type Tag = { key: string; value: string }; | 
					
						
							| 
									
										
										
										
											2023-10-23 21:23:18 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-08 16:07:40 +02:00
										 |  |  | @customElement('dees-chips') | 
					
						
							|  |  |  | export class DeesChips extends DeesElement { | 
					
						
							| 
									
										
										
										
											2023-10-23 21:23:18 +02:00
										 |  |  |   public static demo = demoFunc; | 
					
						
							| 
									
										
										
										
											2021-10-08 16:07:40 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |   @property() | 
					
						
							| 
									
										
										
										
											2023-10-23 21:23:18 +02:00
										 |  |  |   public selectionMode: 'none' | 'single' | 'multiple' = 'single'; | 
					
						
							| 
									
										
										
										
											2021-10-08 16:07:40 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |   @property({ | 
					
						
							| 
									
										
										
										
											2023-10-31 13:44:18 +01:00
										 |  |  |     type: Boolean, | 
					
						
							|  |  |  |   }) | 
					
						
							|  |  |  |   public chipsAreRemovable: boolean = false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   @property({ | 
					
						
							|  |  |  |     type: Array, | 
					
						
							| 
									
										
										
										
											2021-10-08 16:07:40 +02:00
										 |  |  |   }) | 
					
						
							| 
									
										
										
										
											2023-10-23 21:23:18 +02:00
										 |  |  |   public selectableChips: Tag[] = []; | 
					
						
							| 
									
										
										
										
											2021-10-08 16:07:40 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |   @property() | 
					
						
							| 
									
										
										
										
											2023-10-23 21:23:18 +02:00
										 |  |  |   public selectedChip: Tag = null; | 
					
						
							| 
									
										
										
										
											2021-10-08 16:07:40 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |   @property({ | 
					
						
							| 
									
										
										
										
											2023-10-31 13:44:18 +01:00
										 |  |  |     type: Array, | 
					
						
							| 
									
										
										
										
											2021-10-08 16:07:40 +02:00
										 |  |  |   }) | 
					
						
							| 
									
										
										
										
											2023-10-23 21:23:18 +02:00
										 |  |  |   public selectedChips: Tag[] = []; | 
					
						
							| 
									
										
										
										
											2021-10-08 16:07:40 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |   constructor() { | 
					
						
							|  |  |  |     super(); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   public static styles = [ | 
					
						
							|  |  |  |     cssManager.defaultStyles, | 
					
						
							|  |  |  |     css`
 | 
					
						
							|  |  |  |       :host { | 
					
						
							|  |  |  |         display: block; | 
					
						
							|  |  |  |         box-sizing: border-box; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       .mainbox { | 
					
						
							| 
									
										
										
										
											2023-10-23 21:23:18 +02:00
										 |  |  |         user-select: none; | 
					
						
							| 
									
										
										
										
											2025-06-27 21:01:12 +00:00
										 |  |  |         display: flex; | 
					
						
							|  |  |  |         flex-wrap: wrap; | 
					
						
							|  |  |  |         gap: 8px; | 
					
						
							| 
									
										
										
										
											2021-10-08 16:07:40 +02:00
										 |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       .chip { | 
					
						
							| 
									
										
										
										
											2025-06-27 21:01:12 +00:00
										 |  |  |         background: ${cssManager.bdTheme('#f4f4f5', '#27272a')}; | 
					
						
							|  |  |  |         border: 1px solid ${cssManager.bdTheme('#e5e7eb', '#3f3f46')}; | 
					
						
							| 
									
										
										
										
											2023-10-23 21:23:18 +02:00
										 |  |  |         display: inline-flex; | 
					
						
							| 
									
										
										
										
											2025-06-27 21:01:12 +00:00
										 |  |  |         align-items: center; | 
					
						
							|  |  |  |         height: 32px; | 
					
						
							|  |  |  |         padding: 0px 12px; | 
					
						
							|  |  |  |         font-size: 14px; | 
					
						
							|  |  |  |         font-weight: 500; | 
					
						
							|  |  |  |         color: ${cssManager.bdTheme('#09090b', '#fafafa')}; | 
					
						
							|  |  |  |         border-radius: 6px; | 
					
						
							| 
									
										
										
										
											2023-10-23 21:23:18 +02:00
										 |  |  |         position: relative; | 
					
						
							| 
									
										
										
										
											2025-06-27 21:01:12 +00:00
										 |  |  |         cursor: pointer; | 
					
						
							|  |  |  |         transition: all 0.15s ease; | 
					
						
							|  |  |  |         box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.05); | 
					
						
							| 
									
										
										
										
											2021-10-08 16:07:40 +02:00
										 |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       .chip:hover { | 
					
						
							| 
									
										
										
										
											2025-06-27 21:01:12 +00:00
										 |  |  |         background: ${cssManager.bdTheme('#e5e7eb', '#3f3f46')}; | 
					
						
							|  |  |  |         border-color: ${cssManager.bdTheme('#d1d5db', '#52525b')}; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       .chip:active { | 
					
						
							|  |  |  |         transform: scale(0.98); | 
					
						
							| 
									
										
										
										
											2021-10-08 16:07:40 +02:00
										 |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       .chip.selected { | 
					
						
							| 
									
										
										
										
											2025-06-27 21:01:12 +00:00
										 |  |  |         background: ${cssManager.bdTheme('#3b82f6', '#3b82f6')}; | 
					
						
							|  |  |  |         border-color: ${cssManager.bdTheme('#3b82f6', '#3b82f6')}; | 
					
						
							|  |  |  |         color: #ffffff; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       .chip.selected:hover { | 
					
						
							|  |  |  |         background: ${cssManager.bdTheme('#2563eb', '#2563eb')}; | 
					
						
							|  |  |  |         border-color: ${cssManager.bdTheme('#2563eb', '#2563eb')}; | 
					
						
							| 
									
										
										
										
											2021-10-08 16:07:40 +02:00
										 |  |  |       } | 
					
						
							| 
									
										
										
										
											2023-10-23 21:23:18 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |       .chipKey { | 
					
						
							| 
									
										
										
										
											2025-06-27 21:01:12 +00:00
										 |  |  |         background: ${cssManager.bdTheme('rgba(0, 0, 0, 0.06)', 'rgba(255, 255, 255, 0.1)')}; | 
					
						
							|  |  |  |         height: 20px; | 
					
						
							|  |  |  |         line-height: 20px; | 
					
						
							|  |  |  |         display: inline-flex; | 
					
						
							|  |  |  |         align-items: center; | 
					
						
							| 
									
										
										
										
											2023-10-23 21:23:18 +02:00
										 |  |  |         margin-left: -8px; | 
					
						
							| 
									
										
										
										
											2025-06-27 21:01:12 +00:00
										 |  |  |         padding: 0px 8px; | 
					
						
							| 
									
										
										
										
											2023-10-23 21:23:18 +02:00
										 |  |  |         margin-right: 8px; | 
					
						
							| 
									
										
										
										
											2025-06-27 21:01:12 +00:00
										 |  |  |         border-radius: 4px; | 
					
						
							|  |  |  |         font-size: 12px; | 
					
						
							|  |  |  |         font-weight: 600; | 
					
						
							|  |  |  |         color: ${cssManager.bdTheme('#71717a', '#a1a1aa')}; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       .chip.selected .chipKey { | 
					
						
							|  |  |  |         background: rgba(255, 255, 255, 0.2); | 
					
						
							|  |  |  |         color: rgba(255, 255, 255, 0.9); | 
					
						
							| 
									
										
										
										
											2023-10-23 21:23:18 +02:00
										 |  |  |       } | 
					
						
							| 
									
										
										
										
											2023-10-31 13:44:18 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |       dees-icon { | 
					
						
							| 
									
										
										
										
											2025-06-27 21:01:12 +00:00
										 |  |  |         display: flex; | 
					
						
							|  |  |  |         align-items: center; | 
					
						
							|  |  |  |         justify-content: center; | 
					
						
							|  |  |  |         width: 16px; | 
					
						
							|  |  |  |         height: 16px; | 
					
						
							|  |  |  |         margin-left: 8px; | 
					
						
							|  |  |  |         margin-right: -6px; | 
					
						
							|  |  |  |         border-radius: 3px; | 
					
						
							|  |  |  |         transition: all 0.15s ease; | 
					
						
							|  |  |  |         color: ${cssManager.bdTheme('#71717a', '#a1a1aa')}; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       .chip.selected dees-icon { | 
					
						
							|  |  |  |         color: rgba(255, 255, 255, 0.8); | 
					
						
							| 
									
										
										
										
											2023-10-31 13:44:18 +01:00
										 |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       dees-icon:hover { | 
					
						
							| 
									
										
										
										
											2025-06-27 21:01:12 +00:00
										 |  |  |         background: ${cssManager.bdTheme('rgba(0, 0, 0, 0.1)', 'rgba(255, 255, 255, 0.1)')}; | 
					
						
							|  |  |  |         color: ${cssManager.bdTheme('#ef4444', '#ef4444')}; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       .chip.selected dees-icon:hover { | 
					
						
							|  |  |  |         background: rgba(255, 255, 255, 0.2); | 
					
						
							|  |  |  |         color: #ffffff; | 
					
						
							| 
									
										
										
										
											2023-10-31 13:44:18 +01:00
										 |  |  |       } | 
					
						
							| 
									
										
										
										
											2021-10-08 16:07:40 +02:00
										 |  |  |     `,
 | 
					
						
							|  |  |  |   ]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   public render(): TemplateResult { | 
					
						
							|  |  |  |     return html`
 | 
					
						
							|  |  |  |       <div class="mainbox"> | 
					
						
							| 
									
										
										
										
											2023-10-31 13:44:18 +01:00
										 |  |  |         ${this.selectableChips.map( | 
					
						
							|  |  |  |           (chip) => html`
 | 
					
						
							|  |  |  |             <div | 
					
						
							|  |  |  |               @click=${() => this.selectChip(chip)} | 
					
						
							|  |  |  |               class="chip ${this.isSelected(chip) ? 'selected' : ''}" | 
					
						
							|  |  |  |             > | 
					
						
							|  |  |  |               ${chip.key ? html`<div class="chipKey">${chip.key}</div>` : html``} ${chip.value} | 
					
						
							|  |  |  |               ${this.chipsAreRemovable | 
					
						
							|  |  |  |                 ? html`
 | 
					
						
							|  |  |  |                     <dees-icon | 
					
						
							|  |  |  |                       @click=${(event: Event) => { | 
					
						
							|  |  |  |                         event.stopPropagation(); // prevent the selectChip event from being triggered
 | 
					
						
							|  |  |  |                         this.removeChip(chip); | 
					
						
							|  |  |  |                       }} | 
					
						
							| 
									
										
										
										
											2025-06-30 12:57:13 +00:00
										 |  |  |                       .icon=${'fa:xmark'} | 
					
						
							| 
									
										
										
										
											2023-10-31 13:44:18 +01:00
										 |  |  |                     ></dees-icon> | 
					
						
							|  |  |  |                   `
 | 
					
						
							|  |  |  |                 : html``} | 
					
						
							|  |  |  |             </div> | 
					
						
							|  |  |  |           `
 | 
					
						
							|  |  |  |         )} | 
					
						
							| 
									
										
										
										
											2021-10-08 16:07:40 +02:00
										 |  |  |       </div> | 
					
						
							|  |  |  |     `;
 | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   public async firstUpdated() { | 
					
						
							| 
									
										
										
										
											2025-06-27 21:01:12 +00:00
										 |  |  |     // Component initialized
 | 
					
						
							| 
									
										
										
										
											2021-10-08 16:07:40 +02:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-23 21:23:18 +02:00
										 |  |  |   private isSelected(chip: Tag): boolean { | 
					
						
							|  |  |  |     if (this.selectionMode === 'single') { | 
					
						
							| 
									
										
										
										
											2025-06-27 21:01:12 +00:00
										 |  |  |       return this.selectedChip ? this.isSameChip(this.selectedChip, chip) : false; | 
					
						
							| 
									
										
										
										
											2023-10-23 21:23:18 +02:00
										 |  |  |     } else { | 
					
						
							| 
									
										
										
										
											2025-06-27 21:01:12 +00:00
										 |  |  |       return this.selectedChips.some((selected) => this.isSameChip(selected, chip)); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |    | 
					
						
							|  |  |  |   private isSameChip(chip1: Tag, chip2: Tag): boolean { | 
					
						
							|  |  |  |     // If both have keys, compare by key
 | 
					
						
							|  |  |  |     if (chip1.key && chip2.key) { | 
					
						
							|  |  |  |       return chip1.key === chip2.key; | 
					
						
							| 
									
										
										
										
											2023-10-23 21:23:18 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2025-06-27 21:01:12 +00:00
										 |  |  |     // Otherwise compare by value (and key if present)
 | 
					
						
							|  |  |  |     return chip1.value === chip2.value && chip1.key === chip2.key; | 
					
						
							| 
									
										
										
										
											2023-10-23 21:23:18 +02:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   public async selectChip(chip: Tag) { | 
					
						
							|  |  |  |     if (this.selectionMode === 'none') { | 
					
						
							|  |  |  |       return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-08 16:07:40 +02:00
										 |  |  |     if (this.selectionMode === 'single') { | 
					
						
							| 
									
										
										
										
											2023-10-23 21:23:18 +02:00
										 |  |  |       if (this.isSelected(chip)) { | 
					
						
							| 
									
										
										
										
											2021-10-08 16:07:40 +02:00
										 |  |  |         this.selectedChip = null; | 
					
						
							|  |  |  |         this.selectedChips = []; | 
					
						
							|  |  |  |       } else { | 
					
						
							| 
									
										
										
										
											2023-10-23 21:23:18 +02:00
										 |  |  |         this.selectedChip = chip; | 
					
						
							|  |  |  |         this.selectedChips = [chip]; | 
					
						
							| 
									
										
										
										
											2021-10-08 16:07:40 +02:00
										 |  |  |       } | 
					
						
							| 
									
										
										
										
											2023-10-31 13:44:18 +01:00
										 |  |  |     } else if (this.selectionMode === 'multiple') { | 
					
						
							| 
									
										
										
										
											2023-10-23 21:23:18 +02:00
										 |  |  |       if (this.isSelected(chip)) { | 
					
						
							| 
									
										
										
										
											2025-06-27 21:01:12 +00:00
										 |  |  |         this.selectedChips = this.selectedChips.filter((selected) => !this.isSameChip(selected, chip)); | 
					
						
							| 
									
										
										
										
											2021-10-08 16:07:40 +02:00
										 |  |  |       } else { | 
					
						
							| 
									
										
										
										
											2023-10-23 21:23:18 +02:00
										 |  |  |         this.selectedChips = [...this.selectedChips, chip]; | 
					
						
							| 
									
										
										
										
											2021-10-08 16:07:40 +02:00
										 |  |  |       } | 
					
						
							|  |  |  |       this.requestUpdate(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     console.log(this.selectedChips); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2023-10-31 13:44:18 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |   public removeChip(chipToRemove: Tag): void { | 
					
						
							|  |  |  |     // Remove the chip from selectableChips
 | 
					
						
							| 
									
										
										
										
											2025-06-27 21:01:12 +00:00
										 |  |  |     this.selectableChips = this.selectableChips.filter((chip) => !this.isSameChip(chip, chipToRemove)); | 
					
						
							| 
									
										
										
										
											2023-10-31 13:44:18 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     // Remove the chip from selectedChips if present
 | 
					
						
							| 
									
										
										
										
											2025-06-27 21:01:12 +00:00
										 |  |  |     this.selectedChips = this.selectedChips.filter((chip) => !this.isSameChip(chip, chipToRemove)); | 
					
						
							| 
									
										
										
										
											2023-10-31 13:44:18 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     // If the removed chip was the selectedChip, set selectedChip to null
 | 
					
						
							| 
									
										
										
										
											2025-06-27 21:01:12 +00:00
										 |  |  |     if (this.selectedChip && this.isSameChip(this.selectedChip, chipToRemove)) { | 
					
						
							| 
									
										
										
										
											2023-10-31 13:44:18 +01:00
										 |  |  |       this.selectedChip = null; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Trigger an update to re-render the component
 | 
					
						
							|  |  |  |     this.requestUpdate(); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2021-10-08 16:07:40 +02:00
										 |  |  | } |