All files / ima/page componentHelpers.js

12.5% Statements 3/24
13.04% Branches 3/23
0% Functions 0/10
12.5% Lines 3/24
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207          6x     6x 6x                                                                                                                                                                                                                                                                                                                                                                                                          
import classnames from 'classnames';
import PropTypes from 'prop-types';
import React from 'react';
import ReactDOM from 'react-dom';
 
const PRIVATE = {
  contextTypes: Symbol('contextTypes')
};
Eif (typeof $Debug !== 'undefined' && $Debug) {
  Object.freeze(PRIVATE);
}
 
/**
 * Retrieves the context type declarations for the specified component.
 *
 * @param {function(new: React.Component, ...*)} classConstructor The
 *        constructor of the react component.
 * @return {Object<string, function(...*): boolean>} The context type
 *         declarations associated with the specified component.
 */
export function getContextTypes(classConstructor) {
  if (classConstructor.hasOwnProperty(PRIVATE.contextTypes)) {
    return this[PRIVATE.contextTypes];
  }
 
  return {
    $Utils: PropTypes.object.isRequired
  };
}
 
/**
 * Overrides the previously associated context type declarations for the
 * specified component to the provided ones.
 *
 * @param {function(new: React.Component, ...*)} classConstructor The
 *        constructor of the react component.
 * @param {Object<string, function(...*): boolean>} contextTypes The new
 *        context type declarations to associate with the specified component.
 * @return {Object<string, function(...*): boolean>} The provided context type
 *         declarations.
 */
export function setContextTypes(classConstructor, contextTypes) {
  return (classConstructor[PRIVATE.contextTypes] = contextTypes);
}
 
/**
 * Retrieves the view utilities from the component's current context or
 * properties (preferring the context).
 *
 * @param {Object<string, *>} props The component's current properties.
 * @param {Object<string, *>} context The component's current context.
 * @return {Object<string, *>} The retrieved view utilities.
 * @throws Error Throw if the view utils cannot be located in the provided
 *         properties nor context.
 */
export function getUtils(props, context) {
  const utils = context ? context.$Utils || props.$Utils : props.$Utils;
 
  if ($Debug && !utils) {
    throw new Error(
      'The component cannot access the view utils because they were ' +
        'not passed in the initial props or context as $Utils.'
    );
  }
 
  return utils;
}
 
/**
 * Returns the localized phrase identified by the specified key. The
 * placeholders in the localization phrase will be replaced by the provided
 * values.
 *
 * @param {(AbstractComponent|AbstractPureComponent)} component The component
 *        requiring the localization.
 * @param {string} key Localization key.
 * @param {Object<string, (number|string)>=} params Values for replacing the
 *        placeholders in the localization phrase.
 * @return {string} Localized phrase.
 */
export function localize(component, key, params) {
  return component.utils.$Dictionary.get(key, params);
}
 
/**
 * Generates an absolute URL using the provided route name (see the
 * <code>app/config/routes.js</code> file). The provided parameters will
 * replace the placeholders in the route pattern, while the extraneous
 * parameters will be appended to the generated URL's query string.
 *
 * @param {(AbstractComponent|AbstractPureComponent)} component The component
 *        requiring the generating of the URL.
 * @param {string} name The route name.
 * @param {Object<string, (number|string)>=} params Router parameters and
 *        extraneous parameters to add to the URL as a query string.
 * @return {string} The generated URL.
 */
export function link(component, name, params) {
  return component.utils.$Router.link(name, params);
}
 
/**
 * Generate a string of CSS classes from the properties of the passed-in
 * object that resolve to {@code true}.
 *
 * @example
 *        this.cssClasses('my-class my-class-modificator', true);
 * @example
 *        this.cssClasses({
 *            'my-class': true,
 *            'my-class-modificator': this.props.modificator
 *        }, true);
 * @param {(AbstractComponent|AbstractPureComponent)} component The component
 *        requiring the composition of the CSS class names.
 * @param {(string|Object<string, boolean>)} classRules CSS classes in a
 *        string separated by whitespace, or a map of CSS class names to
 *        boolean values. The CSS class name will be included in the result
 *        only if the value is {@code true}.
 * @param {boolean} includeComponentClassName
 * @return {string} String of CSS classes that had their property resolved
 *         to {@code true}.
 */
export function cssClasses(component, classRules, includeComponentClassName) {
  return component.utils.$CssClasses(
    classRules,
    includeComponentClassName && component
  );
}
 
/**
 * Generate a string of CSS classes from the properties of the passed-in
 * object that resolve to {@code true}.
 *
 * @param {(string|Object<string, boolean>)} classRules CSS classes in a
 *        string separated by whitespace, or a map of CSS class names to
 *        boolean values. The CSS class name will be included in the result
 *        only if the value is {@code true}.
 * @param {?(AbstractComponent|AbstractPureComponent)} component The component
 *        requiring the composition of the CSS class names, if it has the
 *        {@code className} property set and requires its inclusion this time.
 * @return {string} String of CSS classes that had their property resolved
 *         to {@code true}.
 */
export function defaultCssClasses(classRules, component) {
  let extraClasses =
    component instanceof React.Component ? component.props.className : null;
  return classnames(classRules, extraClasses);
}
 
/**
 * Creates and sends a new IMA.js DOM custom event from the provided component.
 *
 * @param {(AbstractComponent|AbstractPureComponent)} component The component
 *        at which's root element the event will originate.
 * @param {string} eventName The name of the event.
 * @param {*=} data Data to send within the event.
 */
export function fire(component, eventName, data = null) {
  return component.utils.$EventBus.fire(
    ReactDOM.findDOMNode(component), //eslint-disable-line react/no-find-dom-node
    eventName,
    data
  );
}
 
/**
 * Registers the provided event listener for execution whenever an IMA.js
 * DOM custom event of the specified name occurs at the specified event
 * target.
 *
 * @param {(AbstractComponent|AbstractPureComponent)} component The component
 *        requesting the registration of the event listener.
 * @param {(React.Element|EventTarget)} eventTarget The react component or
 *        event target at which the listener should listen for the event.
 * @param {string} eventName The name of the event for which to listen.
 * @param {function(Event)} listener The listener for event to register.
 */
export function listen(component, eventTarget, eventName, listener) {
  if (!eventTarget.addEventListener) {
    // Safari doesn't have EventTarget
    eventTarget = ReactDOM.findDOMNode(eventTarget); //eslint-disable-line react/no-find-dom-node
  }
 
  return component.utils.$EventBus.listen(eventTarget, eventName, listener);
}
 
/**
 * Deregisters the provided event listener for an IMA.js DOM custom event
 * of the specified name at the specified event target.
 *
 * @param {(AbstractComponent|AbstractPureComponent)} component The component
 *        that requested the registration of the event listener.
 * @param {(React.Element|EventTarget)} eventTarget The react component or
 *        event target at which the listener should listen for the event.
 * @param {string} eventName The name of the event for which to listen.
 * @param {function(Event)} listener The listener for event to register.
 */
export function unlisten(component, eventTarget, eventName, listener) {
  if (!eventTarget.addEventListener) {
    // Safari doesn't have EventTarget
    eventTarget = ReactDOM.findDOMNode(eventTarget); //eslint-disable-line react/no-find-dom-node
  }
 
  const eventBus = component.utils.$EventBus;
  return eventBus.unlisten(eventTarget, eventName, listener);
}