import {
FSelect,
FSelectArray,
FSelectOptionObject,
FSelectOptionsGroup,
FSelectOptionsProp,
FSelectSingleOption
} from "./f-select";
import { html } from "lit";
import { classMap } from "lit-html/directives/class-map.js";
import { unsafeSVG } from "lit-html/directives/unsafe-svg.js";
import loader from "../../mixins/svg/loader";
export default function render(this: FSelect) {
this.validateProperties();
let selectedOptionsLength = 0;
if (Array.isArray(this.selectedOptions)) {
selectedOptionsLength = this.selectedOptions.length;
} else if (this.selectedOptions) {
selectedOptionsLength = Object.keys(this.selectedOptions).length;
}
let filteredOptionsLength = 0;
if (Array.isArray(this.filteredOptions)) {
filteredOptionsLength = this.filteredOptions.length;
} else if (this.selectedOptions) {
filteredOptionsLength = Object.keys(this.filteredOptions).length;
}
/**
* apply width according to the prop
*/
if (this.width === "fill-container") {
this.style.width = "100%";
} else {
this.style.width = `${this.width}px` ?? "100%";
}
/**
* concaticated array from groups
*/
const concatinatedSelectedOptions = !Array.isArray(this.selectedOptions)
? this.getConcaticateGroupOptions(this.selectedOptions)
: [];
/**
* create iconlLeft if available
*/
const iconLeft = this.iconLeft
? html`
`
: "";
/**
* create caret-up/caret-down icon for open/close option-menu
*/
const iconRight = !this.openDropdown
? html``
: html``;
/**
* input text area with alternate f-text placeholder when not searchable
*/
const inputAppend = html`
${selectedOptionsLength === 0 && concatinatedSelectedOptions?.length === 0 && !this.searchable
? html`${this.placeholder}`
: ""}
0 || concatinatedSelectedOptions?.length > 0
? this.searchable && this.openDropdown
? this.placeholder
: ""
: this.placeholder}
size=${this.size}
?readonly=${!this.searchable}
.value=${this.searchValue}
@input=${this.handleInput}
@blur=${this.handleBlur}
style="${this.applyInputStyle()}"
/>
`;
/**
* append prefix consisting of f-tags, iiconLeft and search string
*/
const prefixAppend = html`
${this.iconLeft ? html` ${iconLeft}` : ""}
${Array.isArray(this.selectedOptions) && selectedOptionsLength > 0
? html`
`
: html`
`}
`;
/**
* append suffix consisting of clear icon caret-up/caret-down icon and loader
*/
const suffixAppend = !this.loading
? html`
${(selectedOptionsLength > 0 || concatinatedSelectedOptions?.length > 0) && this.clear
? html`
Array.isArray(this.selectedOptions)
? this.clearInputValue(e)
: this.clearSelectionInGroups(e)}
class=${!this.size ? "f-input-icons-size" : ""}
>
`
: ""}
${iconRight}
`
: html`${unsafeSVG(loader)}
`;
/**
* empty filtered options
*/
const emptyMenu = html` {
e.stopImmediatePropagation();
e.stopPropagation();
}}
>
No Options found.
${this.createOption && this.searchValue && this.searchable
? html`
this.createNewOption(e)}
>
${this.offsetWidth > 200
? html` `
: html``}
`
: ""}
`;
/**
* Final html to render
*/
return html`
{
this.handleDropDownClose(e);
}}
>
${prefixAppend} ${suffixAppend}
${Array.isArray(this.options)
? filteredOptionsLength > 0
? (this.filteredOptions as FSelectArray)?.map(
option =>
html` {
this.handleOptionSelection(option, e);
}}
@mouseover=${(e: MouseEvent) => {
this.handleOptionMouseOver(e);
}}
.disabled=${typeof option === "object" && option.disabled}
>
${this.checkbox
? html` {
this.handleCheckboxInput(option, e);
}}
>`
: ""}
${(option as FSelectOptionObject)?.icon && !this.optionTemplate
? html` `
: ""}
${this.optionTemplate ? this.optionTemplate(option) : ""}
${!this.optionTemplate
? html` ${(option as FSelectOptionObject)?.title ?? option}`
: ""}
${this.isSelected(option) && !this.checkbox
? html` `
: ""}
`
)
: emptyMenu
: Object.keys(this.filteredOptions)?.length > 0 &&
Object.keys(this.filteredOptions)?.every(
groupName => (this.filteredOptions as FSelectOptionsGroup)[groupName].length > 0
)
? Object.keys(this.filteredOptions)?.map(group =>
(this.filteredOptions as FSelectOptionsGroup)[group].length > 0
? html`
this.handleSelectAll(e, group)}
>
${
this.checkbox
? html` this.handleSelectAll(e, group)}
>`
: ""
}
${group}
${(this.filteredOptions as FSelectOptionsGroup)[group].map(
option => html`
{
this.handleSelectionGroup(option, group, e);
}}
@mouseover=${(e: MouseEvent) => {
this.handleOptionMouseOver(e);
}}
.disabled=${typeof option === "object" && option.disabled}
>
${this.checkbox
? html` {
this.handleCheckboxGroup(option, group, e);
}}
>`
: ""}
${(option as FSelectOptionObject)?.icon && !this.optionTemplate
? html` `
: ""}
${this.optionTemplate ? this.optionTemplate(option) : ""}
${!this.optionTemplate
? html` ${(option as FSelectOptionObject)?.title ?? option}`
: ""}
${this.isGroupSelection(option, group) && !this.checkbox
? html` `
: ""}
`
)}
`
: ""
)
: emptyMenu}
`;
}
export function renderSingleSelection(this: FSelect, option: FSelectSingleOption) {
// when user accidently pass array of options in single selection
if (Array.isArray(option)) {
option = option[0];
}
const withoutTemplate = () => {
return html` ${(option as FSelectOptionObject)?.title ?? option}`;
};
const getTemplate = () => {
return this.optionTemplate ? this.optionTemplate(option, true) : withoutTemplate();
};
return html` ${getTemplate()} `;
}
export function renderMultipleSelectionTag(this: FSelect, option: FSelectSingleOption) {
const withoutTemplate = () => {
return html` {
this.handleOptionSelection(option, e);
}}
> `;
};
const getTemplate = () => {
return this.optionTemplate
? html`${this.optionTemplate(option, true)}
{
this.handleOptionSelection(option, e);
}}
category="packed"
>
`
: withoutTemplate();
};
return getTemplate();
}