22import { GecutDirective } from '@gecut/lit-helper/directives/directive.js' ;
33import { numberUtils } from '@gecut/utilities/data-types/number.js' ;
44import { directive , type PartInfo } from 'lit/directive.js' ;
5- import { classMap } from 'lit/directives/class-map.js' ;
5+ import { classMap } from 'lit/directives/class-map.js' ;
66import { ifDefined } from 'lit/directives/if-defined.js' ;
77import { when } from 'lit/directives/when.js' ;
88import { html , noChange , nothing } from 'lit/html.js' ;
99import { literal , html as staticHtml } from 'lit/static-html.js' ;
1010
11- import { divider , icon , iconButton } from '../components' ;
11+ import { divider , icon , gecutIconButton } from '../components' ;
12+ import { gecutEFO } from '../internal/events-handler' ;
1213
1314import type { IconButtonContent , IconContent } from '../components' ;
15+ import type { EventsObject } from '../internal/events-handler' ;
1416import type { RenderResult } from '@gecut/types' ;
17+ import type { ClassInfo } from 'lit/directives/class-map.js' ;
1518import type { TemplateResult } from 'lit/html.js' ;
1619import type { StaticValue } from 'lit/static-html.js' ;
1720
@@ -23,18 +26,18 @@ export interface ItemImageSlotContent {
2326export type HtmlString = string | TemplateResult ;
2427export type ItemSlutContent =
2528 | {
26- type : 'avatar:character' ;
29+ element : 'avatar:character' ;
2730 character : string ;
2831 }
2932 | ( ItemImageSlotContent & {
30- type : 'avatar:image' ;
33+ element : 'avatar:image' ;
3134 } )
3235 | ( ItemImageSlotContent & {
33- type : 'image' ;
36+ element : 'image' ;
3437 } )
35- | { type : 'template' ; template : TemplateResult }
36- | ( IconContent & { type : 'icon' } )
37- | ( IconButtonContent & { type : 'icon-button' } ) ;
38+ | { element : 'template' ; template : TemplateResult }
39+ | ( IconContent & { element : 'icon' } )
40+ | ( IconButtonContent & { element : 'icon-button' } ) ;
3841
3942export interface ItemContent {
4043 headline : HtmlString ;
@@ -47,8 +50,7 @@ export interface ItemContent {
4750 href ?: string ;
4851 target ?: '_blank' | '_parent' | '_self' | '_top' ;
4952
50- onClick ?: ( event : MouseEvent ) => void ;
51- onDblClick ?: ( event : MouseEvent ) => void ;
53+ events ?: EventsObject ;
5254
5355 disabled ?: boolean ;
5456 divider ?: boolean ;
@@ -59,23 +61,20 @@ export interface ItemContent {
5961
6062export class GecutItemDirective extends GecutDirective {
6163 constructor ( partInfo : PartInfo ) {
62- super ( partInfo , 'gecut-button ' ) ;
64+ super ( partInfo , 'gecut-list-item ' ) ;
6365 }
6466
6567 protected content ?: ItemContent ;
6668 protected type : 'link' | 'text' | 'button' = 'text' ;
6769
68- protected $rootClassName =
69- 'relative flex flex-col list-none group w-full bg-surface text-onSurface overflow-hidden [&[interactive]]:focus-ring-inner rounded-lg disabled:cursor-default disabled:pointer-events-none select-none [&[interactive]]:hover:stateHover-onSurface [&[interactive]]:active:stateActive-onSurface' ;
70-
7170 render ( content ?: ItemContent ) : unknown {
7271 this . log . methodArgs ?.( 'render' , content ) ;
7372
7473 if ( content === undefined ) return noChange ;
7574
7675 this . content = content ;
7776
78- if ( content . onClick || content . onDblClick ) this . type = 'button' ;
77+ if ( content . events ) this . type = 'button' ;
7978 if ( content . href ) this . type = 'link' ;
8079
8180 return this . renderItem ( ) ;
@@ -104,44 +103,33 @@ export class GecutItemDirective extends GecutDirective {
104103
105104 return staticHtml `
106105 < ${ tag }
107- class =${ classMap ( { [ this . $rootClassName ] : true , ... this . getRenderClasses ( ) } ) }
106+ class =${ classMap ( this . getRenderClasses ( ) ) }
108107 tabindex="${ this . content . disabled || ! isInteractive ? - 1 : 0 } "
109108 role="listitem"
110109 href=${ ifDefined ( this . content . href ) }
111110 target=${ ifDefined ( this . content . target ) }
112111 ?disabled=${ this . content . disabled }
113- ?sttl=${ this . content . supportingTextTwoLine }
114- ?interactive=${ isInteractive }
115- ?multiline=${ this . content . headline && this . content . supportingText }
116- ?divider=${ this . content . divider }
117- @click=${ this . content . onClick }
118- @dblclick=${ this . content . onDblClick }
112+ ${ gecutEFO ( this . content . events ) }
119113 > ${ this . renderBody ( ) } </ ${ tag } >
120114 ` ;
121115 }
122116 protected renderBody ( ) {
123117 if ( ! this . content ) return nothing ;
124118
125119 return html `
126- < div class ="flex gap-4 py-3 px-4 ">
127- < div class ="empty:hidden flex items-center group-[[sttl]]:items-start shrink-0 ">
128- ${ this . renderSlot ( 'leading' ) }
129- </ div >
120+ < div class ="gecut-list-item-body ">
121+ < div class ="gecut-list-item-leading "> ${ this . renderSlot ( 'leading' ) } </ div >
130122
131- < div class ="flex flex-col min-h-8 grow justify-center group-[[multiline]]:min-h-12 ">
132- < p class ="text-onSurface text-bodyLarge text-start line-clamp-1 "> ${ this . content . headline } </ p >
133- < p class ="text-onSurfaceVariant text-bodyMedium line-clamp-1 text-start group-[[sttl]]:line-clamp-2 ">
134- ${ this . content . supportingText }
135- </ p >
123+ < div class ="gecut-list-item-content ">
124+ < p class ="gecut-list-item-headline "> ${ this . content . headline } </ p >
125+ < p class ="gecut-list-item-supporting-text "> ${ this . content . supportingText } </ p >
136126 </ div >
137127
138- < div class ="empty:hidden flex justify-center items-center shrink-0 gap-4 ">
128+ < div class ="gecut-list-item-trailing ">
139129 ${ when (
140130 this . content . trailingSupportingText ,
141131 ( ) => html `
142- < p class ="text-onSurfaceVariant text-labelSmall ">
143- ${ this . renderItemTrailingSupportingText ( ) }
144- </ p >
132+ < p class ="gecut-list-item-trailing-supporting-text "> ${ this . renderItemTrailingSupportingText ( ) } </ p >
145133 ` ,
146134 ) }
147135 ${ this . renderSlot ( 'trailing' ) }
@@ -161,18 +149,14 @@ export class GecutItemDirective extends GecutDirective {
161149
162150 if ( ! this . content || ! content ) return nothing ;
163151
164- switch ( content . type ) {
152+ switch ( content . element ) {
165153 case 'avatar:character' :
166- return html `
167- < div
168- class ="bg-tertiaryContainer text-onTertiaryContainer uppercase size-10 flex items-center justify-center text-bodyLarge rounded-full "
169- >
170- ${ content . character }
171- </ div >
172- ` ;
154+ return html `< div class ="gecut-list-item-slot-avatar-character "> ${ content . character } </ div > ` ;
173155 case 'avatar:image' :
174156 return nothing ;
175157 case 'image' : {
158+ // TODO: Write a Image LazyLoad Component
159+
176160 const image = new Image ( ) ;
177161 const lazyLoadImage = new Image ( ) ;
178162
@@ -192,12 +176,12 @@ export class GecutItemDirective extends GecutDirective {
192176
193177 lazyLoadImage . src = content . source ;
194178
195- return html `${ image } ` ;
179+ return html `< div class =" gecut-list-item-slot-thumbnail " > ${ image } </ div > ` ;
196180 }
197181 case 'icon' :
198182 return icon ( content ) ;
199183 case 'icon-button' :
200- return iconButton ( content ) ;
184+ return gecutIconButton ( content ) ;
201185 case 'template' :
202186 return content . template ;
203187 }
@@ -220,6 +204,19 @@ export class GecutItemDirective extends GecutDirective {
220204 }
221205 }
222206 }
207+
208+ protected override getRenderClasses ( ) : ClassInfo {
209+ if ( ! this . content ) return super . getRenderClasses ( ) ;
210+
211+ return {
212+ ...super . getRenderClasses ( ) ,
213+
214+ 'supporting-text-two-line' : this . content . supportingTextTwoLine ?? false ,
215+ interactive : this . type !== 'text' ,
216+ multiline : ( ! ! this . content . headline && ! ! this . content . supportingText ) ?? false ,
217+ divider : this . content . divider ?? false ,
218+ } ;
219+ }
223220}
224221
225222export const gecutItem = directive ( GecutItemDirective ) ;
0 commit comments