tweak-tools
Version:
Tweak your React projects until awesomeness
142 lines (141 loc) • 6.78 kB
JavaScript
;
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;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.sanitizeValue = exports.updateInput = exports.normalizeInput = exports.parseOptions = void 0;
const lite_1 = require("dequal/lite");
const _1 = require(".");
const plugin_1 = require("../plugin");
const types_1 = require("../types");
function parseOptions(_input, key, mergedOptions = {}, customType) {
var _a, _b;
// if input isn't an object then we just need to assing default options to it.
if (typeof _input !== 'object' || Array.isArray(_input)) {
return {
type: customType,
input: _input,
options: Object.assign({ key, label: key, optional: false, disabled: false, order: 0 }, mergedOptions),
};
}
// if it's a custom input, then the input will be under the __customInput key
// so we run the parseOptions function on that key and for its type.
if ('__customInput' in _input) {
/**
* If a custom input uses a non object arg, the only way to parse options
* is { ...myPlugin('value'), label: 'my label' }.
* In that case, the input will be shaped like so:
* { type, __customInput, label }
*/
const { type, __customInput } = _input, options = __rest(_input, ["type", "__customInput"]);
return parseOptions(__customInput, key, options, type);
}
// parse generic options from input object
const { render, label, optional, order = 0, disabled, hint, onChange, onEditStart, onEditEnd, transient } = _input, inputWithType = __rest(_input, ["render", "label", "optional", "order", "disabled", "hint", "onChange", "onEditStart", "onEditEnd", "transient"]);
const commonOptions = Object.assign({ render,
key, label: label !== null && label !== void 0 ? label : key, hint, transient: transient !== null && transient !== void 0 ? transient : !!onChange, onEditStart,
onEditEnd,
disabled,
optional,
order }, mergedOptions);
let { type } = inputWithType, input = __rest(inputWithType, ["type"]);
type = customType !== null && customType !== void 0 ? customType : type;
if (type in types_1.SpecialInputs) {
return { type, input, options: commonOptions };
}
// in case this is a custom input like beziers where the argument is an array,
// then the array could be passed as { value: [0,0,0,0], onChange: () => {} }.
let computedInput;
if (customType && (0, _1.isObject)(input) && 'value' in input)
computedInput = input.value;
else
computedInput = (0, _1.isEmptyObject)(input) ? undefined : input;
return {
type,
input: computedInput,
options: Object.assign(Object.assign({}, commonOptions), { onChange, optional: (_a = commonOptions.optional) !== null && _a !== void 0 ? _a : false, disabled: (_b = commonOptions.disabled) !== null && _b !== void 0 ? _b : false }),
};
}
exports.parseOptions = parseOptions;
/**
* This function is used to normalize the way an input is stored in the store.
* Returns a value in the form of { type, value, settings} by doing different
* checks depending on the input structure.
*
* @param input
* @param path
*/
function normalizeInput(_input, key, path, data) {
const parsedInputAndOptions = parseOptions(_input, key);
const { type, input: parsedInput, options } = parsedInputAndOptions;
if (type) {
if (type in types_1.SpecialInputs)
// If the input is a special input then we return it as it is.
return parsedInputAndOptions;
// If the type key exists at this point, it must be a forced type or a
// custom plugin defined by the user.
return { type, input: (0, plugin_1.normalize)(type, parsedInput, path, data), options };
}
let inputType = (0, plugin_1.getValueType)(parsedInput);
if (inputType)
return { type: inputType, input: (0, plugin_1.normalize)(inputType, parsedInput, path, data), options };
inputType = (0, plugin_1.getValueType)({ value: parsedInput });
if (inputType)
return { type: inputType, input: (0, plugin_1.normalize)(inputType, { value: parsedInput }, path, data), options };
// At this point, the input is not recognized and we return false.
return false;
}
exports.normalizeInput = normalizeInput;
function updateInput(input, newValue, path, store, fromPanel) {
const { value, type, settings } = input;
input.value = sanitizeValue({ type, value, settings }, newValue, path, store);
input.fromPanel = fromPanel;
}
exports.updateInput = updateInput;
const ValueError = function (message, value, error) {
this.type = 'tweak_error';
this.message = 'Tweak: ' + message;
this.previousValue = value;
this.error = error;
};
function sanitizeValue({ type, value, settings }, newValue, path, store) {
const _newValue = type !== 'SELECT' && typeof newValue === 'function' ? newValue(value) : newValue;
let sanitizedNewValue;
try {
sanitizedNewValue = (0, plugin_1.sanitize)(type, _newValue, settings, value, path, store);
}
catch (e) {
throw new ValueError(`The value \`${newValue}\` did not result in a correct value.`, value, e);
}
if ((0, lite_1.dequal)(sanitizedNewValue, value)) {
/**
* @note This makes the update function throw when the new value is the same
* as the previous one. This can happen for example, if the minimum value of
* a number is 30, and the user inputs 15. Then the newValue will be sanitized
* to 30 and subsequent calls like 14, 0, etc. won't result in the component displaying
* the value to be notified (ie there wouldn't be a new render)
*/
/**
* @update 22.10.22 this warning is a bit cumbersome when dragging something, which can
* result in the same value being set. Commenting out.
*/
return value;
/*
throw new ValueError(
`The value \`${newValue}\` did not result in a value update, which remained the same: \`${value}\`.
You can ignore this warning if this is the intended behavior.`,
value
)
*/
}
return sanitizedNewValue;
}
exports.sanitizeValue = sanitizeValue;