tweak-tools
Version:
Tweak your React projects until awesomeness
136 lines (135 loc) • 6.02 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Joystick = void 0;
const react_1 = __importStar(require("react"));
const hooks_1 = require("../../hooks");
const utils_1 = require("../../utils");
const StyledJoystick_1 = require("./StyledJoystick");
const styles_1 = require("../../styles");
const UI_1 = require("../UI");
const hooks_2 = require("../../hooks");
function Joystick({ value, settings, onUpdate }) {
const timeout = (0, react_1.useRef)();
const outOfBoundsX = (0, react_1.useRef)(0);
const outOfBoundsY = (0, react_1.useRef)(0);
const stepMultiplier = (0, react_1.useRef)(1);
const [joystickShown, setShowJoystick] = (0, react_1.useState)(false);
const [isOutOfBounds, setIsOutOfBounds] = (0, react_1.useState)(false);
const [spanRef, set] = (0, hooks_2.useTransform)();
const joystickeRef = (0, react_1.useRef)(null);
const playgroundRef = (0, react_1.useRef)(null);
(0, react_1.useLayoutEffect)(() => {
if (joystickShown) {
const { top, left, width, height } = joystickeRef.current.getBoundingClientRect();
playgroundRef.current.style.left = left + width / 2 + 'px';
playgroundRef.current.style.top = top + height / 2 + 'px';
}
}, [joystickShown]);
const { keys: [v1, v2], joystick, } = settings;
const yFactor = joystick === 'invertY' ? 1 : -1;
// prettier-ignore
const { [v1]: { step: stepV1 }, [v2]: { step: stepV2 } } = settings;
const wpx = (0, styles_1.useTh)('sizes', 'joystickWidth');
const hpx = (0, styles_1.useTh)('sizes', 'joystickHeight');
const w = (parseFloat(wpx) * 0.8) / 2;
const h = (parseFloat(hpx) * 0.8) / 2;
const startOutOfBounds = (0, react_1.useCallback)(() => {
if (timeout.current)
return;
setIsOutOfBounds(true);
if (outOfBoundsX.current)
set({ x: outOfBoundsX.current * w });
if (outOfBoundsY.current)
set({ y: outOfBoundsY.current * -h });
timeout.current = window.setInterval(() => {
onUpdate((v) => {
const incX = stepV1 * outOfBoundsX.current * stepMultiplier.current;
const incY = yFactor * stepV2 * outOfBoundsY.current * stepMultiplier.current;
return Array.isArray(v)
? {
[v1]: v[0] + incX,
[v2]: v[1] + incY,
}
: {
[v1]: v[v1] + incX,
[v2]: v[v2] + incY,
};
});
}, 16);
}, [w, h, onUpdate, set, stepV1, stepV2, v1, v2, yFactor]);
const endOutOfBounds = (0, react_1.useCallback)(() => {
window.clearTimeout(timeout.current);
timeout.current = undefined;
setIsOutOfBounds(false);
}, []);
(0, react_1.useEffect)(() => {
function setStepMultiplier(event) {
stepMultiplier.current = (0, utils_1.multiplyStep)(event);
}
window.addEventListener('keydown', setStepMultiplier);
window.addEventListener('keyup', setStepMultiplier);
return () => {
window.clearTimeout(timeout.current);
window.removeEventListener('keydown', setStepMultiplier);
window.removeEventListener('keyup', setStepMultiplier);
};
}, []);
const bind = (0, hooks_1.useDrag)(({ first, active, delta: [dx, dy], movement: [mx, my] }) => {
if (first)
setShowJoystick(true);
const _x = (0, utils_1.clamp)(mx, -w, w);
const _y = (0, utils_1.clamp)(my, -h, h);
outOfBoundsX.current = Math.abs(mx) > Math.abs(_x) ? Math.sign(mx - _x) : 0;
outOfBoundsY.current = Math.abs(my) > Math.abs(_y) ? Math.sign(_y - my) : 0;
// @ts-expect-error
let newX = value[v1];
// @ts-expect-error
let newY = value[v2];
if (active) {
if (!outOfBoundsX.current) {
newX += dx * stepV1 * stepMultiplier.current;
set({ x: _x });
}
if (!outOfBoundsY.current) {
newY -= yFactor * dy * stepV2 * stepMultiplier.current;
set({ y: _y });
}
if (outOfBoundsX.current || outOfBoundsY.current)
startOutOfBounds();
else
endOutOfBounds();
onUpdate({ [v1]: newX, [v2]: newY });
}
else {
setShowJoystick(false);
outOfBoundsX.current = 0;
outOfBoundsY.current = 0;
set({ x: 0, y: 0 });
endOutOfBounds();
}
});
return (react_1.default.createElement(StyledJoystick_1.JoystickTrigger, Object.assign({ ref: joystickeRef }, bind()), joystickShown && (react_1.default.createElement(UI_1.Portal, null,
react_1.default.createElement(StyledJoystick_1.JoystickPlayground, { ref: playgroundRef, isOutOfBounds: isOutOfBounds },
react_1.default.createElement("div", null),
react_1.default.createElement("span", { ref: spanRef }))))));
}
exports.Joystick = Joystick;