@uifabric/utilities
Version:
Fluent UI React utilities for building components.
240 lines • 9.61 kB
JavaScript
import { __extends } from "tslib";
import * as React from 'react';
import { Async } from './Async';
import { EventGroup } from './EventGroup';
import { warnConditionallyRequiredProps } from './warn/warnConditionallyRequiredProps';
import { warnMutuallyExclusive } from './warn/warnMutuallyExclusive';
import { warnDeprecations } from './warn/warnDeprecations';
/**
* BaseComponent class, which provides basic helpers for all components.
*
* @public
* {@docCategory BaseComponent}
*
* @deprecated Do not use. We are moving away from class component.
*/
var BaseComponent = /** @class */ (function (_super) {
__extends(BaseComponent, _super);
/**
* BaseComponent constructor
* @param props - The props for the component.
* @param context - The context for the component.
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
function BaseComponent(props, context) {
var _this = _super.call(this, props, context) || this;
// eslint-disable-next-line deprecation/deprecation
_makeAllSafe(_this, BaseComponent.prototype, [
'componentDidMount',
'shouldComponentUpdate',
'getSnapshotBeforeUpdate',
'render',
'componentDidUpdate',
'componentWillUnmount',
]);
return _this;
}
/**
* When the component receives props, make sure the componentRef is updated.
*/
BaseComponent.prototype.componentDidUpdate = function (prevProps, prevState) {
this._updateComponentRef(prevProps, this.props);
};
/**
* When the component has mounted, update the componentRef.
*/
BaseComponent.prototype.componentDidMount = function () {
this._setComponentRef(this.props.componentRef, this);
};
/**
* If we have disposables, dispose them automatically on unmount.
*/
BaseComponent.prototype.componentWillUnmount = function () {
this._setComponentRef(this.props.componentRef, null);
if (this.__disposables) {
for (var i = 0, len = this._disposables.length; i < len; i++) {
var disposable = this.__disposables[i];
if (disposable.dispose) {
disposable.dispose();
}
}
this.__disposables = null;
}
};
Object.defineProperty(BaseComponent.prototype, "className", {
/**
* Gets the object's class name.
*/
get: function () {
if (!this.__className) {
var funcNameRegex = /function (.{1,})\(/;
var results = funcNameRegex.exec(this.constructor.toString());
this.__className = results && results.length > 1 ? results[1] : '';
}
return this.__className;
},
enumerable: true,
configurable: true
});
Object.defineProperty(BaseComponent.prototype, "_disposables", {
/**
* Allows subclasses to push things to this._disposables to be auto disposed.
*/
get: function () {
if (!this.__disposables) {
this.__disposables = [];
}
return this.__disposables;
},
enumerable: true,
configurable: true
});
Object.defineProperty(BaseComponent.prototype, "_async", {
/**
* Gets the async instance associated with the component, created on demand. The async instance gives
* subclasses a way to execute setTimeout/setInterval async calls safely, where the callbacks
* will be cleared/ignored automatically after unmounting. The helpers within the async object also
* preserve the this pointer so that you don't need to "bind" the callbacks.
*/
get: function () {
if (!this.__async) {
this.__async = new Async(this);
this._disposables.push(this.__async);
}
return this.__async;
},
enumerable: true,
configurable: true
});
Object.defineProperty(BaseComponent.prototype, "_events", {
/**
* Gets the event group instance assocaited with the component, created on demand. The event instance
* provides on/off methods for listening to DOM (or regular javascript object) events. The event callbacks
* will be automatically disconnected after unmounting. The helpers within the events object also
* preserve the this reference so that you don't need to "bind" the callbacks.
*/
get: function () {
if (!this.__events) {
this.__events = new EventGroup(this);
this._disposables.push(this.__events);
}
return this.__events;
},
enumerable: true,
configurable: true
});
/**
* Helper to return a memoized ref resolver function.
* @param refName - Name of the member to assign the ref to.
* @returns A function instance keyed from the given refname.
* @deprecated Use `createRef` from React.createRef.
*/
BaseComponent.prototype._resolveRef = function (refName) {
var _this = this;
if (!this.__resolves) {
this.__resolves = {};
}
if (!this.__resolves[refName]) {
this.__resolves[refName] = function (ref) {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
return (_this[refName] = ref);
};
}
return this.__resolves[refName];
};
/**
* Updates the componentRef (by calling it with "this" when necessary.)
*/
BaseComponent.prototype._updateComponentRef = function (currentProps, newProps) {
if (newProps === void 0) { newProps = {}; }
// currentProps *should* always be defined, but verify that just in case a subclass is manually
// calling a lifecycle method with no parameters (which has happened) or other odd usage.
if (currentProps && newProps && currentProps.componentRef !== newProps.componentRef) {
this._setComponentRef(currentProps.componentRef, null);
this._setComponentRef(newProps.componentRef, this);
}
};
/**
* Warns when a deprecated props are being used.
*
* @param deprecationMap - The map of deprecations, where key is the prop name and the value is
* either null or a replacement prop name.
*/
BaseComponent.prototype._warnDeprecations = function (deprecationMap) {
warnDeprecations(this.className, this.props, deprecationMap);
};
/**
* Warns when props which are mutually exclusive with each other are both used.
*
* @param mutuallyExclusiveMap - The map of mutually exclusive props.
*/
BaseComponent.prototype._warnMutuallyExclusive = function (mutuallyExclusiveMap) {
warnMutuallyExclusive(this.className, this.props, mutuallyExclusiveMap);
};
/**
* Warns when props are required if a condition is met.
*
* @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.
*/
BaseComponent.prototype._warnConditionallyRequiredProps = function (requiredProps, conditionalPropName, condition) {
warnConditionallyRequiredProps(this.className, this.props, requiredProps, conditionalPropName, condition);
};
BaseComponent.prototype._setComponentRef = function (ref, value) {
if (!this._skipComponentRefResolution && ref) {
if (typeof ref === 'function') {
ref(value);
}
if (typeof ref === 'object') {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
ref.current = value;
}
}
};
return BaseComponent;
}(React.Component));
export { BaseComponent };
/**
* Helper to override a given method with a wrapper method that can try/catch the original, but also
* ensures that the BaseComponent's methods are called before the subclass's. This ensures that
* componentWillUnmount in the base is called and that things in the _disposables array are disposed.
*/
// eslint-disable-next-line deprecation/deprecation
function _makeAllSafe(obj, prototype, methodNames) {
for (var i = 0, len = methodNames.length; i < len; i++) {
_makeSafe(obj, prototype, methodNames[i]);
}
}
// eslint-disable-next-line deprecation/deprecation
function _makeSafe(obj, prototype, methodName) {
/* eslint-disable @typescript-eslint/no-explicit-any */
var classMethod = obj[methodName];
var prototypeMethod = prototype[methodName];
if (classMethod || prototypeMethod) {
obj[methodName] = function () {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
/* eslint-enable @typescript-eslint/no-explicit-any */
var retVal;
if (prototypeMethod) {
retVal = prototypeMethod.apply(this, args);
}
if (classMethod !== prototypeMethod) {
retVal = classMethod.apply(this, args);
}
return retVal;
};
}
}
/**
* Simple constant function for returning null, used to render empty templates in JSX.
*
* @public
*/
export function nullRender() {
return null;
}
//# sourceMappingURL=BaseComponent.js.map