@sandlada/mdc
Version:
@sandlada/mdc is an open source component library that follows the Material Design 3 design specifications.
27 lines • 7.82 kB
JavaScript
import{property as e}from"../../../node_modules/@lit/reactive-element/decorators/property.js";import{state as t}from"../../../node_modules/@lit/reactive-element/decorators/state.js";import{query as n}from"../../../node_modules/@lit/reactive-element/decorators/query.js";import{queryAssignedElements as r}from"../../../node_modules/@lit/reactive-element/decorators/query-assigned-elements.js";import{queryAssignedNodes as i}from"../../../node_modules/@lit/reactive-element/decorators/query-assigned-nodes.js";import"../../../node_modules/lit/decorators.js";import{html as a,nothing as o}from"../../../node_modules/lit-html/lit-html.js";import{LitElement as s}from"../../../node_modules/lit-element/lit-element.js";import"../../../node_modules/lit/index.js";import{classMap as c}from"../../../node_modules/lit-html/directives/class-map.js";import"../../../node_modules/lit/directives/class-map.js";import{composeMixin as l}from"../../../utils/compose-mixin/compose-mixin.js";import u from"../../../_virtual/_@oxc-project_runtime@0.144.0/helpers/esm/decorate.js";import{mixinDelegatesAria as d}from"../../../utils/aria/delegate.js";import{mixinFocusRingOptions as f}from"../../focus-ring/focus-ring-options.mixin.js";import{mixinRippleOptions as p}from"../../ripple/ripple-options.mixin.js";import{LIST_ITEM_REQUEST_ACTIVATION_EVENT as m}from"../list.interface.js";import{ListItemStyles as h}from"./list-item.style.js";
/**
* @license
* Copyright 2026 Kai-Orion & Sandlada
* SPDX-License-Identifier: MIT
*
* @fileoverview
* Internal base class for `mdc-list-item` — a single MD3 list row.
*
* The item renders one of three native roots depending on `type`:
*
* - `link` → `<a>` (navigates to `href`, forced when `href` is set)
* - `button` → `<button>` (activates on Enter / Space / click)
* - `text` → `<li>` (non-interactive; hosts a `control` slot, e.g. checkbox)
*
* Interactive items wire `mixinRippleOptions` / `mixinFocusRingOptions` to the
* root element. On activation the item dispatches a composed
* `request-activation` event so the parent `mdc-list` can promote it to the
* roving tabindex slot.
*
* Visual structure (mirrors @material/web `<md-item>`):
*
* [leading: control + start] [content: overline / headline / supporting-text /
* trailing-supporting-text] [end]
*/
var g=class extends l(d,p,f)(s){static{this.styles=h}static{this.shadowRootOptions={...s.shadowRootOptions,delegatesFocus:!0}}get isInteractive(){return this.type!==`text`}get isDisabled(){return this.disabled&&this.type!==`link`}get rippleControl(){return this.isInteractive?this.rootElement:null}get focusRingControl(){return this.isInteractive?this.rootElement:null}constructor(){super(),this.type=`text`,this.disabled=!1,this.href=``,this.target=``,this.selected=!1,this.listTabIndex=0,this.hasControl=!1,this.hasStart=!1,this.hasOverline=!1,this.hasHeadline=!1,this.hasSupportingText=!1,this.hasTrailingSupportingText=!1,this.hasEnd=!1,this.handleControlSlotChange=()=>{this.hasControl=this.assignedControls.length>0},this.handleStartSlotChange=()=>{this.hasStart=this.assignedStarts.length>0},this.handleOverlineSlotChange=()=>{this.hasOverline=this.assignedOverlines.length>0},this.handleHeadlineSlotChange=()=>{this.hasHeadline=this.assignedHeadlines.length>0},this.handleSupportingTextSlotChange=()=>{this.hasSupportingText=this.assignedSupportingTexts.length>0},this.handleTrailingSupportingTextSlotChange=()=>{this.hasTrailingSupportingText=this.assignedTrailingSupportingTexts.length>0},this.handleEndSlotChange=()=>{this.hasEnd=this.assignedEnds.length>0},this.handleDefaultSlotChange=()=>{this.hasHeadline=this.assignedHeadlines.length>0||this.assignedDefaultNodes.length>0},this.handleActivation=e=>{if(this.isDisabled){e.preventDefault();return}this.dispatchEvent(new CustomEvent(m,{detail:{item:this},bubbles:!0,composed:!0}))},this.focusRingInward=!0}willUpdate(e){super.willUpdate(e),this.href&&(this.type=`link`)}getRenderClasses(){return{container:!0,[this.type]:!0,disabled:this.isDisabled,selected:this.selected,"one-line":!this.hasOverline&&!this.hasSupportingText,"two-line":!this.hasOverline&&this.hasSupportingText,"three-line":this.hasOverline,"has-control":this.hasControl,"has-start":this.hasStart,"has-overline":this.hasOverline,"has-headline":this.hasHeadline,"has-supporting-text":this.hasSupportingText,"has-trailing-supporting-text":this.hasTrailingSupportingText,"has-end":this.hasEnd}}render(){let{ariaLabel:e}=this,t=c(this.getRenderClasses()),n=this.isDisabled||!this.isInteractive?-1:this.listTabIndex;return this.type===`link`?a`<a class="${t}" role="listitem" href="${this.href||o}" target="${this.target||o}" aria-label="${e||o}" aria-selected="${this.selected?`true`:o}" tabindex="${n}" ="${this.handleActivation}">${this.renderSurface()} ${this.renderBody()} ${this.renderTouchTarget()}</a>`:this.type===`button`?a`<button class="${t}" type="button" role="listitem" ?disabled="${this.isDisabled}" aria-label="${e||o}" aria-selected="${this.selected?`true`:o}" tabindex="${n}" ="${this.handleActivation}">${this.renderSurface()} ${this.renderBody()} ${this.renderTouchTarget()}</button>`:a`<li class="${t}" role="listitem" tabindex="-1" aria-label="${e||o}">${this.renderBody()} ${this.renderTouchTarget()}</li>`}renderSurface(){return a`${this.renderFocusRing()} ${this.renderRipple()}`}renderBody(){return a`<div class="item"><div class="leading"><slot name="control" ="${this.handleControlSlotChange}"></slot><slot name="start" ="${this.handleStartSlotChange}"></slot></div><div class="content"><div class="overline"><slot name="overline" ="${this.handleOverlineSlotChange}"></slot></div><div class="headline"><slot name="headline" ="${this.handleHeadlineSlotChange}"></slot><slot ="${this.handleDefaultSlotChange}"></slot></div><div class="supporting-text"><slot name="supporting-text" ="${this.handleSupportingTextSlotChange}"></slot></div><div class="trailing-supporting-text"><slot name="trailing-supporting-text" ="${this.handleTrailingSupportingTextSlotChange}"></slot></div></div><div class="end"><slot name="end" ="${this.handleEndSlotChange}"></slot></div></div>`}renderTouchTarget(){return a`<span class="touch-target" aria-hidden="true"></span>`}focus(){this.rootElement?.focus()}click(){this.rootElement?.click()}};u([e({type:String,reflect:!0})],g.prototype,`type`,void 0),u([e({type:Boolean,reflect:!0})],g.prototype,`disabled`,void 0),u([e({type:String,reflect:!0})],g.prototype,`href`,void 0),u([e({type:String,reflect:!0})],g.prototype,`target`,void 0),u([e({type:Boolean,reflect:!0})],g.prototype,`selected`,void 0),u([e({type:Number})],g.prototype,`listTabIndex`,void 0),u([t()],g.prototype,`hasControl`,void 0),u([t()],g.prototype,`hasStart`,void 0),u([t()],g.prototype,`hasOverline`,void 0),u([t()],g.prototype,`hasHeadline`,void 0),u([t()],g.prototype,`hasSupportingText`,void 0),u([t()],g.prototype,`hasTrailingSupportingText`,void 0),u([t()],g.prototype,`hasEnd`,void 0),u([n(`.container`)],g.prototype,`rootElement`,void 0),u([r({slot:`control`,flatten:!0})],g.prototype,`assignedControls`,void 0),u([r({slot:`start`,flatten:!0})],g.prototype,`assignedStarts`,void 0),u([r({slot:`overline`,flatten:!0})],g.prototype,`assignedOverlines`,void 0),u([r({slot:`headline`,flatten:!0})],g.prototype,`assignedHeadlines`,void 0),u([r({slot:`supporting-text`,flatten:!0})],g.prototype,`assignedSupportingTexts`,void 0),u([r({slot:`trailing-supporting-text`,flatten:!0})],g.prototype,`assignedTrailingSupportingTexts`,void 0),u([r({slot:`end`,flatten:!0})],g.prototype,`assignedEnds`,void 0),u([i({flatten:!0})],g.prototype,`assignedDefaultNodes`,void 0);export{g as BaseListItem};
//# sourceMappingURL=base-list-item.js.map