1- import { LitElement , html , css } from ' https://cdn.jsdelivr.net/gh/lit/dist@3/core/lit-core.min.js' ;
1+ import { LitElement , html , css } from " https://cdn.jsdelivr.net/gh/lit/dist@3/core/lit-core.min.js" ;
22
33export class MultiSelect extends LitElement {
4- static styles = css `p { color: blue }` ;
4+ static styles = css `
5+ p {
6+ color: blue;
7+ }
8+ ` ;
59
610 static properties = {
7- id : { type : String } ,
8- name : { type : String } ,
9- options : { type : Array } ,
10- selected : { type : Array } ,
11- enteredValue : { type : String } ,
12- visibleOptions : { type : Array } ,
13- visibleDropdown : { type : Boolean } ,
14- legend : { type : String } ,
11+ id : { type : String } ,
12+ name : { type : String } ,
13+ options : { type : Array } ,
14+ selected : { type : Array } ,
15+ enteredValue : { type : String } ,
16+ visibleOptions : { type : Array } ,
17+ visibleDropdown : { type : Boolean } ,
18+ legend : { type : String } ,
1519 } ;
1620
1721 constructor ( ) {
1822 super ( ) ;
19- this . id = 'id' ;
20- this . name = ' name' ;
23+ this . id = "id" ;
24+ this . name = " name" ;
2125 this . options = [ ] ;
2226 this . selected = [ ] ;
23- this . enteredValue = '' ;
27+ this . enteredValue = "" ;
2428 this . visibleOptions = [ ] ;
2529 this . visibleDropdown = false ;
2630 this . legend = undefined ;
2731 }
2832
2933 connectedCallback ( ) {
30- super . connectedCallback ( )
34+ super . connectedCallback ( ) ;
3135 this . filterOptions ( ) ;
3236 }
3337
@@ -38,75 +42,97 @@ export class MultiSelect extends LitElement {
3842
3943 filterOptions ( ) {
4044 if ( this . enteredValue . length > 0 ) {
41- this . visibleOptions = this . options . filter ( ( option ) => option . toLowerCase ( ) . includes ( this . enteredValue . toLowerCase ( ) ) ) ;
45+ this . visibleOptions = this . options . filter ( ( option ) =>
46+ option . toLowerCase ( ) . includes ( this . enteredValue . toLowerCase ( ) ) ,
47+ ) ;
4248 } else {
4349 this . visibleOptions = this . options ;
4450 }
4551 }
4652
4753 firstUpdated ( ) {
48- window . addEventListener ( ' mousedown' , this . handleClickOutside ) ;
54+ window . addEventListener ( " mousedown" , this . handleClickOutside ) ;
4955 }
5056
5157 handleClickOutside = ( e ) => {
52- if ( ! this . contains ( e . target ) ) {
58+ if ( ! this . contains ( e . target ) ) {
5359 this . visibleDropdown = false ;
5460 }
55- }
61+ } ;
5662
5763 unnormalize ( text ) {
58- return text . replace ( / - / g, ' ' ) ;
64+ return text . replace ( / - / g, " " ) ;
5965 }
6066
6167 render ( ) {
62-
6368 return html `
6469 < label for ="${ this . id } " class ="form-label "> ${ this . name } </ label >
6570 < div class ="mt-2 relative ">
66- < div class ="input-primary px-1.5 flex flex-wrap focus-within:outline focus-within:outline-[3px] focus-within:-outline-offset-2 focus-within:outline-primary-600 ">
71+ < div
72+ class ="input-primary px-1.5 flex flex-wrap focus-within:outline focus-within:outline-[3px] focus-within:-outline-offset-2 focus-within:outline-primary-600 "
73+ >
6774 < div class ="flex flex-items flex-wrap w-full ">
68- ${ this . selected . map ( ( option ) => html `< span class ="inline-flex items-center text-nowrap max-w-[100%] ps-2 pe-0.5 py-0.5 me-2 text-xs font-medium text-gray-800 bg-gray-100 rounded-full ">
69- < div class ="flex items-center w-full ">
70- < div class ="truncate capitalize "> ${ this . unnormalize ( option ) } </ div >
71- < button type ="button " @click =${ ( ) => this . _onRemoveBadge ( option ) } class ="inline-flex items-center p-1 ms-2 bg-transparent rounded-full hover:bg-gray-200" aria-label="Remove badge">
72- < div class ="svg-icon size-3 icon-close bg-gray-400 hover:bg-gray-900 "> </ div >
73- < span class ="sr-only "> Remove badge</ span >
74- </ button >
75- </ div >
76- ` ) }
77- < input type ="text "
75+ ${ this . selected . map (
76+ ( option ) =>
77+ html `< span
78+ class ="inline-flex items-center text-nowrap max-w-[100%] ps-2 pe-0.5 py-0.5 me-2 text-xs font-medium text-gray-800 bg-gray-100 rounded-full "
79+ >
80+ < div class ="flex items-center w-full ">
81+ < div class ="truncate capitalize "> ${ this . unnormalize ( option ) } </ div >
82+ < button
83+ type ="button "
84+ @click =${ ( ) => this . _onRemoveBadge ( option ) }
85+ class ="inline-flex items-center p-1 ms-2 bg-transparent rounded-full hover:bg-gray-200"
86+ aria-label="Remove badge"
87+ >
88+ < div class ="svg-icon size-3 icon-close bg-gray-400 hover:bg-gray-900 "> </ div >
89+ < span class ="sr-only "> Remove badge</ span >
90+ </ button >
91+ </ div >
92+ </ span > ` ,
93+ ) }
94+ < input
95+ type ="text "
7896 @input =${ this . _onInputChange }
79- @focus =${ ( ) => this . visibleDropdown = true }
97+ @focus =${ ( ) => ( this . visibleDropdown = true ) }
8098 .value="${ this . enteredValue } "
8199 placeholder="Type to search"
82- class="flex flex-grow p-0 ps-1.5 rounded-md text-gray-900 max-w-full min-w-[80px] border-0 focus:ring-0 sm:text-sm/6">
100+ class="flex flex-grow p-0 ps-1.5 rounded-md text-gray-900 max-w-full min-w-[80px] border-0 focus:ring-0 sm:text-sm/6"
101+ />
83102 </ div >
84103 </ div >
85- ${ this . legend ? html `< p class ="form-legend "> ${ this . legend } </ p > ` : '' }
86- < div class =${ `${ ! this . visibleDropdown ? 'hidden' : '' } absolute start-0 z-10 bg-white divide-y divide-gray-100 rounded-lg shadow w-full border mt-1` } >
87- ${ this . enteredValue . length > 0 ? html `< div class ="flex items-center justify-between py-2 px-4 ">
88- < div class ="truncate "> ${ this . enteredValue } </ div >
89- < button
90- type ="button "
91- @click =${ ( ) => this . _onClickOption ( ) }
92- class ="btn-primary">
93- Add
94- </ button >
95- </ div > ` : '' }
104+ ${ this . legend ? html `< p class ="form-legend "> ${ this . legend } </ p > ` : "" }
105+ < div
106+ class =${ `${
107+ ! this . visibleDropdown ? "hidden" : ""
108+ } absolute start-0 z-10 bg-white divide-y divide-gray-100 rounded-lg shadow w-full border mt-1`}
109+ >
110+ ${ this . enteredValue . length > 0
111+ ? html `< div class ="flex items-center justify-between py-2 px-4 ">
112+ < div class ="truncate "> ${ this . enteredValue } </ div >
113+ < button type ="button " @click =${ ( ) => this . _onClickOption ( ) } class ="btn-primary"> Add</ button >
114+ </ div > `
115+ : "" }
96116 < ul class ="text-sm text-gray-700 overflow-x-auto max-h-[150px] ">
97117 ${ this . visibleOptions . map ( ( option ) => {
98118 const isSelected = this . selected . includes ( option ) ;
99119 return html `< li >
100- < button @click =${ ( ) => this . _onClickOption ( option ) } type ="button" class=${ `${ isSelected ? 'bg-gray-100 opacity-50' : 'cursor-pointer hover:bg-gray-100' } capitalize block w-full text-left px-4 py-2` }
101- ?disabled="${ isSelected } ">
120+ < button
121+ @click =${ ( ) => this . _onClickOption ( option ) }
122+ type ="button"
123+ class=${ `${
124+ isSelected ? "bg-gray-100 opacity-50" : "cursor-pointer hover:bg-gray-100"
125+ } capitalize block w-full text-left px-4 py-2`}
126+ ?disabled="${ isSelected } "
127+ >
102128 < div class ="flex items-center ">
103129 < div class ="size-3 me-2 ">
104- ${ isSelected ? html `< div class ="svg-icon size-3 icon-check bg-gray-400 "> </ div > ` : '' }
130+ ${ isSelected ? html `< div class ="svg-icon size-3 icon-check bg-gray-400 "> </ div > ` : "" }
105131 </ div >
106132 < div class ="truncate "> ${ this . unnormalize ( option ) } </ div >
107133 </ div >
108134 </ button >
109- </ li > `
135+ </ li > ` ;
110136 } ) }
111137 </ ul >
112138 </ div >
@@ -128,9 +154,9 @@ export class MultiSelect extends LitElement {
128154
129155 _onClickOption ( option ) {
130156 this . selected . push ( option || this . enteredValue ) ;
131- this . enteredValue = '' ;
157+ this . enteredValue = "" ;
132158 this . visibleDropdown = false ;
133159 this . filterOptions ( ) ;
134160 }
135161}
136- customElements . define ( ' multi-select' , MultiSelect ) ;
162+ customElements . define ( " multi-select" , MultiSelect ) ;
0 commit comments