2021-07-09 20:45:44 -04:00
import { LitElement , html } from 'lit' ;
2021-05-27 17:00:43 -04:00
import { customElement , property , query } from 'lit/decorators.js' ;
2021-07-09 20:45:44 -04:00
import styles from './button-group.styles' ;
2020-08-06 09:07:24 -04:00
/ * *
* @since 2.0
* @status stable
*
2021-06-25 16:25:46 -04:00
* @slot - One or more ` <sl-button> ` elements to display in the button group .
2020-08-06 09:07:24 -04:00
*
2021-06-25 16:25:46 -04:00
* @csspart base - The component ' s base wrapper .
2020-08-06 09:07:24 -04:00
* /
2021-03-18 09:04:23 -04:00
@customElement ( 'sl-button-group' )
2021-03-08 19:14:32 -05:00
export default class SlButtonGroup extends LitElement {
2021-07-09 20:45:44 -04:00
static styles = styles ;
2020-08-06 09:07:24 -04:00
2021-04-02 07:24:59 -04:00
@query ( 'slot' ) defaultSlot : HTMLSlotElement ;
2020-09-04 17:11:25 -04:00
/** A label to use for the button group's `aria-label` attribute. */
2021-06-30 20:04:46 -04:00
@property ( ) label = '' ;
2020-08-06 09:07:24 -04:00
handleFocus ( event : CustomEvent ) {
2021-04-02 07:24:59 -04:00
const button = findButton ( event . target as HTMLElement ) ;
button ? . classList . add ( 'sl-button-group__button--focus' ) ;
2020-08-06 09:07:24 -04:00
}
handleBlur ( event : CustomEvent ) {
2021-04-02 07:24:59 -04:00
const button = findButton ( event . target as HTMLElement ) ;
button ? . classList . remove ( 'sl-button-group__button--focus' ) ;
}
handleMouseOver ( event : CustomEvent ) {
const button = findButton ( event . target as HTMLElement ) ;
button ? . classList . add ( 'sl-button-group__button--hover' ) ;
}
handleMouseOut ( event : CustomEvent ) {
const button = findButton ( event . target as HTMLElement ) ;
button ? . classList . remove ( 'sl-button-group__button--hover' ) ;
}
handleSlotChange() {
const slottedElements = [ . . . this . defaultSlot . assignedElements ( { flatten : true } ) ] as HTMLElement [ ] ;
2022-01-15 21:47:14 -08:00
slottedElements . forEach ( el = > {
2021-04-02 07:24:59 -04:00
const index = slottedElements . indexOf ( el ) ;
const button = findButton ( el ) ;
2022-01-15 21:47:14 -08:00
if ( button !== null ) {
2021-04-02 07:24:59 -04:00
button . classList . add ( 'sl-button-group__button' ) ;
button . classList . toggle ( 'sl-button-group__button--first' , index === 0 ) ;
button . classList . toggle ( 'sl-button-group__button--inner' , index > 0 && index < slottedElements . length - 1 ) ;
button . classList . toggle ( 'sl-button-group__button--last' , index === slottedElements . length - 1 ) ;
}
} ) ;
2020-08-06 09:07:24 -04:00
}
render() {
2022-01-15 21:47:14 -08:00
// eslint-disable-next-line lit-a11y/mouse-events-have-key-events -- focusout & focusin support bubbling where as focus & blur do not which is necessary here
2021-02-26 09:09:13 -05:00
return html `
< div
part = "base"
class = "button-group"
2021-04-01 07:50:27 -04:00
role = "group"
2021-02-26 09:09:13 -05:00
aria - label = $ { this . label }
2021-03-06 12:01:39 -05:00
@focusout = $ { this . handleBlur }
@focusin = $ { this . handleFocus }
2021-04-02 07:24:59 -04:00
@mouseover = $ { this . handleMouseOver }
@mouseout = $ { this . handleMouseOut }
2021-02-26 09:09:13 -05:00
>
2021-04-02 07:24:59 -04:00
< slot @ slotchange = $ { this.handleSlotChange } > < / slot >
2020-08-06 09:07:24 -04:00
< / div >
2021-02-26 09:09:13 -05:00
` ;
2020-08-06 09:07:24 -04:00
}
}
2021-03-12 15:07:38 +01:00
2021-04-02 07:24:59 -04:00
function findButton ( el : HTMLElement ) {
return el . tagName . toLowerCase ( ) === 'sl-button' ? el : el.querySelector ( 'sl-button' ) ;
}
2021-03-12 09:09:08 -05:00
declare global {
interface HTMLElementTagNameMap {
'sl-button-group' : SlButtonGroup ;
}
}