first commit

This commit is contained in:
Stefan Hacker
2026-04-03 09:38:48 +02:00
commit 37ad745546
47450 changed files with 3120798 additions and 0 deletions
+18
View File
@@ -0,0 +1,18 @@
export type ISettingsMap<T> = {
[P in keyof T]?: string;
};
/**
* Sends a warning to console, if the api is present.
*
* @public
* @param message - Warning message.
*/
export declare function warn(message: string): void;
/**
* Configures the warning callback. Passing in undefined will reset it to use the default
* console.warn function.
*
* @public
* @param warningCallback - Callback to override the generated warnings.
*/
export declare function setWarningCallback(warningCallback?: (message: string) => void): void;
+27
View File
@@ -0,0 +1,27 @@
/* eslint-disable no-console */
var _warningCallback = undefined;
/**
* Sends a warning to console, if the api is present.
*
* @public
* @param message - Warning message.
*/
export function warn(message) {
if (_warningCallback && process.env.NODE_ENV !== 'production') {
_warningCallback(message);
}
else if (console && console.warn) {
console.warn(message);
}
}
/**
* Configures the warning callback. Passing in undefined will reset it to use the default
* console.warn function.
*
* @public
* @param warningCallback - Callback to override the generated warnings.
*/
export function setWarningCallback(warningCallback) {
_warningCallback = warningCallback;
}
//# sourceMappingURL=warn.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"warn.js","sourceRoot":"../src/","sources":["warn/warn.ts"],"names":[],"mappings":"AAAA,+BAA+B;AAE/B,IAAI,gBAAgB,GAA4C,SAAS,CAAC;AAI1E;;;;;GAKG;AACH,MAAM,UAAU,IAAI,CAAC,OAAe;IAClC,IAAI,gBAAgB,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,YAAY,EAAE,CAAC;QAC9D,gBAAgB,CAAC,OAAO,CAAC,CAAC;IAC5B,CAAC;SAAM,IAAI,OAAO,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;QACnC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACxB,CAAC;AACH,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,kBAAkB,CAAC,eAA2C;IAC5E,gBAAgB,GAAG,eAAe,CAAC;AACrC,CAAC","sourcesContent":["/* eslint-disable no-console */\n\nlet _warningCallback: ((message: string) => void) | undefined = undefined;\n\nexport type ISettingsMap<T> = { [P in keyof T]?: string };\n\n/**\n * Sends a warning to console, if the api is present.\n *\n * @public\n * @param message - Warning message.\n */\nexport function warn(message: string): void {\n if (_warningCallback && process.env.NODE_ENV !== 'production') {\n _warningCallback(message);\n } else if (console && console.warn) {\n console.warn(message);\n }\n}\n\n/**\n * Configures the warning callback. Passing in undefined will reset it to use the default\n * console.warn function.\n *\n * @public\n * @param warningCallback - Callback to override the generated warnings.\n */\nexport function setWarningCallback(warningCallback?: (message: string) => void): void {\n _warningCallback = warningCallback;\n}\n"]}
+1
View File
@@ -0,0 +1 @@
export {};
+99
View File
@@ -0,0 +1,99 @@
import { setWarningCallback } from './warn';
import { warnConditionallyRequiredProps } from './warnConditionallyRequiredProps';
import { warnMutuallyExclusive } from './warnMutuallyExclusive';
import { warnDeprecations } from './warnDeprecations';
var warningCallback = jest.fn();
function sharedBeforeEach() {
setWarningCallback(warningCallback);
}
function sharedAfterEach() {
warningCallback.mockReset();
setWarningCallback(undefined);
}
describe('warnDeprecations', function () {
beforeEach(sharedBeforeEach);
afterEach(sharedAfterEach);
it('does not warn when unnecessary', function () {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
warnDeprecations('Foo', { bar: 1 }, { foo: null });
expect(warningCallback).not.toHaveBeenCalled();
});
it('can warn on a deprecated prop', function () {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
warnDeprecations('Foo', { foo: 1 }, { foo: null });
expect(warningCallback).toHaveBeenCalledTimes(1);
expect(warningCallback).toHaveBeenLastCalledWith("Foo property 'foo' was used but has been deprecated.");
});
it('can warn on a deprecated prop with replacement', function () {
warnDeprecations('Foo', { foo: 1 }, { foo: 'bar' });
expect(warningCallback).toHaveBeenCalledTimes(1);
expect(warningCallback).toHaveBeenLastCalledWith("Foo property 'foo' was used but has been deprecated. Use 'bar' instead.");
});
});
describe('warnMutuallyExclusive', function () {
beforeEach(sharedBeforeEach);
afterEach(sharedAfterEach);
it('does not warn when unnecessary', function () {
warnMutuallyExclusive('Foo', { foo: 1 }, { foo: 'bar' });
expect(warningCallback).not.toHaveBeenCalled();
});
it('does not warn unnecessarily when the key of the exclusive map is explicitly undefined', function () {
warnMutuallyExclusive('Foo', { foo: undefined, bar: 1 }, { foo: 'bar' });
expect(warningCallback).not.toHaveBeenCalled();
});
it('does not warn unnecessarily when the matching prop of the exclusive map key is explicitly undefined', function () {
warnMutuallyExclusive('Foo', { foo: 1, bar: undefined }, { foo: 'bar' });
expect(warningCallback).not.toHaveBeenCalled();
});
it('does not warn unnecessarily when both of them are explicitly undefined', function () {
warnMutuallyExclusive('Foo', { foo: undefined, bar: undefined }, { foo: 'bar' });
expect(warningCallback).not.toHaveBeenCalled();
});
it('does not warn unnecessarily when the key of the exclusive map is implicitly undefined', function () {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
warnMutuallyExclusive('Foo', { bar: 1 }, { foo: 'bar' });
expect(warningCallback).not.toHaveBeenCalled();
});
it('does not warn unnecessarily when the matching prop of the exclusive map is implicitly undefined', function () {
warnMutuallyExclusive('Foo', { foo: 1 }, { foo: 'bar' });
expect(warningCallback).not.toHaveBeenCalled();
});
it('does not warn unnecessarily when both of the props are implicitly undefined ', function () {
warnMutuallyExclusive('Foo', {}, {});
expect(warningCallback).not.toHaveBeenCalled();
});
it('can warn on mutual exclusive props', function () {
warnMutuallyExclusive('Foo', { foo: 1, bar: 1 }, { foo: 'bar' });
expect(warningCallback).toHaveBeenCalledTimes(1);
expect(warningCallback).toHaveBeenLastCalledWith("Foo property 'foo' is mutually exclusive with 'bar'. Use one or the other.");
});
it('can warn if the exclusive props with the key in the map is null', function () {
warnMutuallyExclusive('Foo', { foo: null, bar: 1 }, { foo: 'bar' });
expect(warningCallback).toHaveBeenCalledTimes(1);
expect(warningCallback).toHaveBeenLastCalledWith("Foo property 'foo' is mutually exclusive with 'bar'. Use one or the other.");
});
it('can warn if the matching key in exclusive map is null', function () {
warnMutuallyExclusive('Foo', { foo: 1, bar: null }, { foo: 'bar' });
expect(warningCallback).toHaveBeenCalledTimes(1);
expect(warningCallback).toHaveBeenLastCalledWith("Foo property 'foo' is mutually exclusive with 'bar'. Use one or the other.");
});
it('can warn if both of the props are null', function () {
warnMutuallyExclusive('Foo', { foo: null, bar: null }, { foo: 'bar' });
expect(warningCallback).toHaveBeenCalledTimes(1);
expect(warningCallback).toHaveBeenLastCalledWith("Foo property 'foo' is mutually exclusive with 'bar'. Use one or the other.");
});
});
describe('warnConditionallyRequiredProps', function () {
beforeEach(sharedBeforeEach);
afterEach(sharedAfterEach);
it('does not warn when unnecessary', function () {
warnConditionallyRequiredProps('Foo', { foo: 1, bar: 1 }, ['foo', 'bar'], 'foo', true);
expect(warningCallback).not.toHaveBeenCalled();
});
it('can warn on required props', function () {
warnConditionallyRequiredProps('Foo', { foo: 1 }, ['foo', 'bar'], 'foo', true);
expect(warningCallback).toHaveBeenCalledTimes(1);
expect(warningCallback).toHaveBeenLastCalledWith("Foo property 'bar' is required when 'foo' is used.'");
});
});
//# sourceMappingURL=warn.test.js.map
File diff suppressed because one or more lines are too long
@@ -0,0 +1,11 @@
/**
* Warns when props are required if a condition is met.
*
* @public
* @param componentName - The name of the component being used.
* @param props - The props passed into the component.
* @param requiredProps - The name of the props that are required when the condition is met.
* @param conditionalPropName - The name of the prop that the condition is based on.
* @param condition - Whether the condition is met.
*/
export declare function warnConditionallyRequiredProps<P extends {}>(componentName: string, props: P, requiredProps: string[], conditionalPropName: string, condition: boolean): void;
@@ -0,0 +1,22 @@
import { warn } from './warn';
/**
* Warns when props are required if a condition is met.
*
* @public
* @param componentName - The name of the component being used.
* @param props - The props passed into the component.
* @param requiredProps - The name of the props that are required when the condition is met.
* @param conditionalPropName - The name of the prop that the condition is based on.
* @param condition - Whether the condition is met.
*/
export function warnConditionallyRequiredProps(componentName, props, requiredProps, conditionalPropName, condition) {
if (condition === true && process.env.NODE_ENV !== 'production') {
for (var _i = 0, requiredProps_1 = requiredProps; _i < requiredProps_1.length; _i++) {
var requiredPropName = requiredProps_1[_i];
if (!(requiredPropName in props)) {
warn("".concat(componentName, " property '").concat(requiredPropName, "' is required when '").concat(conditionalPropName, "' is used.'"));
}
}
}
}
//# sourceMappingURL=warnConditionallyRequiredProps.js.map
@@ -0,0 +1 @@
{"version":3,"file":"warnConditionallyRequiredProps.js","sourceRoot":"../src/","sources":["warn/warnConditionallyRequiredProps.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAC9B;;;;;;;;;GASG;AACH,MAAM,UAAU,8BAA8B,CAC5C,aAAqB,EACrB,KAAQ,EACR,aAAuB,EACvB,mBAA2B,EAC3B,SAAkB;IAElB,IAAI,SAAS,KAAK,IAAI,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,YAAY,EAAE,CAAC;QAChE,KAA+B,UAAa,EAAb,+BAAa,EAAb,2BAAa,EAAb,IAAa,EAAE,CAAC;YAA1C,IAAM,gBAAgB,sBAAA;YACzB,IAAI,CAAC,CAAC,gBAAgB,IAAI,KAAK,CAAC,EAAE,CAAC;gBACjC,IAAI,CAAC,UAAG,aAAa,wBAAc,gBAAgB,iCAAuB,mBAAmB,gBAAa,CAAC,CAAC;YAC9G,CAAC;QACH,CAAC;IACH,CAAC;AACH,CAAC","sourcesContent":["import { warn } from './warn';\n/**\n * Warns when props are required if a condition is met.\n *\n * @public\n * @param componentName - The name of the component being used.\n * @param props - The props passed into the component.\n * @param requiredProps - The name of the props that are required when the condition is met.\n * @param conditionalPropName - The name of the prop that the condition is based on.\n * @param condition - Whether the condition is met.\n */\nexport function warnConditionallyRequiredProps<P extends {}>(\n componentName: string,\n props: P,\n requiredProps: string[],\n conditionalPropName: string,\n condition: boolean,\n): void {\n if (condition === true && process.env.NODE_ENV !== 'production') {\n for (const requiredPropName of requiredProps) {\n if (!(requiredPropName in props)) {\n warn(`${componentName} property '${requiredPropName}' is required when '${conditionalPropName}' is used.'`);\n }\n }\n }\n}\n"]}
+31
View File
@@ -0,0 +1,31 @@
/** Reset controlled usage warnings for testing purposes. */
export declare function resetControlledWarnings(): void;
export interface IWarnControlledUsageParams<P> {
/** ID of the component instance. Used to prevent showing warnings repeatedly. */
componentId: string;
/** Name of the component class. */
componentName: string;
/** Current props to evaluate. */
props: P;
/** Previous props to evaluate (undefined if called in the constructor). */
oldProps?: P;
/** Name of the prop for the controlled value. */
valueProp: keyof P;
/** Name of the prop for the uncontrolled initial value. */
defaultValueProp: keyof P;
/** Name of the change handler prop. */
onChangeProp: keyof P;
/** Name of the read-only prop. */
readOnlyProp?: keyof P;
}
/**
* Check for and warn on the following error conditions with a form component:
* - A value prop is provided (indicated it's being used as controlled) without a change handler,
* and the component is not read-only
* - Both the value and defaultValue props are provided
* - The component is attempting to switch between controlled and uncontrolled
*
* The messages mimic the warnings React gives for these error conditions on input elements.
* The warning will only be displayed once per component ID.
*/
export declare function warnControlledUsage<P>(params: IWarnControlledUsageParams<P>): void;
+73
View File
@@ -0,0 +1,73 @@
import { warn } from './warn';
import { isControlled as checkIsControlled } from '../controlled';
var warningsMap;
if (process.env.NODE_ENV !== 'production') {
warningsMap = {
valueOnChange: {},
valueDefaultValue: {},
controlledToUncontrolled: {},
uncontrolledToControlled: {},
};
}
/** Reset controlled usage warnings for testing purposes. */
export function resetControlledWarnings() {
if (process.env.NODE_ENV !== 'production') {
warningsMap.valueOnChange = {};
warningsMap.valueDefaultValue = {};
warningsMap.controlledToUncontrolled = {};
warningsMap.uncontrolledToControlled = {};
}
}
/**
* Check for and warn on the following error conditions with a form component:
* - A value prop is provided (indicated it's being used as controlled) without a change handler,
* and the component is not read-only
* - Both the value and defaultValue props are provided
* - The component is attempting to switch between controlled and uncontrolled
*
* The messages mimic the warnings React gives for these error conditions on input elements.
* The warning will only be displayed once per component ID.
*/
export function warnControlledUsage(params) {
if (process.env.NODE_ENV !== 'production') {
var componentId = params.componentId, componentName = params.componentName, defaultValueProp = params.defaultValueProp, props = params.props, oldProps = params.oldProps, onChangeProp = params.onChangeProp, readOnlyProp = params.readOnlyProp, valueProp = params.valueProp;
// This warning logic closely follows what React does for native <input> elements.
var oldIsControlled = oldProps ? checkIsControlled(oldProps, valueProp) : undefined;
var newIsControlled = checkIsControlled(props, valueProp);
if (newIsControlled) {
// onChange (or readOnly) must be provided if value is provided
var hasOnChange = !!props[onChangeProp];
var isReadOnly = !!(readOnlyProp && props[readOnlyProp]);
if (!(hasOnChange || isReadOnly) && !warningsMap.valueOnChange[componentId]) {
warningsMap.valueOnChange[componentId] = true;
warn("Warning: You provided a '".concat(String(valueProp), "' prop to a ").concat(String(componentName), " without an '").concat(String(onChangeProp), "' handler. ") +
"This will render a read-only field. If the field should be mutable use '".concat(String(defaultValueProp), "'. ") +
"Otherwise, set '".concat(String(onChangeProp), "'").concat(readOnlyProp ? " or '".concat(String(readOnlyProp), "'") : '', "."));
}
// value and defaultValue are mutually exclusive
var defaultValue = props[defaultValueProp];
if (defaultValue !== undefined && defaultValue !== null && !warningsMap.valueDefaultValue[componentId]) {
warningsMap.valueDefaultValue[componentId] = true;
warn("Warning: You provided both '".concat(String(valueProp), "' and '").concat(String(defaultValueProp), "' to a ").concat(componentName, ". ") +
"Form fields must be either controlled or uncontrolled (specify either the '".concat(String(valueProp), "' prop, ") +
"or the '".concat(String(defaultValueProp), "' prop, but not both). Decide between using a controlled or uncontrolled ") +
"".concat(componentName, " and remove one of these props. More info: https://fb.me/react-controlled-components"));
}
}
// Warn if switching between uncontrolled and controlled. (One difference between this implementation
// and React's <input> is that if oldIsControlled is indeterminate and newIsControlled true, we don't warn.)
if (oldProps && newIsControlled !== oldIsControlled) {
var oldType = oldIsControlled ? 'a controlled' : 'an uncontrolled';
var newType = oldIsControlled ? 'uncontrolled' : 'controlled';
var warnMap = oldIsControlled ? warningsMap.controlledToUncontrolled : warningsMap.uncontrolledToControlled;
if (!warnMap[componentId]) {
warnMap[componentId] = true;
warn("Warning: A component is changing ".concat(oldType, " ").concat(componentName, " to be ").concat(newType, ". ") +
"".concat(componentName, "s should not switch from controlled to uncontrolled (or vice versa). ") +
"Decide between using controlled or uncontrolled for the lifetime of the component. " +
"More info: https://fb.me/react-controlled-components");
}
}
}
}
//# sourceMappingURL=warnControlledUsage.js.map
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
export {};
+163
View File
@@ -0,0 +1,163 @@
import { __assign, __rest } from "tslib";
import { setWarningCallback } from './warn';
import { warnControlledUsage, resetControlledWarnings } from './warnControlledUsage';
var warningCallback = jest.fn();
var noOp = function () { return undefined; };
var params = {
componentId: 'TestComponent1',
componentName: 'TestComponent',
valueProp: 'value',
defaultValueProp: 'defaultValue',
onChangeProp: 'onChange',
readOnlyProp: 'readOnly',
};
describe('warnControlledUsage', function () {
beforeEach(function () {
setWarningCallback(warningCallback);
});
afterEach(function () {
warningCallback.mockReset();
setWarningCallback(undefined);
resetControlledWarnings();
});
it('does not warn or throw if old props are undefined', function () {
warnControlledUsage(__assign(__assign({}, params), { props: {} }));
expect(warningCallback).toHaveBeenCalledTimes(0);
// If oldProps was defined, this would be an error for switching from uncontrolled to controlled
warnControlledUsage(__assign(__assign({}, params), { props: { value: 'test', onChange: noOp } }));
expect(warningCallback).toHaveBeenCalledTimes(0);
});
it('does not warn if uncontrolled regardless of if onChange/readOnly is provided', function () {
warnControlledUsage(__assign(__assign({}, params), { props: { defaultValue: 'test' } }));
expect(warningCallback).toHaveBeenCalledTimes(0);
warnControlledUsage(__assign(__assign({}, params), { props: {} }));
expect(warningCallback).toHaveBeenCalledTimes(0);
warnControlledUsage(__assign(__assign({}, params), { props: { defaultValue: 'test', onChange: noOp } }));
expect(warningCallback).toHaveBeenCalledTimes(0);
warnControlledUsage(__assign(__assign({}, params), { props: { onChange: noOp } }));
expect(warningCallback).toHaveBeenCalledTimes(0);
warnControlledUsage(__assign(__assign({}, params), { props: { defaultValue: 'test', readOnly: true } }));
expect(warningCallback).toHaveBeenCalledTimes(0);
warnControlledUsage(__assign(__assign({}, params), { props: { readOnly: true } }));
expect(warningCallback).toHaveBeenCalledTimes(0);
});
it('does not warn if controlled and onChange is provided', function () {
warnControlledUsage(__assign(__assign({}, params), { props: { value: 'test', onChange: noOp } }));
expect(warningCallback).toHaveBeenCalledTimes(0);
});
it('does not warn if controlled and readOnly is true', function () {
warnControlledUsage(__assign(__assign({}, params), { props: { value: 'test', readOnly: true } }));
expect(warningCallback).toHaveBeenCalledTimes(0);
});
it('warns if controlled and onChange/readOnly is not provided', function () {
warnControlledUsage(__assign(__assign({}, params), { props: { value: 'test' } }));
expect(warningCallback).toHaveBeenCalledTimes(1);
expect(warningCallback).toHaveBeenLastCalledWith("Warning: You provided a 'value' prop to a TestComponent without an 'onChange' handler. This will render a " +
"read-only field. If the field should be mutable use 'defaultValue'. Otherwise, set 'onChange' or 'readOnly'.");
// Don't re-warn
warnControlledUsage(__assign(__assign({}, params), { props: { value: 'test' } }));
expect(warningCallback).toHaveBeenCalledTimes(1);
});
it('warns if controlled and onChange is not provided (right message for component without readOnly)', function () {
var readOnlyProp = params.readOnlyProp, otherParams = __rest(params, ["readOnlyProp"]);
warnControlledUsage(__assign(__assign({}, otherParams), { props: { value: 'test' } }));
expect(warningCallback).toHaveBeenCalledTimes(1);
expect(warningCallback).toHaveBeenLastCalledWith("Warning: You provided a 'value' prop to a TestComponent without an 'onChange' handler. This will render a " +
"read-only field. If the field should be mutable use 'defaultValue'. Otherwise, set 'onChange'.");
// Don't re-warn
warnControlledUsage(__assign(__assign({}, otherParams), { props: { value: 'test' } }));
expect(warningCallback).toHaveBeenCalledTimes(1);
});
it('re-warns when componentId changes for controlled without onChange', function () {
warnControlledUsage(__assign(__assign({}, params), { props: { value: 'test' } }));
expect(warningCallback).toHaveBeenCalledTimes(1);
warnControlledUsage(__assign(__assign({}, params), { componentId: 'TestComponent2', props: { value: 'test' } }));
expect(warningCallback).toHaveBeenCalledTimes(2);
});
it('warns if controlled and readOnly is false', function () {
warnControlledUsage(__assign(__assign({}, params), { props: { value: 'test', readOnly: false } }));
expect(warningCallback).toHaveBeenCalledTimes(1);
expect(warningCallback).toHaveBeenLastCalledWith("Warning: You provided a 'value' prop to a TestComponent without an 'onChange' handler. This will render a " +
"read-only field. If the field should be mutable use 'defaultValue'. Otherwise, set 'onChange' or 'readOnly'.");
// Don't re-warn
warnControlledUsage(__assign(__assign({}, params), { props: { value: 'test', readOnly: false } }));
expect(warningCallback).toHaveBeenCalledTimes(1);
});
it('warns if both value and defaultValue are provided', function () {
warnControlledUsage(__assign(__assign({}, params), { props: { value: 'hello', defaultValue: 'world', onChange: noOp } }));
expect(warningCallback).toHaveBeenCalledTimes(1);
expect(warningCallback).toHaveBeenLastCalledWith("Warning: You provided both 'value' and 'defaultValue' to a TestComponent. Form fields must be either " +
"controlled or uncontrolled (specify either the 'value' prop, or the 'defaultValue' prop, but not both). " +
"Decide between using a controlled or uncontrolled TestComponent and remove one of these props. " +
"More info: https://fb.me/react-controlled-components");
// Don't re-warn
warnControlledUsage(__assign(__assign({}, params), { props: { value: 'hello', defaultValue: 'world', onChange: noOp } }));
expect(warningCallback).toHaveBeenCalledTimes(1);
});
it('re-warns when componentId changes if both value and defaultValue are provided', function () {
warnControlledUsage(__assign(__assign({}, params), { props: { value: 'hello', defaultValue: 'world', onChange: noOp } }));
expect(warningCallback).toHaveBeenCalledTimes(1);
warnControlledUsage(__assign(__assign({}, params), { componentId: 'TestComponent2', props: { value: 'hello', defaultValue: 'world', onChange: noOp } }));
expect(warningCallback).toHaveBeenCalledTimes(2);
});
it('does not warn if old and new are uncontrolled', function () {
warnControlledUsage(__assign(__assign({}, params), { oldProps: { defaultValue: 'test' }, props: { defaultValue: 'test' } }));
expect(warningCallback).toHaveBeenCalledTimes(0);
warnControlledUsage(__assign(__assign({}, params), { props: {}, oldProps: {} }));
expect(warningCallback).toHaveBeenCalledTimes(0);
});
it('does not warn if old and new are controlled', function () {
warnControlledUsage(__assign(__assign({}, params), { oldProps: { value: 'world', onChange: noOp }, props: { value: 'test', onChange: noOp } }));
expect(warningCallback).toHaveBeenCalledTimes(0);
});
it('warns if old is implicitly uncontrolled and new is controlled', function () {
warnControlledUsage(__assign(__assign({}, params), { oldProps: {}, props: { value: 'test', onChange: noOp } }));
expect(warningCallback).toHaveBeenCalledTimes(1);
expect(warningCallback).toHaveBeenLastCalledWith("Warning: A component is changing an uncontrolled TestComponent to be controlled. TestComponents should not " +
"switch from controlled to uncontrolled (or vice versa). Decide between using controlled or uncontrolled " +
"for the lifetime of the component. More info: https://fb.me/react-controlled-components");
// Don't re-warn
warnControlledUsage(__assign(__assign({}, params), { oldProps: {}, props: { value: 'test', onChange: noOp } }));
expect(warningCallback).toHaveBeenCalledTimes(1);
});
it('warns if old is uncontrolled and new is controlled', function () {
warnControlledUsage(__assign(__assign({}, params), { oldProps: {}, props: { value: 'test', onChange: noOp } }));
expect(warningCallback).toHaveBeenCalledTimes(1);
expect(warningCallback).toHaveBeenLastCalledWith("Warning: A component is changing an uncontrolled TestComponent to be controlled. TestComponents should not " +
"switch from controlled to uncontrolled (or vice versa). Decide between using controlled or uncontrolled " +
"for the lifetime of the component. More info: https://fb.me/react-controlled-components");
});
it('re-warns when componentId changes if old is uncontrolled and new is controlled', function () {
warnControlledUsage(__assign(__assign({}, params), { oldProps: {}, props: { value: 'test', onChange: noOp } }));
expect(warningCallback).toHaveBeenCalledTimes(1);
warnControlledUsage(__assign(__assign({}, params), { componentId: 'TestComponent2', oldProps: {}, props: { value: 'test', onChange: noOp } }));
expect(warningCallback).toHaveBeenCalledTimes(2);
});
it('warns if old is controlled and new is implicitly uncontrolled', function () {
warnControlledUsage(__assign(__assign({}, params), { oldProps: { value: 'test', onChange: noOp }, props: {} }));
expect(warningCallback).toHaveBeenCalledTimes(1);
expect(warningCallback).toHaveBeenLastCalledWith("Warning: A component is changing a controlled TestComponent to be uncontrolled. TestComponents should not " +
"switch from controlled to uncontrolled (or vice versa). Decide between using controlled or uncontrolled " +
"for the lifetime of the component. More info: https://fb.me/react-controlled-components");
// Don't re-warn
warnControlledUsage(__assign(__assign({}, params), { oldProps: { value: 'test', onChange: noOp }, props: {} }));
expect(warningCallback).toHaveBeenCalledTimes(1);
});
it('warns if old is controlled and new is uncontrolled', function () {
warnControlledUsage(__assign(__assign({}, params), { oldProps: { value: 'hello', onChange: noOp }, props: { defaultValue: 'world' } }));
expect(warningCallback).toHaveBeenCalledTimes(1);
expect(warningCallback).toHaveBeenLastCalledWith("Warning: A component is changing a controlled TestComponent to be uncontrolled. TestComponents should not " +
"switch from controlled to uncontrolled (or vice versa). Decide between using controlled or uncontrolled " +
"for the lifetime of the component. More info: https://fb.me/react-controlled-components");
// Don't re-warn
warnControlledUsage(__assign(__assign({}, params), { oldProps: { value: 'hello', onChange: noOp }, props: { defaultValue: 'world' } }));
expect(warningCallback).toHaveBeenCalledTimes(1);
});
it('re-warns when componentId changes if old is controlled and new is implicitly uncontrolled', function () {
warnControlledUsage(__assign(__assign({}, params), { oldProps: { value: 'test', onChange: noOp }, props: {} }));
expect(warningCallback).toHaveBeenCalledTimes(1);
warnControlledUsage(__assign(__assign({}, params), { componentId: 'TestComponent2', oldProps: { value: 'test', onChange: noOp }, props: {} }));
expect(warningCallback).toHaveBeenCalledTimes(2);
});
});
//# sourceMappingURL=warnControlledUsage.test.js.map
File diff suppressed because one or more lines are too long
+11
View File
@@ -0,0 +1,11 @@
import type { ISettingsMap } from './warn';
/**
* Warns when a deprecated props are being used.
*
* @public
* @param componentName - The name of the component being used.
* @param props - The props passed into the component.
* @param deprecationMap - The map of deprecations, where key is the prop name and the value is
* either null or a replacement prop name.
*/
export declare function warnDeprecations<P extends {}>(componentName: string, props: P, deprecationMap: ISettingsMap<P>): void;
+25
View File
@@ -0,0 +1,25 @@
import { warn } from './warn';
/**
* Warns when a deprecated props are being used.
*
* @public
* @param componentName - The name of the component being used.
* @param props - The props passed into the component.
* @param deprecationMap - The map of deprecations, where key is the prop name and the value is
* either null or a replacement prop name.
*/
export function warnDeprecations(componentName, props, deprecationMap) {
if (process.env.NODE_ENV !== 'production') {
for (var propName in deprecationMap) {
if (props && propName in props) {
var deprecationMessage = "".concat(componentName, " property '").concat(propName, "' was used but has been deprecated.");
var replacementPropName = deprecationMap[propName];
if (replacementPropName) {
deprecationMessage += " Use '".concat(replacementPropName, "' instead.");
}
warn(deprecationMessage);
}
}
}
}
//# sourceMappingURL=warnDeprecations.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"warnDeprecations.js","sourceRoot":"../src/","sources":["warn/warnDeprecations.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAG9B;;;;;;;;GAQG;AACH,MAAM,UAAU,gBAAgB,CAAe,aAAqB,EAAE,KAAQ,EAAE,cAA+B;IAC7G,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,YAAY,EAAE,CAAC;QAC1C,KAAK,IAAM,QAAQ,IAAI,cAAc,EAAE,CAAC;YACtC,IAAI,KAAK,IAAI,QAAQ,IAAI,KAAK,EAAE,CAAC;gBAC/B,IAAI,kBAAkB,GAAG,UAAG,aAAa,wBAAc,QAAQ,wCAAqC,CAAC;gBACrG,IAAM,mBAAmB,GAAG,cAAc,CAAC,QAAQ,CAAC,CAAC;gBACrD,IAAI,mBAAmB,EAAE,CAAC;oBACxB,kBAAkB,IAAI,gBAAS,mBAAmB,eAAY,CAAC;gBACjE,CAAC;gBACD,IAAI,CAAC,kBAAkB,CAAC,CAAC;YAC3B,CAAC;QACH,CAAC;IACH,CAAC;AACH,CAAC","sourcesContent":["import { warn } from './warn';\nimport type { ISettingsMap } from './warn';\n\n/**\n * Warns when a deprecated props are being used.\n *\n * @public\n * @param componentName - The name of the component being used.\n * @param props - The props passed into the component.\n * @param deprecationMap - The map of deprecations, where key is the prop name and the value is\n * either null or a replacement prop name.\n */\nexport function warnDeprecations<P extends {}>(componentName: string, props: P, deprecationMap: ISettingsMap<P>): void {\n if (process.env.NODE_ENV !== 'production') {\n for (const propName in deprecationMap) {\n if (props && propName in props) {\n let deprecationMessage = `${componentName} property '${propName}' was used but has been deprecated.`;\n const replacementPropName = deprecationMap[propName];\n if (replacementPropName) {\n deprecationMessage += ` Use '${replacementPropName}' instead.`;\n }\n warn(deprecationMessage);\n }\n }\n }\n}\n"]}
+10
View File
@@ -0,0 +1,10 @@
import type { ISettingsMap } from './warn';
/**
* Warns when two props which are mutually exclusive are both being used.
*
* @public
* @param componentName - The name of the component being used.
* @param props - The props passed into the component.
* @param exclusiveMap - A map where the key is a parameter, and the value is the other parameter.
*/
export declare function warnMutuallyExclusive<P>(componentName: string, props: P, exclusiveMap: ISettingsMap<P>): void;
+23
View File
@@ -0,0 +1,23 @@
import { warn } from './warn';
/**
* Warns when two props which are mutually exclusive are both being used.
*
* @public
* @param componentName - The name of the component being used.
* @param props - The props passed into the component.
* @param exclusiveMap - A map where the key is a parameter, and the value is the other parameter.
*/
export function warnMutuallyExclusive(componentName, props, exclusiveMap) {
if (process.env.NODE_ENV !== 'production') {
for (var propName in exclusiveMap) {
if (props && props[propName] !== undefined) {
var propInExclusiveMapValue = exclusiveMap[propName];
if (propInExclusiveMapValue && props[propInExclusiveMapValue] !== undefined) {
warn("".concat(componentName, " property '").concat(propName, "' is mutually exclusive with '").concat(exclusiveMap[propName], "'. ") +
"Use one or the other.");
}
}
}
}
}
//# sourceMappingURL=warnMutuallyExclusive.js.map
@@ -0,0 +1 @@
{"version":3,"file":"warnMutuallyExclusive.js","sourceRoot":"../src/","sources":["warn/warnMutuallyExclusive.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAG9B;;;;;;;GAOG;AACH,MAAM,UAAU,qBAAqB,CAAI,aAAqB,EAAE,KAAQ,EAAE,YAA6B;IACrG,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,YAAY,EAAE,CAAC;QAC1C,KAAK,IAAM,QAAQ,IAAI,YAAY,EAAE,CAAC;YACpC,IAAI,KAAK,IAAI,KAAK,CAAC,QAAQ,CAAC,KAAK,SAAS,EAAE,CAAC;gBAC3C,IAAI,uBAAuB,GAAG,YAAY,CAAC,QAAQ,CAAC,CAAC;gBACrD,IAAI,uBAAuB,IAAI,KAAK,CAAC,uBAAkC,CAAC,KAAK,SAAS,EAAE,CAAC;oBACvF,IAAI,CACF,UAAG,aAAa,wBAAc,QAAQ,2CAAiC,YAAY,CAAC,QAAQ,CAAC,QAAK;wBAChG,uBAAuB,CAC1B,CAAC;gBACJ,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;AACH,CAAC","sourcesContent":["import { warn } from './warn';\nimport type { ISettingsMap } from './warn';\n\n/**\n * Warns when two props which are mutually exclusive are both being used.\n *\n * @public\n * @param componentName - The name of the component being used.\n * @param props - The props passed into the component.\n * @param exclusiveMap - A map where the key is a parameter, and the value is the other parameter.\n */\nexport function warnMutuallyExclusive<P>(componentName: string, props: P, exclusiveMap: ISettingsMap<P>): void {\n if (process.env.NODE_ENV !== 'production') {\n for (const propName in exclusiveMap) {\n if (props && props[propName] !== undefined) {\n let propInExclusiveMapValue = exclusiveMap[propName];\n if (propInExclusiveMapValue && props[propInExclusiveMapValue as keyof P] !== undefined) {\n warn(\n `${componentName} property '${propName}' is mutually exclusive with '${exclusiveMap[propName]}'. ` +\n `Use one or the other.`,\n );\n }\n }\n }\n }\n}\n"]}