@massds/mayflower-react
Version:
React versions of Mayflower design system UI components
351 lines (350 loc) • 14.6 kB
JavaScript
;
exports.__esModule = true;
exports["default"] = void 0;
var _react = _interopRequireDefault(require("react"));
var _propTypes = _interopRequireDefault(require("prop-types"));
var _classnames = _interopRequireDefault(require("classnames"));
var _numbro = _interopRequireDefault(require("numbro"));
var _es = require("react-compound-slider/es");
var _context = require("../Input/context.js");
var _utility = require("../Input/utility.js");
function _interopRequireDefault(e) { return e && e.__esModule ? e : { "default": e }; }
function _inheritsLoose(t, o) { t.prototype = Object.create(o.prototype), t.prototype.constructor = t, _setPrototypeOf(t, o); }
function _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }
function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); } /**
* CompoundSlider module.
* @module @massds/mayflower-react/CompoundSlider
*/
var Handle = function Handle(props) {
var _props$handle = props.handle,
id = _props$handle.id,
value = _props$handle.value,
percent = _props$handle.percent,
getHandleProps = props.getHandleProps,
axis = props.axis,
min = props.min,
max = props.max,
step = props.step,
displayValueFormat = props.displayValueFormat,
disabled = props.disabled;
var decimalPlaces = (0, _utility.countDecimals)(step);
var roundedValue = Number.isInteger(step) ? value : Number(Number.parseFloat(value).toFixed(decimalPlaces));
var divProps = _extends({
'aria-valuemin': min,
'aria-valuemax': max,
'aria-valuenow': roundedValue,
disabled: disabled,
role: 'slider',
onClick: function onClick(e) {
e.preventDefault();
}
}, getHandleProps(id));
if (axis === 'x') {
divProps.style = {
left: percent + "%"
};
} else if (axis === 'y') {
divProps.style = {
top: percent + "%"
};
}
return /*#__PURE__*/_react["default"].createElement("button", _extends({
type: "button",
className: "ma__slider-handle"
}, divProps), displayValueFormat && /*#__PURE__*/_react["default"].createElement("div", {
className: "ma__slider-handle-value"
}, displayValueFormat === 'percentage' ? (0, _numbro["default"])(value).format({
output: 'percent',
mantissa: 0
}) : roundedValue));
};
Handle.propTypes = process.env.NODE_ENV !== "production" ? {
handle: {
id: _propTypes["default"].string,
value: _propTypes["default"].oneOfType([_propTypes["default"].string, _propTypes["default"].number]),
percent: _propTypes["default"].oneOfType([_propTypes["default"].string, _propTypes["default"].number])
},
getHandleProps: _propTypes["default"].func,
axis: _propTypes["default"].string,
min: _propTypes["default"].oneOfType([_propTypes["default"].string, _propTypes["default"].number]),
max: _propTypes["default"].oneOfType([_propTypes["default"].string, _propTypes["default"].number]),
step: _propTypes["default"].oneOfType([_propTypes["default"].string, _propTypes["default"].number]),
displayValueFormat: _propTypes["default"].string,
disabled: _propTypes["default"].bool
} : {};
var Track = function Track(props) {
var source = props.source,
target = props.target,
getTrackProps = props.getTrackProps,
axis = props.axis;
var divProps = _extends({}, getTrackProps());
if (axis === 'x') {
divProps.style = {
left: source.percent + "%",
width: target.percent - source.percent + "%"
};
} else if (axis === 'y') {
divProps.style = {
top: source.percent + "%",
height: target.percent - source.percent + "%"
};
}
return /*#__PURE__*/_react["default"].createElement("div", _extends({
className: "ma__slider-track"
}, divProps));
};
Track.propTypes = process.env.NODE_ENV !== "production" ? {
source: {
percent: _propTypes["default"].string
},
target: {
percent: _propTypes["default"].string
},
getTrackProps: _propTypes["default"].func,
axis: _propTypes["default"].string
} : {};
var Tick = function Tick(props) {
var tick = props.tick,
count = props.count,
axis = props.axis,
id = props.id;
var top = {};
var bottom = {};
if (axis === 'x') {
top.style = {
left: tick.percent + "%"
};
bottom.style = {
marginLeft: -(100 / count) / 2 + "%",
width: 100 / count + "%",
left: tick.percent + "%"
};
} else if (axis === 'y') {
top.style = {
top: tick.percent + "%"
};
bottom.style = {
top: tick.percent + "%"
};
}
return /*#__PURE__*/_react["default"].createElement(_react["default"].Fragment, null, /*#__PURE__*/_react["default"].createElement("div", _extends({
className: "ma__slider-tick ma__slider-tick--top"
}, top)), /*#__PURE__*/_react["default"].createElement("div", _extends({
className: "ma__slider-tick ma__slider-tick--bottom"
}, bottom), /*#__PURE__*/_react["default"].createElement("label", {
htmlFor: id
}, tick.value)));
};
Tick.propTypes = process.env.NODE_ENV !== "production" ? {
tick: {
percent: _propTypes["default"].string,
value: _propTypes["default"].oneOfType([_propTypes["default"].string, _propTypes["default"].number])
},
count: _propTypes["default"].number,
getTrackProps: _propTypes["default"].func,
id: _propTypes["default"].string,
axis: _propTypes["default"].string
} : {};
var CompoundSlider = /*#__PURE__*/function (_React$Component) {
function CompoundSlider() {
return _React$Component.apply(this, arguments) || this;
}
_inheritsLoose(CompoundSlider, _React$Component);
var _proto = CompoundSlider.prototype;
_proto.render = function render() {
var _this = this;
return /*#__PURE__*/_react["default"].createElement(_context.InputContext.Consumer, null, function (context) {
var _this$props = _this.props,
min = _this$props.min,
max = _this$props.max,
step = _this$props.step,
disabled = _this$props.disabled,
domain = _this$props.domain,
onChange = _this$props.onChange,
onUpdate = _this$props.onUpdate;
var decimalPlaces = (0, _utility.countDecimals)(step);
var handleChange = function handleChange(values) {
var value = Number.isInteger(step) ? values[0] : Number(Number.parseFloat(values[0]).toFixed(decimalPlaces));
context.updateState({
value: value
}, function () {
if (typeof onChange === 'function') {
onChange(value, _this.props.id);
}
});
};
var handleUpdate = function handleUpdate(values) {
var value = Number.isInteger(step) ? values[0] : Number(Number.parseFloat(values[0]).toFixed(decimalPlaces));
context.updateState({
value: value
}, function () {
if (typeof onUpdate === 'function') {
onUpdate(value, _this.props.id);
}
});
};
var domainCheck = function domainCheck(valToCheck) {
var minCheck = Number(min);
var maxCheck = Number(max);
if (Number.isNaN(valToCheck)) {
return Number.isInteger(step) ? minCheck : Number(Number.parseFloat(minCheck).toFixed(decimalPlaces));
}
var returnValue = valToCheck;
var domainMin = domain[0],
domainMax = domain[1];
// If the min/max passed falls outside of the domain, set it to the respective domain min/max.
if (Number.isNaN(minCheck) || Math.abs(minCheck - domainMax) > Math.abs(domainMin - domainMax)) {
minCheck = domainMin;
}
if (Number.isNaN(maxCheck) || Math.abs(maxCheck - domainMin) > Math.abs(domainMin - domainMax)) {
maxCheck = domainMax;
}
// Ensure the value is always between the min or max values, if any.
if (valToCheck < minCheck) {
returnValue = minCheck;
}
if (valToCheck > maxCheck) {
returnValue = maxCheck;
}
return Number.isInteger(step) ? returnValue : Number(Number.parseFloat(returnValue).toFixed(decimalPlaces));
};
// Anything returned by mode when set to a function will become the value.
// This can be used for min/max validation.
// Next and current values are not numbers, but arrays of objects.
var handleMode = function handleMode(current, next) {
var nextValue = next[0].val;
var checkValue = Number.isInteger(step) ? nextValue : Number(Number.parseFloat(nextValue).toFixed(decimalPlaces));
if (checkValue === domainCheck(nextValue)) {
return next;
}
return current;
};
var defaultValue = domainCheck(Number(context.getValue()));
var sliderProps = {
domain: domain,
step: step,
vertical: !(_this.props.axis === 'x'),
onChange: handleChange,
values: [defaultValue],
mode: handleMode,
disabled: disabled
};
if (onUpdate) {
sliderProps.onUpdate = handleUpdate;
}
var wrapperClasses = (0, _classnames["default"])({
'ma__input-slider': true,
'ma__input-slider--disabled': disabled,
'ma__input-slider-x': _this.props.axis === 'x',
'ma__input-slider-y': _this.props.axis === 'y'
});
return /*#__PURE__*/_react["default"].createElement("div", {
id: _this.props.id,
className: wrapperClasses
}, /*#__PURE__*/_react["default"].createElement(_es.Slider, _extends({
className: "ma__slider"
}, sliderProps), /*#__PURE__*/_react["default"].createElement(_es.Rail, null, function (_ref) {
var getRailProps = _ref.getRailProps;
return /*#__PURE__*/_react["default"].createElement("div", _extends({
className: "ma__slider-rail"
}, getRailProps()));
}), /*#__PURE__*/_react["default"].createElement(_es.Handles, null, function (_ref2) {
var handles = _ref2.handles,
activeHandleID = _ref2.activeHandleID,
getHandleProps = _ref2.getHandleProps;
return /*#__PURE__*/_react["default"].createElement("div", {
className: "slider-handles"
}, handles.map(function (handle) {
return /*#__PURE__*/_react["default"].createElement(Handle, {
key: handle.id,
handle: handle,
getHandleProps: getHandleProps,
isActive: handle.id === activeHandleID,
axis: _this.props.axis,
min: min,
max: max,
step: step,
displayValueFormat: _this.props.displayValueFormat,
disabled: disabled
});
}));
}), /*#__PURE__*/_react["default"].createElement(_es.Tracks, {
right: false
}, function (_ref3) {
var tracks = _ref3.tracks,
getTrackProps = _ref3.getTrackProps;
return /*#__PURE__*/_react["default"].createElement("div", {
className: "slider-tracks"
}, tracks.map(function (_ref4) {
var id = _ref4.id,
source = _ref4.source,
target = _ref4.target;
return /*#__PURE__*/_react["default"].createElement(Track, {
key: id,
source: source,
target: target,
getTrackProps: getTrackProps,
axis: _this.props.axis
});
}));
}), /*#__PURE__*/_react["default"].createElement(_es.Ticks, {
values: Array.from(_this.props.ticks.keys())
}, function (_ref5) {
var ticks = _ref5.ticks;
var ticksLength = ticks.length;
// Placing this check here because Slider can't handle null children but Ticks can.
if (ticksLength > 0) {
return /*#__PURE__*/_react["default"].createElement("div", {
className: "slider-ticks"
}, ticks.map(function (oldTick) {
var tick = _extends({}, oldTick, {
value: _this.props.ticks.get(oldTick.value)
});
var tickProps = {
key: "CompoundSlider.tick." + tick.value,
count: ticksLength,
tick: tick,
axis: _this.props.axis,
id: _this.props.id
};
return /*#__PURE__*/_react["default"].createElement(Tick, tickProps);
}));
}
return null;
})));
});
};
return CompoundSlider;
}(_react["default"].Component);
CompoundSlider.propTypes = process.env.NODE_ENV !== "production" ? {
/** The unique ID for the input field */
id: _propTypes["default"].string.isRequired,
/** Custom update function, triggered with the values on drag (caution: high-volume updates when dragging). Only if a function is passed to onUpdate will form context get updated on drag. */
onUpdate: _propTypes["default"].func,
/** Custom on change function, triggered when the value of the slider has changed. This will recieve changes at the end of a slide as well as changes from clicks on rails and tracks. */
onChange: _propTypes["default"].func,
/** Default input text value */
defaultValue: _propTypes["default"].string,
/** Max value for the field. */
max: _propTypes["default"].number.isRequired,
/** Min value for the field. */
min: _propTypes["default"].number.isRequired,
/** This controls how much sliding the handle increments/decrements the value of the slider. */
step: _propTypes["default"].number,
/** A Map object where each entry is a key (number inclusively between min and max) and value (label to display at the key) pair for displaying tick marks. */
ticks: _propTypes["default"].instanceOf(Map),
/** The direction for the slider, where x is horizontal and y is vertical. */
axis: _propTypes["default"].oneOf(['x', 'y']),
/** Disables the slider if true. */
disabled: _propTypes["default"].bool,
/** The range of numbers, inclusively, for the slider to fall between. First number is the min and second number is the max. */
domain: _propTypes["default"].arrayOf(_propTypes["default"].number),
/** Display the value of the slider based. If null, don't display. If equals percentage, format the value in percentage. */
displayValueFormat: _propTypes["default"].oneOf(['percentage', 'value', null])
} : {};
CompoundSlider.defaultProps = {
ticks: new Map(),
domain: [0, 1]
};
var _default = exports["default"] = CompoundSlider;
module.exports = exports.default;