import { LitElement, html, css } from 'lit';
import { property } from 'lit/decorators.js';
export type KbdVariant = 'default' | 'primary' | 'secondary' | 'info' | 'warning' | 'success' | 'danger' | 'error' | 'monochrome';
export type KbdSize = 'sm' | 'md' | 'lg';
export interface KbdProps {
variant?: KbdVariant;
bordered?: boolean;
background?: boolean;
size?: KbdSize;
}
export class AgKbd extends LitElement implements KbdProps {
@property({ type: String, reflect: true }) declare variant: KbdVariant;
@property({ type: Boolean, reflect: true }) declare bordered: boolean;
@property({ type: Boolean, reflect: true }) declare background: boolean;
@property({ type: String, reflect: true }) declare size: KbdSize;
constructor() {
super();
this.variant = 'default';
this.bordered = true;
this.background = false;
this.size = 'md';
}
static styles = css`
:host {
display: inline-flex;
font-family: monospace;
font-size: var(--ag-font-size-sm);
}
.kbd-wrapper {
display: inline-flex;
align-items: center;
justify-content: center;
border-radius: var(--ag-radius-md);
white-space: nowrap;
user-select: none;
}
:host([bordered]) .kbd-wrapper {
border: var(--ag-border-width-1) solid var(--ag-border-subtle);
}
:host([background]) .kbd-wrapper {
background-color: var(--ag-background-secondary);
}
/* Sizes */
:host([size='sm']) .kbd-wrapper {
padding: var(--ag-space-1);
font-size: var(--ag-font-size-sm);
}
:host([size='md']) .kbd-wrapper {
padding: var(--ag-space-2);
font-size: var(--ag-font-size-md);
}
:host([size='lg']) .kbd-wrapper {
padding: var(--ag-space-3);
font-size: var(--ag-font-size-lg);
}
/* Square aspect ratio for single characters - note we bump up
the size for single character */
:host([size='sm'][single-char]) .kbd-wrapper {
padding: 2px;
width: 1.25rem;
height: 1.25rem;
font-size: var(--ag-font-size-md);
}
:host([size='md'][single-char]) .kbd-wrapper {
padding: 2px;
width: 1.5rem;
height: 1.5rem;
font-size: var(--ag-font-size-lg);
}
:host([size='lg'][single-char]) .kbd-wrapper {
padding: 3px;
width: 1.875rem;
height: 1.875rem;
font-size: var(--ag-font-size-xl);
}
/* Variants */
:host([variant='default']) .kbd-wrapper {
color: var(--ag-text-primary);
}
:host([variant='primary']) .kbd-wrapper {
color: var(--ag-primary-text);
border-color: var(--ag-primary);
}
:host([variant='primary'][background]) .kbd-wrapper {
background-color: var(--ag-primary-background);
}
:host([variant='secondary']) .kbd-wrapper {
color: var(--ag-text-secondary);
border-color: var(--ag-secondary);
}
:host([variant='secondary'][background]) .kbd-wrapper {
background-color: var(--ag-secondary-background);
}
:host([variant='info']) .kbd-wrapper {
color: var(--ag-info-text);
border-color: var(--ag-info);
}
:host([variant='info'][background]) .kbd-wrapper {
background-color: var(--ag-info-background);
}
:host([variant='warning']) .kbd-wrapper {
color: var(--ag-warning-text);
border-color: var(--ag-warning);
}
:host([variant='warning'][background]) .kbd-wrapper {
background-color: var(--ag-warning-background);
}
:host([variant='success']) .kbd-wrapper {
color: var(--ag-success-text);
border-color: var(--ag-success);
}
:host([variant='success'][background]) .kbd-wrapper {
background-color: var(--ag-success-background);
}
:host([variant='danger']) .kbd-wrapper {
color: var(--ag-danger-text);
border-color: var(--ag-danger);
}
:host([variant='danger'][background]) .kbd-wrapper {
background-color: var(--ag-danger-background);
}
:host([variant='error']) .kbd-wrapper {
color: var(--ag-danger-text);
border-color: var(--ag-danger);
}
:host([variant='error'][background]) .kbd-wrapper {
background-color: var(--ag-danger-background);
}
:host([variant='monochrome']) .kbd-wrapper {
color: var(--ag-text-primary);
border-color: var(--ag-text-primary);
}
:host([variant='monochrome'][background]) .kbd-wrapper {
background-color: var(--ag-background-primary-inverted);
color: var(--ag-text-primary-inverted);
}
`;
updated(changedProperties: Map) {
super.updated(changedProperties);
this._checkSingleChar();
}
private _checkSingleChar() {
let text = '';
const slot = this.shadowRoot?.querySelector('slot');
if (slot) {
const nodes = slot.assignedNodes({ flatten: true });
text = nodes.map(node => node.textContent || '').join('');
}
text = text.trim();
if (text.length === 1) {
this.setAttribute('single-char', 'true');
} else {
this.removeAttribute('single-char');
}
}
private _onSlotChange() {
this._checkSingleChar();
}
render() {
return html`
`;
}
}