@@ -3,8 +3,9 @@ import { html, render, TemplateResult } from "lit-html";
33import { unsafeHTML } from "lit-html/directives/unsafe-html" ;
44import env from "~brixi/controllers/env" ;
55import { InputBase , IInputBase } from "../input-base" ;
6+ import alerts from "~brixi/controllers/alerts" ;
67
7- env . css ( "input" ) ;
8+ env . css ( [ "input" , "button" , "toast" ] ) ;
89
910export interface IInput extends IInputBase {
1011 label : string ;
@@ -15,7 +16,7 @@ export interface IInput extends IInputBase {
1516 placeholder : string ;
1617 maxlength : number ;
1718 minlength : number ;
18- readOnly : boolean ;
19+ readOnly ? : boolean ;
1920 datalist : string [ ] ;
2021 autofocus : boolean ;
2122 value : string ;
@@ -137,6 +138,13 @@ export default class Input extends InputBase<IInput> {
137138 ) ;
138139 } ;
139140
141+ private handleCopyClick : EventListener = ( e : Event ) => {
142+ e . stopImmediatePropagation ( ) ;
143+ window . navigator . clipboard . writeText ( this . model . value ) . then ( ( ) => {
144+ alerts . toast ( "Copied to clipboard" ) ;
145+ } ) ;
146+ } ;
147+
140148 private renderCopy ( ) : string | TemplateResult {
141149 let output : string | TemplateResult = "" ;
142150 if ( this . state === "IDLING" && this . model . instructions ) {
@@ -155,6 +163,32 @@ export default class Input extends InputBase<IInput> {
155163 return output ;
156164 }
157165
166+ private renderReadOnlyIcon ( ) : string | TemplateResult {
167+ let output : string | TemplateResult = "" ;
168+ if ( this . model . readOnly ) {
169+ output = html `
170+ < button class ="bttn absolute r-0 b-0 " kind ="text " color ="primary " size ="slim " icon ="center " dull @click =${ this . handleCopyClick } type ="button">
171+ < svg
172+ xmlns ="http://www.w3.org/2000/svg "
173+ width ="24 "
174+ height ="24 "
175+ viewBox ="0 0 24 24 "
176+ stroke-width ="2 "
177+ stroke ="currentColor "
178+ fill ="none "
179+ stroke-linecap ="round "
180+ stroke-linejoin ="round "
181+ >
182+ < path stroke ="none " d ="M0 0h24v24H0z " fill ="none "> </ path >
183+ < path d ="M8 8m0 2a2 2 0 0 1 2 -2h8a2 2 0 0 1 2 2v8a2 2 0 0 1 -2 2h-8a2 2 0 0 1 -2 -2z "> </ path >
184+ < path d ="M16 8v-2a2 2 0 0 0 -2 -2h-8a2 2 0 0 0 -2 2v8a2 2 0 0 0 2 2h2 "> </ path >
185+ </ svg >
186+ </ button >
187+ ` ;
188+ }
189+ return output ;
190+ }
191+
158192 private renderLabel ( ) : string | TemplateResult {
159193 let output : string | TemplateResult = "" ;
160194 if ( this . model . label ?. length ) {
@@ -180,6 +214,9 @@ export default class Input extends InputBase<IInput> {
180214 render ( ) {
181215 this . setAttribute ( "state" , this . state ) ;
182216 this . classList . add ( "input" ) ;
217+ if ( this . model . readOnly ) {
218+ this . setAttribute ( "readonly" , `${ this . model . readOnly } ` ) ;
219+ }
183220 const view = html `
184221 ${ this . renderLabel ( ) } ${ this . renderCopy ( ) }
185222 < input-container >
@@ -201,7 +238,9 @@ export default class Input extends InputBase<IInput> {
201238 ?disabled=${ this . model . disabled }
202239 list="${ this . model . datalist . length ? `${ this . inputId } -datalist` : "" } "
203240 ?autofocus=${ this . model . autofocus }
241+ ?readonly=${ this . model . readOnly }
204242 />
243+ ${ this . renderReadOnlyIcon ( ) }
205244 </ input-container >
206245 ${ this . renderDatalist ( ) }
207246 ` ;
0 commit comments