UNPKG

tweak-tools

Version:

Tweak your React projects until awesomeness

169 lines (168 loc) 7.15 kB
"use strict"; var __rest = (this && this.__rest) || function (s, e) { var t = {}; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p]; if (s != null && typeof Object.getOwnPropertySymbols === "function") for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) t[p[i]] = s[p[i]]; } return t; }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.getVectorPlugin = exports.normalizeVector = exports.formatVector = exports.sanitizeVector = exports.getVectorType = exports.getVectorSchema = void 0; const v8n_1 = __importDefault(require("v8n")); const utils_1 = require("../../utils"); const number_plugin_1 = require("../Number/number-plugin"); const vector_utils_1 = require("./vector-utils"); function getVectorSchema(dimension) { // Check if vector matches dimension and that every item is a number // prettier-ignore const isVectorArray = (0, v8n_1.default)().array().length(dimension).every.number(); // check if vector is an object and that all its keys are finite numbers const isVectorObject = (o) => { if (!o || typeof o !== 'object') return false; const values = Object.values(o); return values.length === dimension && values.every((v) => isFinite(v)); }; return (o) => { return isVectorArray.test(o) || isVectorObject(o); }; } exports.getVectorSchema = getVectorSchema; /** * Returns 'array' if value is an array, 'object' if it's an object. * @param value * @returns */ function getVectorType(value) { return Array.isArray(value) ? 'array' : 'object'; } exports.getVectorType = getVectorType; /** * Converts a value to either an object or an array. * @param value * @param format * @param keys * @returns */ function convert(value, format, keys) { if (getVectorType(value) === format) return value; return (format === 'array' ? Object.values(value) : (0, utils_1.mapArrayToKeys)(value, keys)); } /** * This function will check if the value argument is the full vector or only * a slice of it. If it's only a slice, then it will merge it with the * previousValue, preserving ratio if settings.lock is set. * @param value * @param settings * @param previousValue * @returns */ const sanitizeVector = (value, settings, previousValue) => { // 1. We convert the value to a keyed object const _value = convert(value, 'object', settings.keys); for (let key in _value) _value[key] = (0, number_plugin_1.sanitize)(_value[key], settings[key]); // 2. We extract the keys const _valueKeys = Object.keys(_value); // will be the new value let newValue = {}; // 3.a. if _value includes all keys of the vector input then _value is // complete and can be considered as the new value. if (_valueKeys.length === settings.keys.length) newValue = _value; // 3.b if _value is only a slice of the vector, therefore we need to merge // it with the previous value. else { // 3.b.i We convert the previous value to an object. const _previousValue = convert(previousValue, 'object', settings.keys); // 3.b.i.1 if there's only one key and lock is true we keep the aspect ratio // on all keys, then we keep the aspect ratio on all keys. if (_valueKeys.length === 1 && settings.locked) { // the only key from _value, which holds the base value for aspect ratio. const lockedKey = _valueKeys[0]; // the base value for aspect ratio. const lockedCoordinate = _value[lockedKey]; // the previous base value for aspect ratio const previousLockedCoordinate = _previousValue[lockedKey]; // iterate through the previous value keys const ratio = previousLockedCoordinate !== 0 ? lockedCoordinate / previousLockedCoordinate : 1; for (let key in _previousValue) { // if key is the lockedKey, then its new value should be the locked // value. if (key === lockedKey) newValue[lockedKey] = lockedCoordinate; // if not then the other key should change by the same ratio as the // lockedValue else newValue[key] = _previousValue[key] * ratio; } } else { // _value is incomplete so we merge the previous value with the new one newValue = Object.assign(Object.assign({}, _previousValue), _value); } } return convert(newValue, settings.format, settings.keys); }; exports.sanitizeVector = sanitizeVector; /** * Formats a vector into an object to be displayed. * @param value * @param settings * @returns */ const formatVector = (value, settings) => convert(value, 'object', settings.keys); exports.formatVector = formatVector; /** * Checks if an object matches the format of the settings object for a number * input. * @param o * @returns */ const isNumberSettings = (o) => !!o && ('step' in o || 'min' in o || 'max' in o); /** * Normalizes a vector by extracting its keys and creating a number settings * for each of them. * @param _value * @param settings * @param defaultKeys * @returns */ function normalizeVector(value, settings, defaultKeys = []) { const { lock = false } = settings, _settings = __rest(settings, ["lock"]); const format = Array.isArray(value) ? 'array' : 'object'; const keys = format === 'object' ? Object.keys(value) : defaultKeys; const _value = convert(value, 'object', keys); // vector can accept either { value: { x, y }, { x: settings, y: settings } } // or { value: { x, y }, { settings } } where settings will apply to both keys // merged settings will recognize a unified settings and dispatch it to all keys const mergedSettings = isNumberSettings(_settings) ? keys.reduce((acc, k) => Object.assign(acc, { [k]: _settings }), {}) : _settings; const numberSettings = (0, vector_utils_1.normalizeKeyedNumberSettings)(_value, mergedSettings); return { value: (format === 'array' ? value : _value), settings: Object.assign(Object.assign({}, numberSettings), { format, keys, lock, locked: false }), }; } exports.normalizeVector = normalizeVector; function getVectorPlugin(defaultKeys) { return { schema: getVectorSchema(defaultKeys.length), normalize: (_a) => { var { value } = _a, settings = __rest(_a, ["value"]); return normalizeVector(value, settings, defaultKeys); }, format: (value, settings) => (0, exports.formatVector)(value, settings), sanitize: (value, settings, prevValue) => (0, exports.sanitizeVector)(value, settings, prevValue), }; } exports.getVectorPlugin = getVectorPlugin;