Files
catalog/ts_web/elements/idp-select.ts
T

120 lines
3.2 KiB
TypeScript
Raw Normal View History

import { DeesElement, html, property, customElement, css, type TemplateResult } from '@design.estate/dees-element';
import { idpElementStyles } from './tokens.js';
export interface IIdpSelectOption {
option: string;
key: string;
payload?: string;
}
export interface IIdpSelectEventDetail {
key: string;
payload?: string;
selectedOption: IIdpSelectOption | null;
}
declare global {
interface HTMLElementTagNameMap {
'idp-select': IdpSelect;
}
}
@customElement('idp-select')
export class IdpSelect extends DeesElement {
public static demo = () => html`
<idp-select
label="Organization"
.options=${[
{ option: 'Lossless GmbH', key: 'lossless', payload: 'lossless' },
{ option: '+ Create new...', key: '__create_new__', payload: '__create_new__' },
]}
></idp-select>
`;
public static demoGroups = ['idp.global v3 primitives'];
@property({ type: String })
public accessor label = '';
@property({ type: String })
public accessor placeholder = 'Select...';
@property({ type: Array })
public accessor options: IIdpSelectOption[] = [];
@property({ type: Object })
public accessor selectedOption: IIdpSelectOption | null = null;
@property({ type: Boolean, reflect: true })
public accessor disabled = false;
public static styles = [
...idpElementStyles,
css`
:host {
display: block;
}
label {
display: grid;
gap: 6px;
}
.label {
color: var(--idp-fg);
font-size: 13px;
font-weight: 500;
}
select {
width: 100%;
height: 36px;
box-sizing: border-box;
padding: 0 34px 0 10px;
border: 1px solid var(--idp-border);
border-radius: 8px;
outline: none;
background: var(--idp-card);
color: var(--idp-fg);
font-family: var(--idp-font);
font-size: 13px;
cursor: pointer;
transition: border-color 120ms ease, box-shadow 120ms ease;
}
select:focus {
border-color: var(--idp-accent);
box-shadow: 0 0 0 3px color-mix(in srgb, var(--idp-accent), transparent 86%);
}
select:disabled {
cursor: not-allowed;
opacity: 0.5;
}
`,
];
private handleChange(eventArg: Event) {
const key = (eventArg.target as HTMLSelectElement).value;
const selectedOption = this.options.find((optionArg) => optionArg.key === key) || null;
this.selectedOption = selectedOption;
this.dispatchEvent(new CustomEvent<IIdpSelectEventDetail>('idp-select', {
detail: {
key,
payload: selectedOption?.payload,
selectedOption,
},
bubbles: true,
composed: true,
}));
}
public render(): TemplateResult {
return html`
<label>
${this.label ? html`<span class="label">${this.label}</span>` : html``}
<select .value=${this.selectedOption?.key || ''} ?disabled=${this.disabled} @change=${this.handleChange}>
<option value="" disabled>${this.placeholder}</option>
${this.options.map((optionArg) => html`
<option value=${optionArg.key}>${optionArg.option}</option>
`)}
</select>
</label>
`;
}
}