@syncfusion/ej2-inputs
Version:
A package of Essential JS 2 input components such as Textbox, Color-picker, Masked-textbox, Numeric-textbox, Slider, Upload, and Form-validator that is used to get input from the users.
661 lines (660 loc) • 26.5 kB
JavaScript
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
import { NotifyPropertyChanges, Component, getUniqueID, Property, isNullOrUndefined as isNOU, Event, EventHandler, ChildProperty, Complex, removeClass, addClass, L10n } from '@syncfusion/ej2-base';
import { Button } from '@syncfusion/ej2-buttons';
import { Tooltip } from '@syncfusion/ej2-popups';
/**
* Configuration settings for the toggle button used in the SpeechToText component.
*/
var ButtonSettings = /** @class */ (function (_super) {
__extends(ButtonSettings, _super);
function ButtonSettings() {
return _super !== null && _super.apply(this, arguments) || this;
}
__decorate([
Property('')
], ButtonSettings.prototype, "content", void 0);
__decorate([
Property('')
], ButtonSettings.prototype, "stopContent", void 0);
__decorate([
Property('')
], ButtonSettings.prototype, "iconCss", void 0);
__decorate([
Property('')
], ButtonSettings.prototype, "stopIconCss", void 0);
__decorate([
Property('Left')
], ButtonSettings.prototype, "iconPosition", void 0);
__decorate([
Property(false)
], ButtonSettings.prototype, "isPrimary", void 0);
return ButtonSettings;
}(ChildProperty));
export { ButtonSettings };
/**
* Configuration settings for tooltips in the SpeechToText component.
* This allows customization of the tooltip content and its positioning.
*/
var TooltipSettings = /** @class */ (function (_super) {
__extends(TooltipSettings, _super);
function TooltipSettings() {
return _super !== null && _super.apply(this, arguments) || this;
}
__decorate([
Property('Start listening')
], TooltipSettings.prototype, "content", void 0);
__decorate([
Property('Stop listening')
], TooltipSettings.prototype, "stopContent", void 0);
__decorate([
Property('TopCenter')
], TooltipSettings.prototype, "position", void 0);
return TooltipSettings;
}(ChildProperty));
export { TooltipSettings };
/**
* Enum representing the operational states of the SpeechToText component.
*/
export var SpeechToTextState;
(function (SpeechToTextState) {
/**
* Specifies the state where the SpeechToText component is inactive and not processing spoken input.
*/
SpeechToTextState["Inactive"] = "Inactive";
/**
* Specifies the state where the SpeechToText component is actively listening to spoken input.
*/
SpeechToTextState["Listening"] = "Listening";
/**
* Specifies the state where the SpeechToText component has stopped processing spoken input.
*/
SpeechToTextState["Stopped"] = "Stopped";
})(SpeechToTextState || (SpeechToTextState = {}));
//#endregion
var SpeechToText = /** @class */ (function (_super) {
__extends(SpeechToText, _super);
//#endregion
//#region Inherited methods
/**
* Constructor for creating the component
*
* @param {SpeechToTextModel} options - Specifies the SpeechToTextModel model.
* @param {string | HTMLElement} element - Specifies the element to render as component.
* @private
*/
function SpeechToText(options, element) {
var _this = _super.call(this, options, element) || this;
_this.fullTranscript = '';
_this.isClicked = false;
_this.isUserInteracted = false;
_this.hasStarted = false;
return _this;
}
/**
* Initialize the event handler
*
* @private
* @returns {void}
*/
SpeechToText.prototype.preRender = function () {
if (!this.element.id) {
this.element.id = getUniqueID('e-' + this.getModuleName());
}
};
SpeechToText.prototype.getDirective = function () {
return 'EJS-SPEECHTOTEXT';
};
/**
* To get component name.
*
* @returns {string} - It returns the current module name.
* @private
*/
SpeechToText.prototype.getModuleName = function () {
return 'speech-to-text';
};
/**
* Get the properties to be maintained in the persisted state.
*
* @private
* @returns {string} - It returns the persisted data.
*/
SpeechToText.prototype.getPersistData = function () {
return this.addOnPersist([]);
};
SpeechToText.prototype.render = function () {
this.renderSpeechToText();
this.initializeSpeechRecognition();
if (!isNOU(this.listeningState)) {
this.handleStateChange();
}
this.wireEvents();
};
//#endregion
//#region Private Methods
SpeechToText.prototype.initializeLocale = function () {
this.l10n = new L10n(this.getModuleName(), {
abortedError: 'Speech recognition was aborted.',
audioCaptureError: 'No microphone detected. Ensure your microphone is connected.',
defaultError: 'An unknown error occurred.',
networkError: 'Network error occurred. Check your internet connection.',
noSpeechError: 'No speech detected. Please speak into the microphone.',
notAllowedError: 'Microphone access denied. Allow microphone permissions.',
serviceNotAllowedError: 'Speech recognition service is not allowed in this context.',
unsupportedBrowserError: 'The browser does not support the SpeechRecognition API.',
startAriaLabel: 'Press to start speaking and transcribe your words',
stopAriaLabel: 'Press to stop speaking and end transcription',
startTooltipText: 'Start listening',
stopTooltipText: 'Stop listening'
}, this.locale);
};
SpeechToText.prototype.renderSpeechToText = function () {
this.initializeLocale();
var iconCss = !isNOU(this.buttonSettings.iconCss) && this.buttonSettings.iconCss !== '' ? this.buttonSettings.iconCss : 'e-icons e-listen-icon';
this.buttonInst = new Button({
iconCss: iconCss,
isPrimary: this.buttonSettings.isPrimary,
cssClass: this.updateButtonCssClass(),
disabled: this.disabled,
content: this.buttonSettings.content,
iconPosition: this.buttonSettings.iconPosition,
enableRtl: this.enableRtl
});
this.buttonInst.appendTo(this.element);
this.updateTooltip();
this.updateCssClass(this.cssClass, '');
this.updateAriaLabel();
if (!isNOU(this.htmlAttributes)) {
this.addHtmlAttributes(this.htmlAttributes);
}
};
SpeechToText.prototype.updateAriaLabel = function () {
var ariaLabel;
if (this.htmlAttributes && this.htmlAttributes['aria-label']) {
ariaLabel = this.htmlAttributes['aria-label'];
}
else {
ariaLabel = this.micOn ? this.l10n.getConstant('stopAriaLabel') : this.l10n.getConstant('startAriaLabel');
}
this.element.setAttribute('aria-label', ariaLabel);
};
SpeechToText.prototype.updateCssClass = function (newClass, oldClass) {
if (oldClass) {
removeClass([this.element], oldClass.trim().split(' '));
}
if (newClass) {
addClass([this.element], newClass.trim().split(' '));
}
};
SpeechToText.prototype.updateButtonCssClass = function () {
var content = this.isClicked ? this.buttonSettings.stopContent : this.buttonSettings.content;
var cssClass;
if (content === '') {
cssClass = 'e-round';
}
if (this.micOn) {
cssClass += ' e-listening-state';
}
return cssClass;
};
SpeechToText.prototype.updateTooltip = function () {
if (this.showTooltip) {
if (this.tooltipSettings) {
if (this.tooltipSettings.content === 'Start listening') {
this.tooltipSettings.content = this.l10n.getConstant('startTooltipText');
}
if (this.tooltipSettings.stopContent === 'Stop listening') {
this.tooltipSettings.stopContent = this.l10n.getConstant('stopTooltipText');
}
}
this.tooltipInst = new Tooltip({
content: this.hasStarted ? this.tooltipSettings.stopContent : this.tooltipSettings.content,
position: this.tooltipSettings.position,
windowCollision: true,
cssClass: this.cssClass ? ('e-speech-to-text-tooltip ' + this.cssClass) : 'e-speech-to-text-tooltip',
opensOn: 'Hover',
enableRtl: this.enableRtl
});
this.tooltipInst.appendTo(this.element);
}
else {
if (!isNOU(this.tooltipInst)) {
this.tooltipInst.destroy();
this.tooltipInst = null;
}
}
};
SpeechToText.prototype.handleStateChange = function () {
if (this.disabled) {
return;
}
if (this.listeningState === SpeechToTextState.Listening) {
this.micOn = true;
this.startSpeechRecognition();
}
else if (this.listeningState === SpeechToTextState.Inactive || this.listeningState === SpeechToTextState.Stopped) {
if (this.micOn) {
this.micOn = false;
this.stopSpeechRecognition();
}
else {
var prevOnChange = this.isProtectedOnChange;
this.isProtectedOnChange = true;
this.listeningState = SpeechToTextState.Inactive;
this.isProtectedOnChange = prevOnChange;
}
}
};
SpeechToText.prototype.addHtmlAttributes = function (attrs) {
if (attrs) {
for (var attr in attrs) {
if (Object.prototype.hasOwnProperty.call(attrs, attr)) {
this.element.setAttribute(attr, attrs[attr]);
}
}
}
};
SpeechToText.prototype.removeHtmlAttributes = function (attrs) {
if (attrs) {
for (var attr in attrs) {
if (Object.prototype.hasOwnProperty.call(attrs, attr)) {
this.element.removeAttribute(attr);
}
}
}
};
SpeechToText.prototype.wireEvents = function () {
EventHandler.add(this.element, 'click', this.handleButtonClick, this);
};
SpeechToText.prototype.unWireEvents = function () {
EventHandler.remove(this.element, 'click', this.handleButtonClick);
};
SpeechToText.prototype.handleButtonClick = function (event) {
this.isUserInteracted = true;
this.micOn = !this.micOn;
if (this.micOn) {
this.startSpeechRecognition(event);
}
else {
this.stopSpeechRecognition(event);
}
};
SpeechToText.prototype.triggerUnSupportedError = function () {
var eventArgs = {
error: 'unsupported-browser',
errorMessage: this.l10n.getConstant('unsupportedBrowserError')
};
this.trigger('onError', eventArgs);
};
SpeechToText.prototype.initializeSpeechRecognition = function () {
var _this = this;
var windowInst = window;
var SpeechRecognition = windowInst.SpeechRecognition || windowInst.webkitSpeechRecognition;
if (!SpeechRecognition) {
this.triggerUnSupportedError();
return;
}
this.recognition = new SpeechRecognition();
this.recognition.continuous = true;
this.recognition.lang = this.lang;
this.recognition.interimResults = this.allowInterimResults;
this.recognition.onstart = function (event) {
var prevOnChange = _this.isProtectedOnChange;
_this.isProtectedOnChange = true;
_this.transcript = _this.fullTranscript = '';
_this.isProtectedOnChange = prevOnChange;
var eventArgs = {
cancel: false,
listeningState: SpeechToTextState.Listening,
event: event,
isInteracted: _this.isUserInteracted
};
_this.trigger('onStart', eventArgs, function () {
if (!eventArgs.cancel) {
_this.handleStartRecognition();
}
else {
_this.recognition.abort();
_this.micOn = false;
}
});
};
this.recognition.onend = function (event) {
if (_this.hasStarted) {
_this.micOn = false;
_this.handleStopRecognition(event);
}
};
this.recognition.onerror = function (event) {
var errorMessage = '';
switch (event.error) {
case 'not-allowed':
errorMessage = _this.l10n.getConstant('notAllowedError');
break;
case 'audio-capture':
errorMessage = _this.l10n.getConstant('audioCaptureError');
break;
case 'network':
errorMessage = _this.l10n.getConstant('networkError');
break;
case 'no-speech':
errorMessage = _this.l10n.getConstant('noSpeechError');
break;
case 'aborted':
errorMessage = _this.l10n.getConstant('abortedError');
break;
case 'service-not-allowed':
errorMessage = _this.l10n.getConstant('serviceNotAllowedError');
break;
default:
errorMessage = _this.l10n.getConstant('defaultError');
}
var eventArgs = {
event: event,
error: event.error,
errorMessage: errorMessage
};
_this.trigger('onError', eventArgs);
_this.isUserInteracted = false;
};
this.recognition.onresult = function (event) {
var result = event.results[event.resultIndex];
var interimTranscript = '';
var prevOnChange = _this.isProtectedOnChange;
_this.isProtectedOnChange = true;
if (result.isFinal) {
_this.fullTranscript += result[0].transcript;
_this.transcript = _this.fullTranscript;
}
else {
interimTranscript += result[0].transcript;
_this.transcript = _this.fullTranscript + interimTranscript;
}
var eventArgs = {
event: event,
transcript: _this.transcript,
isInterimResult: !result.isFinal
};
_this.trigger('transcriptChanged', eventArgs, function () {
if (eventArgs.transcript !== _this.transcript) {
var prevOnChange_1 = _this.isProtectedOnChange;
_this.isProtectedOnChange = true;
_this.transcript = _this.fullTranscript = eventArgs.transcript;
_this.isProtectedOnChange = prevOnChange_1;
}
});
_this.isProtectedOnChange = prevOnChange;
};
};
SpeechToText.prototype.handleStartRecognition = function () {
var prevOnChange = this.isProtectedOnChange;
this.isProtectedOnChange = true;
this.hasStarted = true;
this.listeningState = SpeechToTextState.Listening;
if (!isNOU(this.tooltipInst)) {
this.tooltipInst.content = this.tooltipSettings.stopContent;
}
this.updateAriaLabel();
this.isClicked = true;
this.buttonInst.cssClass = this.updateButtonCssClass();
this.buttonInst.content = this.buttonSettings.stopContent;
var iconCss = !isNOU(this.buttonSettings.stopIconCss) && this.buttonSettings.stopIconCss !== '' ? this.buttonSettings.stopIconCss : 'e-icons e-listen-stop';
this.buttonInst.iconCss = iconCss;
this.isProtectedOnChange = prevOnChange;
};
SpeechToText.prototype.triggerUnSupportedStart = function (event) {
var _this = this;
var prevOnChange = this.isProtectedOnChange;
this.isProtectedOnChange = true;
this.transcript = '';
this.isProtectedOnChange = prevOnChange;
var eventArgs = {
cancel: false,
listeningState: SpeechToTextState.Listening,
event: event,
isInteracted: this.isUserInteracted
};
this.trigger('onStart', eventArgs, function () {
if (!eventArgs.cancel) {
_this.handleStartRecognition();
}
});
};
SpeechToText.prototype.startSpeechRecognition = function (event) {
if (this.hasStarted) {
return;
}
if (this.recognition) {
this.recognition.start();
}
else {
this.triggerUnSupportedStart(event);
}
};
SpeechToText.prototype.stopSpeechRecognition = function (event) {
if (this.recognition) {
this.recognition.stop();
}
else {
this.handleStopRecognition(event);
}
};
SpeechToText.prototype.handleStopRecognition = function (event) {
if (!this.hasStarted) {
return;
} // Ensure onStop is only processed if needed
var prevOnChange = this.isProtectedOnChange;
this.isProtectedOnChange = true;
this.listeningState = SpeechToTextState.Stopped;
if (!isNOU(this.tooltipInst)) {
this.tooltipInst.content = this.tooltipSettings.content;
}
this.updateAriaLabel();
this.isClicked = false;
this.buttonInst.cssClass = this.updateButtonCssClass();
this.buttonInst.content = this.buttonSettings.content;
var eventArgs = {
listeningState: SpeechToTextState.Stopped,
event: event,
isInteracted: this.isUserInteracted
};
this.trigger('onStop', eventArgs);
this.listeningState = SpeechToTextState.Inactive;
var iconCss = !isNOU(this.buttonSettings.iconCss) && this.buttonSettings.iconCss !== '' ? this.buttonSettings.iconCss : 'e-icons e-listen-icon';
this.buttonInst.iconCss = iconCss;
this.hasStarted = false;
this.isProtectedOnChange = prevOnChange;
};
SpeechToText.prototype.buttonSettingsChanges = function (oldModel, newModel) {
if (oldModel.content !== newModel.content || oldModel.stopContent !== newModel.stopContent) {
this.buttonInst.content = this.hasStarted ? this.buttonSettings.stopContent : this.buttonSettings.content;
this.buttonInst.cssClass = this.updateButtonCssClass();
}
if (oldModel.iconCss !== newModel.iconCss || oldModel.stopIconCss !== newModel.stopIconCss) {
var iconCss = !isNOU(this.buttonSettings.iconCss) && this.buttonSettings.iconCss !== '' ? this.buttonSettings.iconCss : 'e-icons e-listen-icon';
var stopIconCss = !isNOU(this.buttonSettings.stopIconCss) && this.buttonSettings.stopIconCss !== '' ? this.buttonSettings.stopIconCss : 'e-icons e-listen-stop';
this.buttonInst.iconCss = this.hasStarted ? stopIconCss : iconCss;
}
if (oldModel.iconPosition !== newModel.iconPosition) {
this.buttonInst.iconPosition = this.buttonSettings.iconPosition;
}
if (oldModel.isPrimary !== newModel.isPrimary) {
this.buttonInst.isPrimary = this.buttonSettings.isPrimary;
}
};
SpeechToText.prototype.destroyAndNullify = function (obj) {
if (obj) {
obj.destroy();
obj = null;
}
};
//#endregion
//#region Public Methods
/**
* Destroy the SpeechToText.
*
* @returns {void}
*/
SpeechToText.prototype.destroy = function () {
_super.prototype.destroy.call(this);
this.unWireEvents();
this.destroyAndNullify(this.buttonInst);
this.destroyAndNullify(this.tooltipInst);
this.recognition = null;
this.micOn = null;
this.htmlAttributes = this.tooltipSettings = this.buttonSettings = null;
this.element.classList.remove('e-rtl');
};
/**
* Begins the audio capture process by listening to the user's microphone input.
* This method initiates the speech-to-text process and continuously updates the `transcript` property with interim and final recognition results.
*
* @returns {void} No return value.
*/
SpeechToText.prototype.startListening = function () {
if (!this.disabled && !this.isClicked) {
this.isUserInteracted = false;
this.micOn = true;
this.startSpeechRecognition();
}
};
/**
* Stops the audio capture process and finalizes the speech recognition.
* This method ends the ongoing speech-to-text operation and completes the recognition process, storing the final transcription.
* It is typically called to stop listening when the user is finished speaking.
*
* @returns {void} No return value.
*/
SpeechToText.prototype.stopListening = function () {
if (!this.disabled && this.isClicked) {
this.isUserInteracted = false;
this.micOn = false;
this.stopSpeechRecognition();
}
};
/**
* Called if any of the property value is changed.
*
* @param {SpeechToTextModel} newProp - Specifies new properties
* @param {SpeechToTextModel} oldProp - Specifies old properties
* @returns {void}
* @private
*/
SpeechToText.prototype.onPropertyChanged = function (newProp, oldProp) {
for (var _i = 0, _a = Object.keys(newProp); _i < _a.length; _i++) {
var prop = _a[_i];
switch (prop) {
case 'lang':
if (this.recognition) {
this.recognition.lang = this.lang;
}
break;
case 'allowInterimResults':
if (this.recognition) {
this.recognition.interimResults = this.allowInterimResults;
}
break;
case 'buttonSettings':
this.buttonSettingsChanges(oldProp.buttonSettings, newProp.buttonSettings);
break;
case 'cssClass':
this.updateCssClass(newProp.cssClass, oldProp.cssClass);
break;
case 'disabled':
this.buttonInst.disabled = this.disabled;
this.handleStateChange();
break;
case 'htmlAttributes':
this.removeHtmlAttributes(oldProp.htmlAttributes);
this.addHtmlAttributes(newProp.htmlAttributes);
break;
case 'listeningState':
this.handleStateChange();
break;
case 'tooltipSettings':
case 'showTooltip':
this.updateTooltip();
break;
case 'transcript':
this.transcript = this.fullTranscript = newProp.transcript;
break;
case 'enableRtl':
this.buttonInst.enableRtl = this.tooltipInst.enableRtl = this.enableRtl;
break;
case 'locale':
this.l10n.setLocale(this.locale);
this.updateAriaLabel();
this.updateTooltip();
break;
}
}
};
__decorate([
Property('')
], SpeechToText.prototype, "transcript", void 0);
__decorate([
Property('')
], SpeechToText.prototype, "lang", void 0);
__decorate([
Property(true)
], SpeechToText.prototype, "allowInterimResults", void 0);
__decorate([
Property(true)
], SpeechToText.prototype, "showTooltip", void 0);
__decorate([
Property('Inactive')
], SpeechToText.prototype, "listeningState", void 0);
__decorate([
Complex({}, ButtonSettings)
], SpeechToText.prototype, "buttonSettings", void 0);
__decorate([
Complex({}, TooltipSettings)
], SpeechToText.prototype, "tooltipSettings", void 0);
__decorate([
Property(false)
], SpeechToText.prototype, "disabled", void 0);
__decorate([
Property('')
], SpeechToText.prototype, "cssClass", void 0);
__decorate([
Property({})
], SpeechToText.prototype, "htmlAttributes", void 0);
__decorate([
Event()
], SpeechToText.prototype, "created", void 0);
__decorate([
Event()
], SpeechToText.prototype, "onStart", void 0);
__decorate([
Event()
], SpeechToText.prototype, "onStop", void 0);
__decorate([
Event()
], SpeechToText.prototype, "onError", void 0);
__decorate([
Event()
], SpeechToText.prototype, "transcriptChanged", void 0);
SpeechToText = __decorate([
NotifyPropertyChanges
], SpeechToText);
return SpeechToText;
}(Component));
export { SpeechToText };