@sandlada/mdc
Version:
@sandlada/mdc is an open source component library that follows the Material Design 3 design specifications.
21 lines • 5.28 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{SEGMENTED_BUTTON_INTERACTION_EVENT as m}from"../segmented-button.interface.js";import{SegmentedButtonStyles as h}from"./segmented-button.style.js";
/**
* @license
* Copyright 2026 Kai-Orion & Sandlada
* SPDX-License-Identifier: MIT
*
* @fileoverview
* Internal base class for `mdc-segmented-button` — a single selectable segment.
*
* A segment is a pure view: it renders a native `<button>` (the focusable,
* accessible element) holding the optional icon, label and — when selected —
* an animated checkmark. Selection state is owned by the parent
* `mdc-segmented-button-set`; on pointer / keyboard activation the segment
* only reports the `segmented-button-interaction` event and the set decides
* whether the selection commits.
*
* Ripple and focus-ring are wired to the inner button via
* `mixinRippleOptions` / `mixinFocusRingOptions`.
*/
var g=class extends l(d,p,f)(s){static{this.styles=h}get rippleControl(){return this.buttonElement}get focusRingControl(){return this.buttonElement}constructor(){super(),this.selected=!1,this.disabled=!1,this.noCheckmark=!1,this.hasIcon=!1,this.hasLabel=!1,this.animState=``,this.handleClick=()=>{this.disabled||this.dispatchEvent(new Event(m,{bubbles:!0,composed:!0}))},this.handleIconSlotChange=()=>{this.hasIcon=this.assignedIcons.length>0},this.handleLabelSlotChange=()=>{let e=!1;for(let t of this.assignedDefaultNodes){let n=t.nodeType===Node.TEXT_NODE&&!!t.wholeText.match(/\S/);if(t.nodeType===Node.ELEMENT_NODE||n){e=!0;break}}this.hasLabel=e},this.addEventListener(`click`,this.handleClick)}getRenderClasses(){return{container:!0,selected:this.selected,unselected:!this.selected,"with-label":this.hasLabel,"without-label":!this.hasLabel,"with-icon":this.hasIcon,"without-icon":!this.hasIcon,"with-checkmark":!this.noCheckmark,"without-checkmark":this.noCheckmark,selecting:this.animState===`selecting`,deselecting:this.animState===`deselecting`,disabled:this.disabled}}willUpdate(e){if(super.willUpdate(e),e.has(`selected`)){let t=e.get(`selected`),n=!this.noCheckmark;this.animState=t===!1&&this.selected&&n?`selecting`:t===!0&&!this.selected&&n?`deselecting`:``}}render(){let{ariaLabel:e}=this;return a`<button class="${c(this.getRenderClasses())}" tabindex="${this.disabled?-1:0}" ?disabled="${this.disabled}" aria-pressed="${this.selected}" aria-label="${e||o}">${this.renderFocusRing()} ${this.renderRipple()} ${this.renderOutline()} ${this.renderLeading()} ${this.renderLabel()} ${this.renderTouchTarget()}</button>`}renderOutline(){return a`<span class="outline" aria-hidden="true"></span>`}renderLeading(){return a`<span class="leading" aria-hidden="true">${this.hasLabel?a`<span class="graphic">${this.renderCheckmark()} ${this.renderIcon()}</span>`:a`<span class="graphic">${this.renderCheckmark()}</span> ${this.renderIcon()}`}</span>`}renderIcon(){return a`<span class="icon"><slot name="icon" ="${this.handleIconSlotChange}"></slot></span>`}renderCheckmark(){return a`<svg class="checkmark" viewBox="0 0 24 24" aria-hidden="true"><path class="checkmark-path" fill="none" d="M1.73,12.91 8.1,19.28 22.79,4.59"></path></svg>`}renderLabel(){return a`<span class="label"><slot ="${this.handleLabelSlotChange}"></slot></span>`}renderTouchTarget(){return a`<span class="touch-target" aria-hidden="true"></span>`}focus(){this.buttonElement?.focus()}blur(){this.buttonElement?.blur()}};u([e({type:Boolean,reflect:!0})],g.prototype,`selected`,void 0),u([e({type:Boolean,reflect:!0})],g.prototype,`disabled`,void 0),u([e({type:Boolean,reflect:!0,attribute:`no-checkmark`})],g.prototype,`noCheckmark`,void 0),u([t()],g.prototype,`hasIcon`,void 0),u([t()],g.prototype,`hasLabel`,void 0),u([n(`.container`)],g.prototype,`buttonElement`,void 0),u([r({slot:`icon`,flatten:!0})],g.prototype,`assignedIcons`,void 0),u([i({flatten:!0})],g.prototype,`assignedDefaultNodes`,void 0),u([t()],g.prototype,`animState`,void 0);export{g as BaseSegmentedButton};
//# sourceMappingURL=base-segmented-button.js.map