coveo-search-ui-extensions
Version:
Small generic components to extend the functionality of Coveo's Search UI framework.
96 lines • 4.54 kB
JavaScript
import { ActionButton } from './ActionButton';
/**
* An action button able to handle multiple states and their transitions.
*/
export class StatefulActionButton {
constructor(element, options, bindings) {
var _a;
this.element = element;
this.options = options;
this.bindings = bindings;
const optionsValidity = this.checkOptionsValidity();
if (!optionsValidity.areValid) {
console.warn(`Cannot render the stateful action button because options are invalid.\n\t${optionsValidity.errorMessage}`);
return;
}
this.currentState = this.options.initialState;
(_a = this.currentState.onStateEntry) === null || _a === void 0 ? void 0 : _a.apply(this);
this.innerActionButton = new ActionButton(element, Object.assign(Object.assign({}, this.options.initialState), { click: this.handleClick.bind(this) }), bindings);
}
/**
* Switch the state of the instance if the state and the transition between the current and new state are allowed.
* @param state a state to try to switch to
*/
switchTo(state) {
if (this.options.states.indexOf(state) === -1) {
console.warn(`State '${state.name}' does not exist on this StatefulActionButton\nEnsure to use the object references used at the instantiation.`);
return;
}
if (!this.isTransitionAllowed(state)) {
console.warn(`Transition from State '${this.currentState.name}' to State '${state.name}' is not allowed on this StatefulActionButton.\nEnsure to use the object references used at the instantiation.`);
return;
}
const [oldStateExit, newStateEntry] = [this.currentState.onStateExit, state.onStateEntry];
this.innerActionButton.updateIcon(state.icon);
this.innerActionButton.updateTooltip(state.tooltip);
this.currentState = state;
oldStateExit === null || oldStateExit === void 0 ? void 0 : oldStateExit.call(this);
newStateEntry === null || newStateEntry === void 0 ? void 0 : newStateEntry.call(this);
}
/**
* Return the current state of the instance.
*/
getCurrentState() {
return this.currentState;
}
/**
* Check if the options given to the constructor are valid.
* If not, it will also display the appropriate warning.
*/
checkOptionsValidity() {
var _a;
if (!((_a = this.options.states) === null || _a === void 0 ? void 0 : _a.length)) {
return { areValid: false, errorMessage: 'States is not defined or empty.' };
}
if (!this.options.initialState) {
return { areValid: false, errorMessage: 'InitialState is not defined.' };
}
if (this.options.states.indexOf(this.options.initialState) < 0) {
return { areValid: false, errorMessage: 'InitialState is not in the list of state.' };
}
return !this.options.allowedTransitions ? { areValid: true } : this.areTransitionsValid();
}
areTransitionsValid() {
for (let index = 0; index < this.options.allowedTransitions.length; index++) {
const transition = this.options.allowedTransitions[index];
if (this.options.states.indexOf(transition.from) === -1) {
return { areValid: false, errorMessage: this.generateInvalidTransitionMessage(index, true) };
}
if (this.options.states.indexOf(transition.to) === -1) {
return { areValid: false, errorMessage: this.generateInvalidTransitionMessage(index, false) };
}
}
return { areValid: true };
}
generateInvalidTransitionMessage(transitionNumber, isOrigin) {
return `${isOrigin ? 'Origin' : 'Destination'} of Transition #${transitionNumber} is not in the list of states. Ensure to use the same object reference as in the options.states.`;
}
/**
* Check if a transition from the current state to @param state is allowed.
* @param state the destination of the transition
*/
isTransitionAllowed(state) {
if (!this.options.allowedTransitions) {
return true;
}
return this.options.allowedTransitions.some((transition) => transition.from === this.currentState && transition.to === state);
}
/**
* Handle user click.
*/
handleClick() {
this.currentState.click();
}
}
StatefulActionButton.ID = 'StatefulActionButton';
//# sourceMappingURL=StatefulActionButton.js.map