UNPKG

react-simple-knob

Version:
551 lines (483 loc) 15.4 kB
'use strict'; function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; } var React = _interopDefault(require('react')); function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; } function _objectSpread2(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); } function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); } function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); } function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; } function _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; } function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; } function _possibleConstructorReturn(self, call) { if (call && (typeof call === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); } function createCommonjsModule(fn, module) { return module = { exports: {} }, fn(module, module.exports), module.exports; } /** * Copyright (c) 2013-present, Facebook, Inc. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ var ReactPropTypesSecret = 'SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED'; var ReactPropTypesSecret_1 = ReactPropTypesSecret; function emptyFunction() {} function emptyFunctionWithReset() {} emptyFunctionWithReset.resetWarningCache = emptyFunction; var factoryWithThrowingShims = function() { function shim(props, propName, componentName, location, propFullName, secret) { if (secret === ReactPropTypesSecret_1) { // It is still safe when called from React. return; } var err = new Error( 'Calling PropTypes validators directly is not supported by the `prop-types` package. ' + 'Use PropTypes.checkPropTypes() to call them. ' + 'Read more at http://fb.me/use-check-prop-types' ); err.name = 'Invariant Violation'; throw err; } shim.isRequired = shim; function getShim() { return shim; } // Important! // Keep this list in sync with production version in `./factoryWithTypeCheckers.js`. var ReactPropTypes = { array: shim, bool: shim, func: shim, number: shim, object: shim, string: shim, symbol: shim, any: shim, arrayOf: getShim, element: shim, elementType: shim, instanceOf: getShim, node: shim, objectOf: getShim, oneOf: getShim, oneOfType: getShim, shape: getShim, exact: getShim, checkPropTypes: emptyFunctionWithReset, resetWarningCache: emptyFunction }; ReactPropTypes.PropTypes = ReactPropTypes; return ReactPropTypes; }; var propTypes = createCommonjsModule(function (module) { /** * Copyright (c) 2013-present, Facebook, Inc. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ { // By explicitly using `prop-types` you are opting into new production behavior. // http://fb.me/prop-types-in-prod module.exports = factoryWithThrowingShims(); } }); var pointOnCircle = function pointOnCircle(center, radius, angle) { return { x: center + radius * Math.cos(angle), y: center + radius * Math.sin(angle) }; }; var degTorad = function degTorad(deg) { return Math.PI * deg / 180; }; var calcPath = function calcPath(_ref) { var percentage = _ref.percentage, angleOffset = _ref.angleOffset, angleRange = _ref.angleRange, arcWidth = _ref.arcWidth, outerRadius = _ref.radius, center = _ref.center; var angle = angleRange * percentage; var startAngle = angleOffset - 90; var innerRadius = outerRadius - arcWidth; var startAngleDegree = degTorad(startAngle); var endAngleDegree = degTorad(startAngle + angle); var largeArcFlag = angle < 180 ? 0 : 1; var p1 = pointOnCircle(center, outerRadius, endAngleDegree); var p2 = pointOnCircle(center, outerRadius, startAngleDegree); var p3 = pointOnCircle(center, innerRadius, startAngleDegree); var p4 = pointOnCircle(center, innerRadius, endAngleDegree); return "M".concat(p1.x, ",").concat(p1.y, " A").concat(outerRadius, ",").concat(outerRadius, " 0 ").concat(largeArcFlag, " 0 ").concat(p2.x, ",").concat(p2.y, "L").concat(p3.x, ",").concat(p3.y, " A").concat(innerRadius, ",").concat(innerRadius, " 0 ").concat(largeArcFlag, " 1 ").concat(p4.x, ",").concat(p4.y, " L").concat(p1.x, ",").concat(p1.y); }; var Arc = (function (_ref2) { var color = _ref2.color, background = _ref2.background, style = _ref2.style, props = _objectWithoutProperties(_ref2, ["color", "background", "style"]); return React.createElement("g", null, background && React.createElement("path", { d: calcPath(_objectSpread2({}, props, { percentage: 1 })), style: { fill: background, transform: style.transform } }), React.createElement("path", { d: calcPath(props), style: { fill: color, transform: style.transform } })); }); var viewBox = { height: 150, width: 250 }; var angleRange = 270; var angleOffset = 180; var Knob = /*#__PURE__*/ function (_React$Component) { _inherits(Knob, _React$Component); function Knob(props) { var _this; _classCallCheck(this, Knob); _this = _possibleConstructorReturn(this, _getPrototypeOf(Knob).call(this, props)); _this.state = { drag: false, angle: props.defaultPercentage * angleRange, text: { x: 0, y: 0 }, svgRatio: 1, nameWidth: 20, lastVal: null }; _this.handleDown = _this.handleDown.bind(_assertThisInitialized(_this)); _this.handleMove = _this.handleMove.bind(_assertThisInitialized(_this)); _this.handleUp = _this.handleUp.bind(_assertThisInitialized(_this)); _this.calcAngle = _this.calcAngle.bind(_assertThisInitialized(_this)); _this.calcSvgRatio = _this.calcSvgRatio.bind(_assertThisInitialized(_this)); _this.onWindowResize = _this.onWindowResize.bind(_assertThisInitialized(_this)); return _this; } _createClass(Knob, [{ key: "handleDown", value: function handleDown(_ref) { var pageY = _ref.pageY; this.setState({ drag: true }); } }, { key: "handleUp", value: function handleUp() { this.setState({ drag: false, prevPageY: null }); } }, { key: "handleMove", value: function handleMove(_ref2) { var pageY = _ref2.pageY; if (!this.state.drag) return; var _this$props = this.props, transform = _this$props.transform, onChange = _this$props.onChange, mouseSpeed = _this$props.mouseSpeed; var _this$state = this.state, angle = _this$state.angle, prevPageY = _this$state.prevPageY; if (!prevPageY) { this.setState({ prevPageY: pageY }); return; } var delta = (prevPageY - pageY) * mouseSpeed; angle = this.calcAngle(angle, delta, angleRange); onChange(transform(angle / angleRange)); this.setState({ angle: angle, prevPageY: pageY }); } }, { key: "calcAngle", value: function calcAngle(angle, delta, angleRange) { angle += delta; if (angle > angleRange) { angle -= angle - angleRange; } else if (angle < 0) { angle += Math.abs(angle); } return angle; } }, { key: "componentDidMount", value: function componentDidMount() { window.addEventListener("resize", this.onWindowResize); window.addEventListener("mousemove", this.handleMove); window.addEventListener("mouseup", this.handleUp); // NOTE: We call this initially, to set the width and height values. this.onWindowResize(); } }, { key: "calcSvgRatio", value: function calcSvgRatio() { var _this2 = this; var _this$refs$box$getBou = this.refs.box.getBoundingClientRect(), width = _this$refs$box$getBou.width; // NOTE: As the svg preserves it's aspect ratio, we have to calculate only // one value that accounts for both width and height ratios. return new Promise(function (resolve) { _this2.setState({ svgRatio: width / viewBox.width }, resolve); }); } }, { key: "onWindowResize", value: function onWindowResize() { return regeneratorRuntime.async(function onWindowResize$(_context) { while (1) { switch (_context.prev = _context.next) { case 0: _context.next = 2; return regeneratorRuntime.awrap(this.calcSvgRatio()); case 2: this.fitText(); case 3: case "end": return _context.stop(); } } }, null, this); } }, { key: "fitText", value: function fitText() { var svgRatio = this.state.svgRatio; var rect = this.refs.name.getBoundingClientRect(); this.setState({ nameWidth: rect.width / svgRatio }); } }, { key: "render", value: function render() { var _this$props2 = this.props, bg = _this$props2.bg, fg = _this$props2.fg, transform = _this$props2.transform, step = _this$props2.step, unit = _this$props2.unit, name = _this$props2.name, style = _this$props2.style; var _this$state2 = this.state, svgRatio = _this$state2.svgRatio, angle = _this$state2.angle, nameWidth = _this$state2.nameWidth; var percentage = angle / angleRange; var width = viewBox.width, height = viewBox.height; var outerCircle = { arcWidth: 10, radius: 40 }; var font = { marginBottom: 5, size: style && style.fontSize || 40, family: style && style.fontFamily || "Arial" }; return React.createElement("svg", { ref: "box", onMouseDown: this.handleDown, style: style, viewBox: "0 0 ".concat(width, " ").concat(height) }, React.createElement("text", { ref: "name", style: { fill: style && style.color, fontFamily: font.family, pointerEvents: "none", cursor: "pointer", userSelect: "none" }, x: "0", y: font.size, fontSize: font.size }, name), React.createElement("circle", { fill: bg, r: 25, cx: outerCircle.arcWidth + outerCircle.radius, cy: 50 + font.size + font.marginBottom }), React.createElement(Arc, { percentage: percentage, angleOffset: angleOffset, angleRange: angleRange, arcWidth: outerCircle.arcWidth, radius: outerCircle.radius, center: 50, background: bg, color: fg, style: { transform: "translateY(".concat(font.size + font.marginBottom, "px)") } }), React.createElement("text", { ref: "value", style: { fill: style && style.color, fontFamily: style && style.fontFamily || "Arial", pointerEvents: "none", cursor: "pointer", userSelect: "none" }, x: 80, y: outerCircle.arcWidth + 2 * outerCircle.radius + font.size, fontSize: font.size }, "".concat(transform(percentage), " ").concat(unit))); } }]); return Knob; }(React.Component); Knob.propTypes = { defaultPercentage: propTypes.number, onChange: propTypes.func.isRequired, transform: propTypes.func, mouseSpeed: propTypes.number, unit: propTypes.string, name: propTypes.string, style: propTypes.object, bg: propTypes.string, fg: propTypes.string }; Knob.defaultProps = { defaultPercentage: 0, transform: function transform(p) { return p; }, mouseSpeed: 1, unit: "", name: "", bg: "black", fg: "white" }; module.exports = Knob; //# sourceMappingURL=react-simple-knob.cjs.js.map