UNPKG

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