@guardian/threads
Version:
177 lines • 7.8 kB
JavaScript
import { __assign, __extends } from "tslib";
import React, { Component, createRef } from 'react';
import _range from 'lodash.range';
import { QueryElementHelpers, } from '../StructuredQuery';
import { ChipWrapper } from './Chip/ChipWrapper';
import { InlineInput } from './InlineInput';
import styles from './InputSupper.module.css';
var InputSupper = /** @class */ (function (_super) {
__extends(InputSupper, _super);
function InputSupper() {
var _this = _super !== null && _super.apply(this, arguments) || this;
_this.deleteExpiryInterval = undefined;
_this.elementRefs = [];
_this.state = {};
_this.focusElement = function (index, focusEnd) {
if (index >= 0 && index < _this.elementRefs.length) {
var current = _this.elementRefs[index].current;
if (current) {
current.focus(focusEnd);
}
}
};
_this.focusElementAt = function (index, offset) {
if (index >= 0 && index < _this.elementRefs.length) {
var current = _this.elementRefs[index].current;
if (current) {
current.focusAt(offset);
}
}
};
_this.selectElement = function (index) {
if (index >= 0 && index < _this.elementRefs.length) {
var current = _this.elementRefs[index].current;
if (current) {
current.select();
}
}
};
_this.inputUpdated = function (index, value, label) {
_this.props.onChange(QueryElementHelpers.updateElementValue(_this.props.elements, index, value, label));
};
_this.spawnChip = function (index, chipPosition, filter) {
var elements = _this.props.elements;
var sourceElement = elements[index];
// Should ONLY spawn a chip inside a text element
if (sourceElement.type == 'text') {
var value = sourceElement.value;
var startIndex = chipPosition.startIndex, cursorIndex = chipPosition.cursorIndex;
var elementsToInsert = [
QueryElementHelpers.textElementFromValue(value.substring(0, startIndex).trim()),
QueryElementHelpers.filterElementFromFilter(filter, value[startIndex] === '-'),
QueryElementHelpers.textElementFromValue(value.substring(cursorIndex, value.length).trim()),
];
_this.props.onChange(QueryElementHelpers.replaceElement(elements, index, elementsToInsert));
_this.setState({
focusElementIndex: index + 1,
});
}
};
_this.onNegateClicked = function (index) {
var elements = _this.props.elements;
var target = _this.props.elements[index];
if (QueryElementHelpers.isFilter(target)) {
var newElement = __assign(__assign({}, target), { negate: !target.negate });
_this.props.onChange(QueryElementHelpers.replaceElement(elements, index, [newElement]));
}
};
_this.onDeleteClicked = function (index) {
var elements = _this.props.elements;
var left = elements[index - 1];
var right = elements[index + 1];
if (QueryElementHelpers.isText(left) && QueryElementHelpers.isText(right)) {
var mergedText = {
type: 'text',
value: left.value.trim() + ' ' + right.value.trim(),
};
_this.props.onChange(QueryElementHelpers.replaceElements(elements, index - 1, index + 2, [
mergedText,
]));
_this.setState({
focusElementIndex: index - 1,
});
}
};
_this.deleteChip = function (index) {
if (index < 0 || index > _this.props.elements.length - 1) {
return;
}
if (_this.state.deleteStagedIndex === index) {
// Confirm deleting chip
_this.onDeleteClicked(index);
_this.setState({
deleteStagedIndex: undefined,
});
}
else {
// Stage the chip for deletion
_this.setState({
deleteStagedIndex: index,
deleteExpiry: 2,
});
_this.deleteExpiryInterval = setInterval(_this.deleteExpiryTick, 1000);
}
};
_this.deleteExpiryTick = function () {
var deleteExpiry = _this.state.deleteExpiry;
if (_this.deleteExpiryInterval && deleteExpiry && deleteExpiry > 0) {
var countdown = deleteExpiry - 1;
if (countdown <= 0) {
clearInterval(_this.deleteExpiryInterval);
_this.setState({
deleteStagedIndex: undefined,
deleteExpiry: undefined,
});
}
else {
_this.setState({
deleteExpiry: countdown,
});
}
}
};
_this.renderElement = function (e, index) {
var sharedProps = {
ref: _this.elementRefs[index],
key: index,
index: index,
value: e.value,
onUpdate: _this.inputUpdated,
focusElement: _this.focusElement,
deleteChip: _this.deleteChip,
};
if (QueryElementHelpers.isFilter(e)) {
return (React.createElement(ChipWrapper, __assign({}, sharedProps, { negate: e.negate, filter: e.filter, label: e.label, stagedForDeletion: _this.state.deleteStagedIndex === index, onDeleteClicked: _this.onDeleteClicked, onNegateClicked: _this.onNegateClicked })));
}
else {
return (React.createElement(InlineInput, __assign({}, sharedProps, { availableFilters: _this.props.availableFilters, spawnChip: _this.spawnChip, isLastInput: index === _this.props.elements.length - 1 })));
}
};
return _this;
}
InputSupper.prototype.componentDidMount = function () {
if (this.props.elements.length === 0) {
this.props.onChange([
{
type: 'text',
value: '',
},
]);
}
};
InputSupper.prototype.componentDidUpdate = function (prevProps) {
var focusElementIndex = this.state.focusElementIndex;
if (focusElementIndex !== undefined) {
if (prevProps.elements > this.props.elements) {
// We've deleted a chip so we need to focus at the correct offset
var offset = prevProps.elements[focusElementIndex].value.length;
this.focusElementAt(focusElementIndex, offset);
}
else {
this.focusElement(focusElementIndex, false);
}
this.setState({
focusElementIndex: undefined,
});
}
};
InputSupper.prototype.render = function () {
var _this = this;
var elements = this.props.elements;
this.elementRefs = _range(elements.length).map(function () { return createRef(); });
return (React.createElement("div", { className: styles.root }, elements.map(function (e, index) { return _this.renderElement(e, index); })));
};
return InputSupper;
}(Component));
export { InputSupper };
//# sourceMappingURL=InputSupper.js.map