office-ui-fabric-react
Version:
Reusable React components for building experiences for Microsoft 365.
396 lines • 20.2 kB
JavaScript
import { __assign, __extends } from "tslib";
import * as React from 'react';
import { KeyCodes, css, getId, getRTL, getRTLSafeKeyCode, warnMutuallyExclusive, initializeComponentRef, Async, on, FocusRects, } from '../../Utilities';
import { classNamesFunction, getNativeProps, divProperties } from '../../Utilities';
import { Label } from '../../Label';
var getClassNames = classNamesFunction();
var COMPONENT_NAME = 'SliderBase';
export var ONKEYDOWN_TIMEOUT_DURATION = 1000;
var SliderBase = /** @class */ (function (_super) {
__extends(SliderBase, _super);
function SliderBase(props) {
var _this = _super.call(this, props) || this;
_this._disposables = [];
_this._sliderLine = React.createRef();
_this._thumb = React.createRef();
_this._lowerValueThumb = React.createRef();
_this._onKeyDownTimer = -1;
_this._isAdjustingLowerValue = false;
_this._getAriaValueText = function (value) {
var ariaValueText = _this.props.ariaValueText;
if (value !== undefined) {
return ariaValueText ? ariaValueText(value) : value.toString();
}
return undefined;
};
_this._calculateCurrentSteps = function (event) {
if (!_this._sliderLine.current) {
return;
}
var _a = _this.props, max = _a.max, min = _a.min, step = _a.step;
var steps = (max - min) / step;
var sliderPositionRect = _this._sliderLine.current.getBoundingClientRect();
var sliderLength = !_this.props.vertical ? sliderPositionRect.width : sliderPositionRect.height;
var stepLength = sliderLength / steps;
var currentSteps;
var distance;
if (!_this.props.vertical) {
var left = _this._getPosition(event, _this.props.vertical);
distance = getRTL(_this.props.theme) ? sliderPositionRect.right - left : left - sliderPositionRect.left;
currentSteps = distance / stepLength;
}
else {
var bottom = _this._getPosition(event, _this.props.vertical);
distance = sliderPositionRect.bottom - bottom;
currentSteps = distance / stepLength;
}
return currentSteps;
};
_this._onMouseDownOrTouchStart = function (event) {
var _a = _this.props, ranged = _a.ranged, min = _a.min, step = _a.step;
if (ranged) {
var currentSteps = _this._calculateCurrentSteps(event);
var newRenderedValue = min + step * currentSteps;
if (newRenderedValue <= _this.state.lowerValue ||
newRenderedValue - _this.state.lowerValue <= _this.state.value - newRenderedValue) {
_this._isAdjustingLowerValue = true;
}
else {
_this._isAdjustingLowerValue = false;
}
}
if (event.type === 'mousedown') {
_this._disposables.push(on(window, 'mousemove', _this._onMouseMoveOrTouchMove, true), on(window, 'mouseup', _this._onMouseUpOrTouchEnd, true));
}
else if (event.type === 'touchstart') {
_this._disposables.push(on(window, 'touchmove', _this._onMouseMoveOrTouchMove, true), on(window, 'touchend', _this._onMouseUpOrTouchEnd, true));
}
_this._onMouseMoveOrTouchMove(event, true);
};
_this._onMouseMoveOrTouchMove = function (event, suppressEventCancelation) {
if (!_this._sliderLine.current) {
return;
}
var _a = _this.props, max = _a.max, min = _a.min, step = _a.step;
var steps = (max - min) / step;
var currentSteps = _this._calculateCurrentSteps(event);
var currentValue;
var renderedValue;
// The value shouldn't be bigger than max or be smaller than min.
if (currentSteps > Math.floor(steps)) {
renderedValue = currentValue = max;
}
else if (currentSteps < 0) {
renderedValue = currentValue = min;
}
else {
renderedValue = min + step * currentSteps;
currentValue = min + step * Math.round(currentSteps);
}
_this._updateValue(currentValue, renderedValue);
if (!suppressEventCancelation) {
event.preventDefault();
event.stopPropagation();
}
};
_this._onMouseUpOrTouchEnd = function (event) {
// Disable renderedValue override.
_this.setState({
renderedValue: undefined,
renderedLowerValue: undefined,
});
if (_this.props.onChanged) {
_this.props.onChanged(event, _this.state.value);
}
_this._disposeListeners();
};
_this._disposeListeners = function () {
_this._disposables.forEach(function (dispose) { return dispose(); });
_this._disposables = [];
};
_this._onKeyDown = function (event) {
var value;
if (_this._isAdjustingLowerValue) {
value = _this.props.lowerValue || _this.state.lowerValue;
}
else {
value = _this.props.value || _this.state.value;
}
var _a = _this.props, max = _a.max, min = _a.min, step = _a.step;
var diff = 0;
// eslint-disable-next-line deprecation/deprecation
switch (event.which) {
case getRTLSafeKeyCode(KeyCodes.left, _this.props.theme):
case KeyCodes.down:
diff = -step;
_this._clearOnKeyDownTimer();
_this._setOnKeyDownTimer(event);
break;
case getRTLSafeKeyCode(KeyCodes.right, _this.props.theme):
case KeyCodes.up:
diff = step;
_this._clearOnKeyDownTimer();
_this._setOnKeyDownTimer(event);
break;
case KeyCodes.home:
value = min;
_this._clearOnKeyDownTimer();
_this._setOnKeyDownTimer(event);
break;
case KeyCodes.end:
value = max;
_this._clearOnKeyDownTimer();
_this._setOnKeyDownTimer(event);
break;
default:
return;
}
var newValue = Math.min(max, Math.max(min, value + diff));
_this._updateValue(newValue, newValue);
event.preventDefault();
event.stopPropagation();
// Disable renderedValue override.
_this.setState({
renderedValue: undefined,
renderedLowerValue: undefined,
});
};
_this._onThumbFocus = function (event) {
_this._isAdjustingLowerValue = event.target === _this._lowerValueThumb.current;
};
_this._clearOnKeyDownTimer = function () {
_this._async.clearTimeout(_this._onKeyDownTimer);
};
_this._setOnKeyDownTimer = function (event) {
_this._onKeyDownTimer = _this._async.setTimeout(function () {
if (_this.props.onChanged) {
_this.props.onChanged(event, _this.state.value);
}
}, ONKEYDOWN_TIMEOUT_DURATION);
};
_this._async = new Async(_this);
initializeComponentRef(_this);
warnMutuallyExclusive(COMPONENT_NAME, _this.props, {
value: 'defaultValue',
});
if (props.ranged) {
warnMutuallyExclusive(COMPONENT_NAME, _this.props, {
lowerValue: 'defaultLowerValue',
});
}
_this._id = getId('Slider');
var value = props.value !== undefined ? props.value : props.defaultValue !== undefined ? props.defaultValue : props.min;
var lowerValue = props.lowerValue !== undefined
? props.lowerValue
: props.defaultLowerValue !== undefined
? props.defaultLowerValue
: props.min;
_this.state = {
value: value,
lowerValue: lowerValue,
renderedValue: undefined,
renderedLowerValue: undefined,
};
return _this;
}
SliderBase.prototype.componentWillUnmount = function () {
this._async.dispose();
this._disposeListeners();
};
SliderBase.prototype.render = function () {
var _a, _b, _c;
var _d = this.props, ariaLabel = _d.ariaLabel, className = _d.className, disabled = _d.disabled, label = _d.label, max = _d.max, min = _d.min, showValue = _d.showValue, buttonProps = _d.buttonProps, vertical = _d.vertical, styles = _d.styles, theme = _d.theme, originFromZero = _d.originFromZero, ranged = _d.ranged;
var value = this.value;
var renderedValue = this.renderedValue;
var renderedLowerValue = this.renderedLowerValue;
var thumbOffsetPercent = this._getPercent(renderedValue);
var lowerThumbOffsetPercent = this._getPercent(renderedLowerValue);
var originValue = originFromZero ? 0 : min;
var originPercent = this._getPercent(originValue);
var activeSectionWidth = ranged
? thumbOffsetPercent - lowerThumbOffsetPercent
: Math.abs(originPercent - thumbOffsetPercent);
var topSectionWidth = Math.min(100 - thumbOffsetPercent, 100 - originPercent);
var bottomSectionWidth = ranged ? lowerThumbOffsetPercent : Math.min(thumbOffsetPercent, originPercent);
var lengthString = vertical ? 'height' : 'width';
var onMouseDownProp = disabled ? {} : { onMouseDown: this._onMouseDownOrTouchStart };
var onTouchStartProp = disabled ? {} : { onTouchStart: this._onMouseDownOrTouchStart };
var onKeyDownProp = disabled ? {} : { onKeyDown: this._onKeyDown };
var onFocusProp = disabled ? {} : { onFocus: this._onThumbFocus };
var classNames = getClassNames(styles, {
className: className,
ranged: ranged,
disabled: disabled,
vertical: vertical,
showTransitions: renderedValue === value || (ranged && renderedLowerValue === this.lowerValue),
showValue: showValue,
theme: theme,
});
var divButtonProps = buttonProps
? getNativeProps(buttonProps, divProperties)
: undefined;
var sliderProps = {
'aria-disabled': disabled,
role: 'slider',
tabIndex: disabled ? undefined : 0,
'data-is-focusable': !disabled,
};
var sliderBoxProps = __assign(__assign(__assign(__assign(__assign({ id: this._id, className: css(classNames.slideBox, buttonProps.className) }, onMouseDownProp), onTouchStartProp), onKeyDownProp), divButtonProps), (!ranged && __assign(__assign({}, sliderProps), { 'aria-valuemin': min, 'aria-valuemax': max, 'aria-valuenow': value, 'aria-valuetext': this._getAriaValueText(value), 'aria-label': ariaLabel || label })));
var thumbProps = ranged
? __assign(__assign(__assign({}, sliderProps), onFocusProp), { id: "max-" + this._id, 'aria-valuemin': this.lowerValue, 'aria-valuemax': max, 'aria-valuenow': value, 'aria-valuetext': this._getAriaValueText(value), 'aria-label': "max " + (ariaLabel || label) }) : undefined;
var lowerValueThumbProps = ranged
? __assign(__assign(__assign({}, sliderProps), onFocusProp), { id: "min-" + this._id, 'aria-valuemin': min, 'aria-valuemax': value, 'aria-valuenow': this.lowerValue, 'aria-valuetext': this._getAriaValueText(this.lowerValue), 'aria-label': "min " + (ariaLabel || label) }) : undefined;
return (React.createElement("div", { className: classNames.root },
label && (React.createElement(Label, __assign({ className: classNames.titleLabel }, (ariaLabel ? {} : { htmlFor: this._id }), { disabled: disabled }), label)),
React.createElement("div", { className: classNames.container },
ranged && showValue && (React.createElement(Label, { className: classNames.valueLabel, disabled: disabled }, this._getValueLabel(vertical ? this.value : this.lowerValue))),
React.createElement("div", __assign({}, sliderBoxProps),
React.createElement("div", { ref: this._sliderLine, className: classNames.line },
originFromZero && (React.createElement("span", { className: css(classNames.zeroTick), style: this._getStyleUsingOffsetPercent(vertical, originPercent) })),
ranged && (React.createElement("span", __assign({ ref: this._lowerValueThumb, className: classNames.thumb, style: this._getStyleUsingOffsetPercent(vertical, lowerThumbOffsetPercent) }, lowerValueThumbProps))),
React.createElement("span", __assign({ ref: this._thumb, className: classNames.thumb, style: this._getStyleUsingOffsetPercent(vertical, thumbOffsetPercent) }, thumbProps)),
(ranged || originFromZero) && (React.createElement("span", { className: css(classNames.lineContainer, classNames.inactiveSection), style: (_a = {}, _a[lengthString] = bottomSectionWidth + '%', _a) })),
React.createElement("span", { className: css(classNames.lineContainer, classNames.activeSection), style: (_b = {}, _b[lengthString] = activeSectionWidth + '%', _b) }),
React.createElement("span", { className: css(classNames.lineContainer, classNames.inactiveSection), style: (_c = {}, _c[lengthString] = topSectionWidth + '%', _c) }))),
showValue && (React.createElement(Label, { className: classNames.valueLabel, disabled: disabled }, this._getValueLabel(ranged && vertical ? this.lowerValue : this.value)))),
React.createElement(FocusRects, null)));
};
SliderBase.prototype.focus = function () {
if (this._thumb.current) {
this._thumb.current.focus();
}
};
Object.defineProperty(SliderBase.prototype, "range", {
get: function () {
if (this.props.ranged) {
return [this.lowerValue, this.value];
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(SliderBase.prototype, "value", {
get: function () {
var _a = this.props.value, value = _a === void 0 ? this.state.value : _a;
if (this.props.min === undefined || this.props.max === undefined || value === undefined) {
return undefined;
}
else {
return Math.max(this.props.min, Math.min(this.props.max, value));
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(SliderBase.prototype, "renderedValue", {
get: function () {
// renderedValue is expected to be defined while user is interacting with control, otherwise `undefined`.
// Fall back to `value`.
var _a = this.state.renderedValue, renderedValue = _a === void 0 ? this.value : _a;
return renderedValue;
},
enumerable: true,
configurable: true
});
Object.defineProperty(SliderBase.prototype, "lowerValue", {
get: function () {
var _a = this.props, _b = _a.lowerValue, lowerValue = _b === void 0 ? this.state.lowerValue : _b, ranged = _a.ranged;
if (!ranged || this.props.min === undefined || this.props.max === undefined || lowerValue === undefined) {
return undefined;
}
else {
return Math.max(this.props.min, Math.min(this.props.max, lowerValue));
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(SliderBase.prototype, "renderedLowerValue", {
get: function () {
// renderedLowerValue is expected to be defined while user is interacting with control, otherwise `undefined`.
// Fall back to `lowerValue`.
var _a = this.state.renderedLowerValue, renderedLowerValue = _a === void 0 ? this.lowerValue : _a;
return renderedLowerValue;
},
enumerable: true,
configurable: true
});
SliderBase.prototype._getPercent = function (value) {
var _a = this.props, min = _a.min, max = _a.max;
return max === min ? 0 : ((value - min) / (max - min)) * 100;
};
SliderBase.prototype._getValueLabel = function (value) {
var valueFormat = this.props.valueFormat;
return valueFormat ? valueFormat(value) : value;
};
SliderBase.prototype._getStyleUsingOffsetPercent = function (vertical, thumbOffsetPercent) {
var _a;
var direction = vertical ? 'bottom' : getRTL(this.props.theme) ? 'right' : 'left';
return _a = {},
_a[direction] = thumbOffsetPercent + '%',
_a;
};
SliderBase.prototype._getPosition = function (event, vertical) {
var currentPosition;
switch (event.type) {
case 'mousedown':
case 'mousemove':
currentPosition = !vertical ? event.clientX : event.clientY;
break;
case 'touchstart':
case 'touchmove':
currentPosition = !vertical
? event.touches[0].clientX
: event.touches[0].clientY;
break;
}
return currentPosition;
};
SliderBase.prototype._setValueState = function (roundedValue, renderedValue) {
var _a;
var _this = this;
var isAdjustingLowerValue = this._isAdjustingLowerValue;
var valueChanged = roundedValue !== (isAdjustingLowerValue ? this.state.lowerValue : this.state.value);
this.setState((_a = {},
_a[isAdjustingLowerValue ? 'lowerValue' : 'value'] = roundedValue,
_a[isAdjustingLowerValue ? 'renderedLowerValue' : 'renderedValue'] = renderedValue,
_a), function () {
var _a = _this.state, lowerValue = _a.lowerValue, value = _a.value;
if (valueChanged && _this.props.onChange) {
_this.props.onChange(isAdjustingLowerValue ? lowerValue : value, _this.props.ranged ? [lowerValue, value] : undefined);
}
});
};
SliderBase.prototype._updateValue = function (value, renderedValue) {
var _a = this.props, step = _a.step, snapToStep = _a.snapToStep, ranged = _a.ranged, originFromZero = _a.originFromZero;
var numDec = 0;
if (isFinite(step)) {
while (Math.round(step * Math.pow(10, numDec)) / Math.pow(10, numDec) !== step) {
numDec++;
}
}
// Make sure value has correct number of decimal places based on number of decimals in step
var roundedValue = parseFloat(value.toFixed(numDec));
if (snapToStep) {
renderedValue = roundedValue;
}
var shouldAdjustLowerThumb = this._isAdjustingLowerValue && (originFromZero ? roundedValue <= 0 : roundedValue <= this.renderedValue);
var shouldAdjustUpperThumb = !this._isAdjustingLowerValue && (originFromZero ? roundedValue >= 0 : roundedValue >= this.renderedLowerValue);
if (!ranged || shouldAdjustLowerThumb || shouldAdjustUpperThumb) {
this._setValueState(roundedValue, renderedValue);
}
};
SliderBase.defaultProps = {
step: 1,
min: 0,
max: 10,
showValue: true,
disabled: false,
vertical: false,
buttonProps: {},
originFromZero: false,
};
return SliderBase;
}(React.Component));
export { SliderBase };
//# sourceMappingURL=Slider.base.js.map