Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

react-jsonschema-form

Package Overview
Dependencies
Maintainers
7
Versions
103
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

react-jsonschema-form - npm Package Compare versions

Comparing version 1.2.1 to 1.3.0

10

lib/components/fields/MultiSchemaField.js

@@ -141,2 +141,6 @@ "use strict";

// Remove the "required" field as it's likely that not all fields have
// been filled in yet, which will mean that the schema is not valid
delete augmentedSchema.required;
if ((0, _validate.isValid)(augmentedSchema, formData)) {

@@ -238,3 +242,7 @@ return i;

if ((0, _utils.guessType)(formData) === "object") {
var newOption = options[selectedOption];
// If the new option is of type object and the current data is an object,
// discard properties added using the old option.
if ((0, _utils.guessType)(formData) === "object" && (newOption.type === "object" || newOption.properties)) {
var newFormData = (0, _assign2.default)({}, formData);

@@ -241,0 +249,0 @@

@@ -11,2 +11,26 @@ "use strict";

var _objectWithoutProperties2 = require("babel-runtime/helpers/objectWithoutProperties");
var _objectWithoutProperties3 = _interopRequireDefault(_objectWithoutProperties2);
var _getPrototypeOf = require("babel-runtime/core-js/object/get-prototype-of");
var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf);
var _classCallCheck2 = require("babel-runtime/helpers/classCallCheck");
var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
var _createClass2 = require("babel-runtime/helpers/createClass");
var _createClass3 = _interopRequireDefault(_createClass2);
var _possibleConstructorReturn2 = require("babel-runtime/helpers/possibleConstructorReturn");
var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2);
var _inherits2 = require("babel-runtime/helpers/inherits");
var _inherits3 = _interopRequireDefault(_inherits2);
var _react = require("react");

@@ -26,11 +50,94 @@

function NumberField(props) {
var StringField = props.registry.fields.StringField;
// Matches a string that ends in a . character, optionally followed by a sequence of
// digits followed by any number of 0 characters up until the end of the line.
// Ensuring that there is at least one prefixed character is important so that
// you don't incorrectly match against "0".
var trailingCharMatcherWithPrefix = /\.([0-9]*0)*$/;
return _react2.default.createElement(StringField, (0, _extends3.default)({}, props, {
onChange: function onChange(value) {
return props.onChange((0, _utils.asNumber)(value));
// This is used for trimming the trailing 0 and . characters without affecting
// the rest of the string. Its possible to use one RegEx with groups for this
// functionality, but it is fairly complex compared to simply defining two
// different matchers.
var trailingCharMatcher = /[0.]0*$/;
/**
* The NumberField class has some special handling for dealing with trailing
* decimal points and/or zeroes. This logic is designed to allow trailing values
* to be visible in the input element, but not be represented in the
* corresponding form data.
*
* The algorithm is as follows:
*
* 1. When the input value changes the value is cached in the component state
*
* 2. The value is then normalized, removing trailing decimal points and zeros,
* then passed to the "onChange" callback
*
* 3. When the component is rendered, the formData value is checked against the
* value cached in the state. If it matches the cached value, the cached
* value is passed to the input instead of the formData value
*/
var NumberField = function (_React$Component) {
(0, _inherits3.default)(NumberField, _React$Component);
function NumberField(props) {
(0, _classCallCheck3.default)(this, NumberField);
var _this = (0, _possibleConstructorReturn3.default)(this, (NumberField.__proto__ || (0, _getPrototypeOf2.default)(NumberField)).call(this, props));
_this.handleChange = function (value) {
// Cache the original value in component state
_this.setState({ lastValue: value });
// Normalize decimals that don't start with a zero character in advance so
// that the rest of the normalization logic is simpler
if (("" + value).charAt(0) === ".") {
value = "0" + value;
}
// Check that the value is a string (this can happen if the widget used is a
// <select>, due to an enum declaration etc) then, if the value ends in a
// trailing decimal point or multiple zeroes, strip the trailing values
var processed = typeof value === "string" && value.match(trailingCharMatcherWithPrefix) ? (0, _utils.asNumber)(value.replace(trailingCharMatcher, "")) : (0, _utils.asNumber)(value);
_this.props.onChange(processed);
};
_this.state = {
lastValue: props.value
};
return _this;
}
(0, _createClass3.default)(NumberField, [{
key: "render",
value: function render() {
var StringField = this.props.registry.fields.StringField;
var _props = this.props,
formData = _props.formData,
props = (0, _objectWithoutProperties3.default)(_props, ["formData"]);
var lastValue = this.state.lastValue;
var value = formData;
if (typeof lastValue === "string" && value) {
// Construct a regular expression that checks for a string that consists
// of the formData value suffixed with zero or one '.' characters and zero
// or more '0' characters
var re = new RegExp(("" + value).replace(".", "\\.") + "\\.?0*$");
// If the cached "lastValue" is a match, use that instead of the formData
// value to prevent the input value from changing in the UI
if (lastValue.match(re)) {
value = lastValue;
}
}
return _react2.default.createElement(StringField, (0, _extends3.default)({}, props, { formData: value, onChange: this.handleChange }));
}
}));
}
}]);
return NumberField;
}(_react2.default.Component);

@@ -37,0 +144,0 @@ if (process.env.NODE_ENV !== "production") {

2

lib/components/fields/ObjectField.js

@@ -300,3 +300,3 @@ "use strict";

idPrefix: idPrefix,
formData: formData[name],
formData: (formData || {})[name],
onKeyChange: _this2.onKeyChange(name),

@@ -303,0 +303,0 @@ onChange: _this2.onPropertyChange(name, addedByAdditionalProperties),

@@ -168,10 +168,12 @@ "use strict";

}
return _react2.default.createElement(
"div",
null,
_react2.default.createElement("p", null),
_react2.default.createElement(
"ul",
{ className: "error-detail bs-callout bs-callout-info" },
errors.map(function (error, index) {
errors.filter(function (elem) {
return !!elem;
}).map(function (error, index) {
return _react2.default.createElement(

@@ -188,3 +190,2 @@ "li",

var id = props.id,
classNames = props.classNames,
label = props.label,

@@ -197,5 +198,3 @@ children = props.children,

required = props.required,
displayLabel = props.displayLabel,
onKeyChange = props.onKeyChange,
onDropPropertyClick = props.onDropPropertyClick;
displayLabel = props.displayLabel;

@@ -210,5 +209,62 @@ if (hidden) {

var additional = props.schema.hasOwnProperty(_utils.ADDITIONAL_PROPERTY_FLAG);
var keyLabel = label + " Key";
return _react2.default.createElement(
WrapIfAdditional,
props,
displayLabel && _react2.default.createElement(Label, { label: label, required: required, id: id }),
displayLabel && description ? description : null,
children,
errors,
help
);
}
if (process.env.NODE_ENV !== "production") {
DefaultTemplate.propTypes = {
id: _propTypes2.default.string,
classNames: _propTypes2.default.string,
label: _propTypes2.default.string,
children: _propTypes2.default.node.isRequired,
errors: _propTypes2.default.element,
rawErrors: _propTypes2.default.arrayOf(_propTypes2.default.string),
help: _propTypes2.default.element,
rawHelp: _propTypes2.default.oneOfType([_propTypes2.default.string, _propTypes2.default.element]),
description: _propTypes2.default.element,
rawDescription: _propTypes2.default.oneOfType([_propTypes2.default.string, _propTypes2.default.element]),
hidden: _propTypes2.default.bool,
required: _propTypes2.default.bool,
readonly: _propTypes2.default.bool,
displayLabel: _propTypes2.default.bool,
fields: _propTypes2.default.object,
formContext: _propTypes2.default.object
};
}
DefaultTemplate.defaultProps = {
hidden: false,
readonly: false,
required: false,
displayLabel: true
};
function WrapIfAdditional(props) {
var id = props.id,
classNames = props.classNames,
disabled = props.disabled,
label = props.label,
onKeyChange = props.onKeyChange,
onDropPropertyClick = props.onDropPropertyClick,
readonly = props.readonly,
required = props.required,
schema = props.schema;
var keyLabel = label + " Key"; // i18n ?
var additional = schema.hasOwnProperty(_utils.ADDITIONAL_PROPERTY_FLAG);
if (!additional) {
return _react2.default.createElement(
"div",
{ className: classNames },
props.children
);
}
return _react2.default.createElement(

@@ -219,4 +275,4 @@ "div",

"div",
{ className: additional ? "row" : "" },
additional && _react2.default.createElement(
{ className: "row" },
_react2.default.createElement(
"div",

@@ -238,9 +294,4 @@ { className: "col-xs-5 form-additional" },

"div",
{
className: additional ? "form-additional form-group col-xs-5" : "" },
displayLabel && _react2.default.createElement(Label, { label: label, required: required, id: id }),
displayLabel && description ? description : null,
children,
errors,
help
{ className: "form-additional form-group col-xs-5" },
props.children
),

@@ -250,3 +301,3 @@ _react2.default.createElement(

{ className: "col-xs-2" },
additional && _react2.default.createElement(_IconButton2.default, {
_react2.default.createElement(_IconButton2.default, {
type: "danger",

@@ -257,4 +308,4 @@ icon: "remove",

style: { border: "0" },
disabled: props.disabled || props.readonly,
onClick: onDropPropertyClick(props.label)
disabled: disabled || readonly,
onClick: onDropPropertyClick(label)
})

@@ -265,30 +316,3 @@ )

}
if (process.env.NODE_ENV !== "production") {
DefaultTemplate.propTypes = {
id: _propTypes2.default.string,
classNames: _propTypes2.default.string,
label: _propTypes2.default.string,
children: _propTypes2.default.node.isRequired,
errors: _propTypes2.default.element,
rawErrors: _propTypes2.default.arrayOf(_propTypes2.default.string),
help: _propTypes2.default.element,
rawHelp: _propTypes2.default.oneOfType([_propTypes2.default.string, _propTypes2.default.element]),
description: _propTypes2.default.element,
rawDescription: _propTypes2.default.oneOfType([_propTypes2.default.string, _propTypes2.default.element]),
hidden: _propTypes2.default.bool,
required: _propTypes2.default.bool,
readonly: _propTypes2.default.bool,
displayLabel: _propTypes2.default.bool,
fields: _propTypes2.default.object,
formContext: _propTypes2.default.object
};
}
DefaultTemplate.defaultProps = {
hidden: false,
readonly: false,
required: false,
displayLabel: true
};
function SchemaFieldRender(props) {

@@ -295,0 +319,0 @@ var uiSchema = props.uiSchema,

@@ -103,2 +103,3 @@ "use strict";

event.preventDefault();
event.persist();

@@ -124,3 +125,3 @@ if (!_this.props.noValidate) {

if (_this.props.onSubmit) {
_this.props.onSubmit((0, _extends3.default)({}, _this.state, { status: "submitted" }));
_this.props.onSubmit((0, _extends3.default)({}, _this.state, { status: "submitted" }), event);
}

@@ -160,4 +161,5 @@ });

var retrievedSchema = (0, _utils.retrieveSchema)(schema, definitions, formData);
var additionalMetaSchemas = props.additionalMetaSchemas;
var _ref = mustValidate ? this.validate(formData, schema) : {
var _ref = mustValidate ? this.validate(formData, schema, additionalMetaSchemas) : {
errors: state.errors || [],

@@ -177,3 +179,4 @@ errorSchema: state.errorSchema || {}

errors: errors,
errorSchema: errorSchema
errorSchema: errorSchema,
additionalMetaSchemas: additionalMetaSchemas
};

@@ -190,2 +193,3 @@ }

var schema = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : this.props.schema;
var additionalMetaSchemas = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : this.props.additionalMetaSchemas;
var _props = this.props,

@@ -199,3 +203,3 @@ validate = _props.validate,

var resolvedSchema = (0, _utils.retrieveSchema)(schema, definitions, formData);
return (0, _validate2.default)(formData, resolvedSchema, validate, transformErrors);
return (0, _validate2.default)(formData, resolvedSchema, validate, transformErrors, additionalMetaSchemas);
}

@@ -372,4 +376,5 @@ }, {

safeRenderCompletion: _propTypes2.default.bool,
formContext: _propTypes2.default.object
formContext: _propTypes2.default.object,
additionalMetaSchemas: _propTypes2.default.arrayOf(_propTypes2.default.object)
};
}

@@ -49,4 +49,29 @@ "use strict";

// If options.inputType is set use that as the input type
inputProps.type = options.inputType || inputProps.type || "text";
if (options.inputType) {
inputProps.type = options.inputType;
} else if (!inputProps.type) {
// If the schema is of type number or integer, set the input type to number
if (schema.type === "number") {
inputProps.type = "number";
// Setting step to 'any' fixes a bug in Safari where decimals are not
// allowed in number inputs
inputProps.step = "any";
} else if (schema.type === "integer") {
inputProps.type = "number";
// Since this is integer, you always want to step up or down in multiples
// of 1
inputProps.step = "1";
} else {
inputProps.type = "text";
}
}
// If multipleOf is defined, use this as the step value. This mainly improves
// the experience for keyboard users (who can use the up/down KB arrows).
if (schema.multipleOf) {
inputProps.step = schema.multipleOf;
}
var _onChange = function _onChange(_ref) {

@@ -76,3 +101,2 @@ var value = _ref.target.value;

BaseInput.defaultProps = {
type: "text",
required: false,

@@ -79,0 +103,0 @@ disabled: false,

@@ -21,2 +21,31 @@ "use strict";

// Check to see if a schema specifies that a value must be true
function schemaRequiresTrueValue(schema) {
// Check if const is a truthy value
if (schema.const) {
return true;
}
// Check if an enum has a single value of true
if (schema.enum && schema.enum.length === 1 && schema.enum[0] === true) {
return true;
}
// If anyOf has a single value, evaluate the subschema
if (schema.anyOf && schema.anyOf.length === 1) {
return schemaRequiresTrueValue(schema.anyOf[0]);
}
// If oneOf has a single value, evaluate the subschema
if (schema.oneOf && schema.oneOf.length === 1) {
return schemaRequiresTrueValue(schema.oneOf[0]);
}
// Evaluate each subschema in allOf, to see if one of them requires a true
// value
if (schema.allOf) {
return schema.allOf.some(schemaRequiresTrueValue);
}
}
function CheckboxWidget(props) {

@@ -26,3 +55,2 @@ var schema = props.schema,

value = props.value,
required = props.required,
disabled = props.disabled,

@@ -36,2 +64,8 @@ readonly = props.readonly,

// Because an unchecked checkbox will cause html5 validation to fail, only add
// the "required" attribute if the field value must be "true", due to the
// "const" or "enum" keywords
var required = schemaRequiresTrueValue(schema);
return _react2.default.createElement(

@@ -38,0 +72,0 @@ "div",

@@ -113,3 +113,3 @@ "use strict";

} },
!multiple && !schema.default && _react2.default.createElement(
!multiple && schema.default === undefined && _react2.default.createElement(
"option",

@@ -116,0 +116,0 @@ { value: "" },

@@ -166,2 +166,7 @@ "use strict";

if (!type && schema.const) {
return guessType(schema.const);
}
if (!type && schema.enum) {

@@ -806,3 +811,6 @@ type = "string";

var fieldId = idSchema.$id + "_" + name;
idSchema[name] = toIdSchema(field, fieldId, definitions, formData[name], idPrefix);
idSchema[name] = toIdSchema(field, fieldId, definitions,
// It's possible that formData is not an object -- this can happen if an
// array item has just been added, but not populated with data yet
(formData || {})[name], idPrefix);
}

@@ -809,0 +817,0 @@ return idSchema;

@@ -7,2 +7,6 @@ "use strict";

var _toConsumableArray2 = require("babel-runtime/helpers/toConsumableArray");
var _toConsumableArray3 = _interopRequireDefault(_toConsumableArray2);
var _defineProperty2 = require("babel-runtime/helpers/defineProperty");

@@ -40,11 +44,21 @@

var ajv = new _ajv2.default({
errorDataPath: "property",
allErrors: true,
multipleOfPrecision: 8
});
// add custom formats
ajv.addFormat("data-url", /^data:([a-z]+\/[a-z0-9-+.]+)?;(?:name=(.*);)?base64,(.*)$/);
ajv.addFormat("color", /^(#?([0-9A-Fa-f]{3}){1,2}\b|aqua|black|blue|fuchsia|gray|green|lime|maroon|navy|olive|orange|purple|red|silver|teal|white|yellow|(rgb\(\s*\b([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\b\s*,\s*\b([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\b\s*,\s*\b([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\b\s*\))|(rgb\(\s*(\d?\d%|100%)+\s*,\s*(\d?\d%|100%)+\s*,\s*(\d?\d%|100%)+\s*\)))$/);
var ajv = createAjvInstance();
var formerMetaSchema = null;
function createAjvInstance() {
var ajv = new _ajv2.default({
errorDataPath: "property",
allErrors: true,
multipleOfPrecision: 8,
schemaId: "auto"
});
// add custom formats
ajv.addFormat("data-url", /^data:([a-z]+\/[a-z0-9-+.]+)?;(?:name=(.*);)?base64,(.*)$/);
ajv.addFormat("color", /^(#?([0-9A-Fa-f]{3}){1,2}\b|aqua|black|blue|fuchsia|gray|green|lime|maroon|navy|olive|orange|purple|red|silver|teal|white|yellow|(rgb\(\s*\b([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\b\s*,\s*\b([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\b\s*,\s*\b([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\b\s*\))|(rgb\(\s*(\d?\d%|100%)+\s*,\s*(\d?\d%|100%)+\s*,\s*(\d?\d%|100%)+\s*\)))$/);
return ajv;
}
function toErrorSchema(errors) {

@@ -116,3 +130,5 @@ // Transforms a ajv validation errors list:

} else {
parent.__errors = [message];
if (message) {
parent.__errors = [message];
}
}

@@ -213,7 +229,16 @@ return errorSchema;

function validateFormData(formData, schema, customValidate, transformErrors) {
var additionalMetaSchemas = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : [];
// add more schemas to validate against
if (additionalMetaSchemas && !(0, _utils.deepEquals)(formerMetaSchema, additionalMetaSchemas) && Array.isArray(additionalMetaSchemas)) {
ajv = createAjvInstance();
ajv.addMetaSchema(additionalMetaSchemas);
formerMetaSchema = additionalMetaSchemas;
}
var validationError = null;
try {
ajv.validate(schema, formData);
} catch (e) {
// swallow errors thrown in ajv due to invalid schemas, these
// still get displayed
} catch (err) {
validationError = err;
}

@@ -223,9 +248,26 @@

// Clear errors to prevent persistent errors, see #1104
ajv.errors = null;
var noProperMetaSchema = validationError && validationError.message && typeof validationError.message === "string" && validationError.message.includes("no schema with key or ref ");
if (noProperMetaSchema) {
errors = [].concat((0, _toConsumableArray3.default)(errors), [{
stack: validationError.message
}]);
}
if (typeof transformErrors === "function") {
errors = transformErrors(errors);
}
var errorSchema = toErrorSchema(errors);
if (noProperMetaSchema) {
errorSchema = (0, _extends7.default)({}, errorSchema, {
$schema: {
__errors: [validationError.message]
}
});
}
if (typeof customValidate !== "function") {

@@ -243,3 +285,6 @@ return { errors: errors, errorSchema: errorSchema };

return { errors: newErrors, errorSchema: newErrorSchema };
return {
errors: newErrors,
errorSchema: newErrorSchema
};
}

@@ -246,0 +291,0 @@

{
"name": "react-jsonschema-form",
"version": "1.2.1",
"version": "1.3.0",
"description": "A simple React component capable of building HTML forms out of a JSON schema.",
"scripts": {
"build:readme": "toctoc README.md -w",
"build:lib": "rimraf lib && cross-env NODE_ENV=production babel -d lib/ src/",

@@ -17,7 +16,8 @@ "build:dist": "rimraf dist && cross-env NODE_ENV=production webpack --config webpack.config.dist.js",

"publish-to-gh-pages": "npm run build:playground && gh-pages --dist build/",
"publish-to-npm": "npm run build:readme && npm run dist && npm publish",
"preversion": "npm run build:playground && npm run dist && npm run build:readme && npm run cs-check && npm run lint",
"publish-to-npm": "npm run dist && npm publish",
"preversion": "npm run build:playground && npm run dist && npm run cs-check && npm run lint",
"start": "node devServer.js",
"tdd": "cross-env NODE_ENV=test mocha --require babel-register --watch --require ./test/setup-jsdom.js test/**/*_test.js",
"test": "cross-env NODE_ENV=test mocha --require babel-register --require ./test/setup-jsdom.js test/**/*_test.js",
"test-coverage": "cross-env NODE_ENV=test nyc --reporter=lcov mocha --require babel-register --require ./test/setup-jsdom.js test/**/*_test.js",
"test-debug": "cross-env NODE_ENV=test mocha --require babel-register --require ./test/setup-jsdom.js --debug-brk --inspect test/Form_test.js"

@@ -47,3 +47,3 @@ },

"dependencies": {
"ajv": "^5.2.3",
"ajv": "^6.7.0",
"babel-runtime": "^6.26.0",

@@ -88,2 +88,3 @@ "core-js": "^2.5.7",

"mocha": "^5.2.0",
"nyc": "^13.2.0",
"prettier": "^1.15.1",

@@ -100,3 +101,2 @@ "react": "^15.5.0",

"style-loader": "^0.13.1",
"toctoc": "^0.2.3",
"webpack": "^4.20.2",

@@ -103,0 +103,0 @@ "webpack-cli": "^3.1.2",

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc