@freshworks/crayons
Version:
Crayons Web Components library
280 lines (274 loc) • 10.4 kB
JavaScript
import { attachShadow, createEvent, h, Host, proxyCustomElement } from '@stencil/core/internal/client';
/* tslint:enable */
// function to parse string or array as input and return the array state value
function validateAndParseInputSelectedValues(inputValue) {
let arrParsedValues = [];
let boolArrayInput = false;
const strParsedValues = inputValue ? inputValue.toString() : '';
if (inputValue) {
boolArrayInput = Array.isArray(inputValue) ? true : false;
if (boolArrayInput) {
arrParsedValues = [...inputValue];
}
else {
arrParsedValues =
strParsedValues !== '' ? strParsedValues.split(',') : [];
}
}
return {
isArray: boolArrayInput,
strSelectedValues: strParsedValues,
arrSelectedValues: arrParsedValues,
};
}
// function to return the selected values
function updateSelectedValues(arrChildElements = null, intSelectedIndex = -1, boolSelected = true, boolMultipleSelection = false, arrSelectedValues = null) {
// Check if the values passed for setting the selected index and child elements array are valid
if (intSelectedIndex < 0 ||
!arrChildElements ||
arrChildElements.length <= 0 ||
intSelectedIndex > arrChildElements.length - 1) {
return arrSelectedValues;
}
if (!arrSelectedValues) {
arrSelectedValues = [];
}
const strValue = arrChildElements[intSelectedIndex].value;
const isValueStored = arrSelectedValues.length > 0 ? arrSelectedValues.includes(strValue) : false;
// if loop to deselect the child item provided multiple selection is allowed
if (!boolSelected && boolMultipleSelection && isValueStored) {
let intSelectedChildIndex = -1;
const intLength = arrSelectedValues.length;
for (let i1 = 0; i1 < intLength; i1++) {
if (arrSelectedValues[i1] === strValue) {
intSelectedChildIndex = i1;
break;
}
}
// remove the selected item from the selected items array
arrSelectedValues = [
...arrSelectedValues.slice(0, intSelectedChildIndex),
...arrSelectedValues.slice(intSelectedChildIndex + 1),
];
}
else if (boolSelected && !isValueStored) {
if (boolMultipleSelection) {
arrSelectedValues = [...arrSelectedValues, strValue];
}
else {
arrSelectedValues = [strValue];
}
}
return arrSelectedValues;
}
// function to update the selected state of the child - for both multiple selection and radio group support - based on the passed values argument
function updateChildSelectionState(arrChildElements = null, boolMultipleSelection = false, arrSelectedValues = null, boolSetCheckboxType = false) {
if (!arrChildElements || arrChildElements.length === 0) {
return -1;
}
let numSelectedIndex = -1;
let boolFirstItemSetSelected = false;
const intLength = arrChildElements.length;
for (let i1 = 0; i1 < intLength; i1++) {
const elChild = arrChildElements[i1];
const strChildValue = elChild.value;
elChild.index = i1;
if (boolSetCheckboxType) {
elChild.isCheckbox = boolMultipleSelection;
}
const boolItemSelected = arrSelectedValues && arrSelectedValues.includes(strChildValue)
? true
: false;
let boolApplySelection = boolItemSelected;
if (!boolMultipleSelection) {
if (!boolFirstItemSetSelected && boolItemSelected) {
boolFirstItemSetSelected = true;
boolApplySelection = true;
}
else {
boolApplySelection = false;
}
}
elChild.selected = boolApplySelection;
if (boolApplySelection && numSelectedIndex === -1) {
numSelectedIndex = i1;
elChild.setAttribute('tabindex', '0');
}
else {
elChild.setAttribute('tabindex', '-1');
}
}
return numSelectedIndex;
}
// function to validate the arrow and select the susequent children based on key press
function doKeyDownOperations(keyCode, arrChildElements = null, intCurrentIndex = 0, boolMultipleSelection = false) {
// check for the valid children
if (!arrChildElements || arrChildElements.length === 0) {
return { index: intCurrentIndex, changeSelection: false, selected: false };
}
if (intCurrentIndex < 0) {
intCurrentIndex = 0;
}
switch (keyCode) {
case 'ArrowDown':
case 'ArrowRight':
arrChildElements[intCurrentIndex].setAttribute('tabindex', '-1');
// set currently selectedIndex using roving tabindex technique
intCurrentIndex = ++intCurrentIndex % arrChildElements.length;
arrChildElements[intCurrentIndex].setAttribute('tabindex', '0');
arrChildElements[intCurrentIndex].setFocus();
break;
case 'ArrowUp':
case 'ArrowLeft':
arrChildElements[intCurrentIndex].setAttribute('tabindex', '-1');
intCurrentIndex =
intCurrentIndex === 0 ? arrChildElements.length - 1 : --intCurrentIndex;
arrChildElements[intCurrentIndex].setAttribute('tabindex', '0');
arrChildElements[intCurrentIndex].setFocus();
break;
case 'Enter':
case 'Space': {
arrChildElements[intCurrentIndex].setFocus();
const boolCurrentItemSelection = arrChildElements[intCurrentIndex].selected;
// return if multiple selection in the group is not allowed and the item is already selected
if (!boolMultipleSelection && boolCurrentItemSelection) {
return;
}
const boolApplySelectState = boolMultipleSelection
? !boolCurrentItemSelection
: true;
return {
index: intCurrentIndex,
changeSelection: true,
selected: boolApplySelectState,
};
}
}
return {
index: intCurrentIndex,
changeSelection: false,
selected: false,
};
}
const toggleGroupCss = ":host{font-family:var(--fw-font-family, -apple-system, blinkmacsystemfont, \"Segoe UI\", roboto, oxygen, ubuntu, cantarell, \"Open Sans\", \"Helvetica Neue\", sans-serif);-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;-webkit-box-sizing:border-box;box-sizing:border-box}:host{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;padding:0;gap:12px}";
let ToggleGroup = class extends HTMLElement {
constructor() {
super();
this.__registerHost();
attachShadow(this);
this.fwChange = createEvent(this, "fwChange", 7);
this.selectedIndex = -1;
this.isInputFormatArray = false;
/**
* Boolean value to allow multiple selection or single child selection
*/
this.multiple = false;
/**
* Selected items to be shown - stored in array format - if property "multiple" is set to false, this will always be a single value array
*/
this.value = null;
/**
* Internal state of array items store the selected items
*/
this.arrSelectedItems = null;
/**
* Label for the component, that can be used by screen readers.
*/
this.label = '';
/**
* Name of the component, saved as part of form data.
*/
this.name = '';
}
// public method to set selected values
async setSelectedValues(values) {
this.value = values;
}
watchSelectedValuesChangeHandler() {
this.parseSelectedItems();
this.updateSelection();
}
keyupHandler(event) {
const arrChildren = this.arrChildElements;
if (!arrChildren || arrChildren.length === 0) {
return;
}
const objResponse = doKeyDownOperations(event.code, this.arrChildElements, this.selectedIndex, this.multiple);
this.selectedIndex = objResponse.index;
if (objResponse.changeSelection) {
const arrUpdatedSelectionItems = updateSelectedValues(arrChildren, this.selectedIndex, objResponse.selected, this.multiple, this.arrSelectedItems);
this.arrSelectedItems = [...arrUpdatedSelectionItems];
this.dispatchSelectionChangeEvent();
}
}
toggleChangeHandler(event) {
const objDetail = event.detail;
this.selectedIndex = objDetail.index;
const arrUpdatedSelectionItems = updateSelectedValues(this.arrChildElements, this.selectedIndex, objDetail.selected, this.multiple, this.arrSelectedItems);
this.arrSelectedItems = arrUpdatedSelectionItems;
this.dispatchSelectionChangeEvent();
}
componentWillLoad() {
this.parseSelectedItems();
}
componentDidLoad() {
const elHost = this.host;
this.arrChildElements = elHost.children;
this.updateSelection(true);
}
dispatchSelectionChangeEvent() {
const strDispatchSelectedValues = this.arrSelectedItems.toString();
if (strDispatchSelectedValues !== this.value) {
this.value = strDispatchSelectedValues;
this.fwChange.emit({
value: !this.isInputFormatArray
? strDispatchSelectedValues
: [...this.arrSelectedItems],
});
}
}
parseSelectedItems() {
const objResponse = validateAndParseInputSelectedValues(this.value);
if (this.value !== objResponse.strSelectedValues) {
this.value = objResponse.strSelectedValues;
}
this.isInputFormatArray = objResponse.isArray;
this.arrSelectedItems = objResponse.arrSelectedValues;
}
updateSelection(boolSetRadioCheckboxType = false) {
const intUpdatedIndex = updateChildSelectionState(this.arrChildElements, this.multiple, this.arrSelectedItems, boolSetRadioCheckboxType);
// for the first time when the component is loaded and the selectedIndex is not set
if (intUpdatedIndex !== -1 && this.selectedIndex === -1) {
this.selectedIndex = intUpdatedIndex;
}
}
render() {
return (h(Host, { "aria-label": this.label }, h("slot", null)));
}
get host() { return this; }
static get watchers() { return {
"value": ["watchSelectedValuesChangeHandler"]
}; }
static get style() { return toggleGroupCss; }
};
ToggleGroup = /*@__PURE__*/ proxyCustomElement(ToggleGroup, [1, "fw-toggle-group", {
"multiple": [4],
"value": [1032],
"label": [1],
"name": [1],
"arrSelectedItems": [32],
"setSelectedValues": [64]
}, [[0, "keyup", "keyupHandler"], [0, "fwToggled", "toggleChangeHandler"]]]);
function defineCustomElement$1() {
const components = ["fw-toggle-group"];
components.forEach(tagName => { switch (tagName) {
case "fw-toggle-group":
if (!customElements.get(tagName)) {
customElements.define(tagName, ToggleGroup);
}
break;
} });
}
const FwToggleGroup = ToggleGroup;
const defineCustomElement = defineCustomElement$1;
export { FwToggleGroup, defineCustomElement };