feat(catalog): add admin dashboard components
This commit is contained in:
@@ -0,0 +1,119 @@
|
||||
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>
|
||||
`;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user