UNPKG

21.6 kBJavaScriptView Raw
1'use strict';
2
3Object.defineProperty(exports, '__esModule', { value: true });
4
5var _extends = require('@babel/runtime/helpers/extends');
6var _objectWithoutPropertiesLoose = require('@babel/runtime/helpers/objectWithoutPropertiesLoose');
7var React = require('react');
8var hoistNonReactStatics = require('hoist-non-react-statics');
9var theming = require('theming');
10var isInBrowser = require('is-in-browser');
11var warning = require('tiny-warning');
12var jss = require('jss');
13var preset = require('jss-preset-default');
14var shallowEqual = require('shallow-equal');
15var isPropValid = require('@emotion/is-prop-valid');
16var defaultCss = require('css-jss');
17
18function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
19
20var _extends__default = /*#__PURE__*/_interopDefaultLegacy(_extends);
21var _objectWithoutPropertiesLoose__default = /*#__PURE__*/_interopDefaultLegacy(_objectWithoutPropertiesLoose);
22var hoistNonReactStatics__default = /*#__PURE__*/_interopDefaultLegacy(hoistNonReactStatics);
23var isInBrowser__default = /*#__PURE__*/_interopDefaultLegacy(isInBrowser);
24var warning__default = /*#__PURE__*/_interopDefaultLegacy(warning);
25var preset__default = /*#__PURE__*/_interopDefaultLegacy(preset);
26var isPropValid__default = /*#__PURE__*/_interopDefaultLegacy(isPropValid);
27var defaultCss__default = /*#__PURE__*/_interopDefaultLegacy(defaultCss);
28
29var getDisplayName = function getDisplayName(Component) {
30 return Component.displayName || Component.name || 'Component';
31};
32
33var memoize = function memoize(fn) {
34 var lastArgs;
35 var lastResult;
36 return function () {
37 for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
38 args[_key] = arguments[_key];
39 }
40
41 if (Array.isArray(lastArgs) && args.length === lastArgs.length) {
42 var isSame = true;
43
44 for (var i = 0; i < args.length; i++) {
45 if (args[i] !== lastArgs[i]) {
46 isSame = false;
47 }
48 }
49
50 if (isSame) {
51 return lastResult;
52 }
53 }
54
55 lastArgs = args;
56 lastResult = fn.apply(void 0, args);
57 return lastResult;
58 };
59};
60
61var mergeClasses = function mergeClasses(baseClasses, additionalClasses) {
62 var combinedClasses = _extends__default['default']({}, baseClasses);
63
64 for (var name in additionalClasses) {
65 combinedClasses[name] = name in combinedClasses ? combinedClasses[name] + " " + additionalClasses[name] : additionalClasses[name];
66 }
67
68 return combinedClasses;
69};
70
71/**
72 * Global index counter to preserve source order.
73 * As we create the style sheet during componentWillMount lifecycle,
74 * children are handled after the parents, so the order of style elements would
75 * be parent->child. It is a problem though when a parent passes a className
76 * which needs to override any childs styles. StyleSheet of the child has a higher
77 * specificity, because of the source order.
78 * So our solution is to render sheets them in the reverse order child->sheet, so
79 * that parent has a higher specificity.
80 *
81 * We start at [Number.MIN_SAFE_INTEGER] to always insert sheets from react-jss first before any
82 * sheet which might be inserted manually by the user.
83 */
84var index = Number.MIN_SAFE_INTEGER || -1e9;
85
86var getSheetIndex = function getSheetIndex() {
87 return index++;
88};
89
90var JssContext = React.createContext({
91 classNamePrefix: '',
92 disableStylesGeneration: false
93});
94
95var defaultManagers = new Map();
96var getManager = function getManager(context, managerId) {
97 // If `managers` map is present in the context, we use it in order to
98 // let JssProvider reset them when new response has to render server-side.
99 var managers = context.managers;
100
101 if (managers) {
102 if (!managers[managerId]) {
103 managers[managerId] = new jss.SheetsManager();
104 }
105
106 return managers[managerId];
107 }
108
109 var manager = defaultManagers.get(managerId);
110
111 if (!manager) {
112 manager = new jss.SheetsManager();
113 defaultManagers.set(managerId, manager);
114 }
115
116 return manager;
117};
118var manageSheet = function manageSheet(options) {
119 var sheet = options.sheet,
120 context = options.context,
121 index = options.index,
122 theme = options.theme;
123
124 if (!sheet) {
125 return;
126 }
127
128 var manager = getManager(context, index);
129 manager.manage(theme);
130
131 if (context.registry) {
132 context.registry.add(sheet);
133 }
134};
135var unmanageSheet = function unmanageSheet(options) {
136 if (!options.sheet) {
137 return;
138 }
139
140 var manager = getManager(options.context, options.index);
141 manager.unmanage(options.theme);
142};
143
144var defaultJss = jss.create(preset__default['default']());
145
146var sheetsMeta = new WeakMap();
147var getMeta = function getMeta(sheet) {
148 return sheetsMeta.get(sheet);
149};
150var addMeta = function addMeta(sheet, meta) {
151 sheetsMeta.set(sheet, meta);
152};
153
154var getStyles = function getStyles(options) {
155 var styles = options.styles;
156
157 if (typeof styles !== 'function') {
158 return styles;
159 }
160
161 process.env.NODE_ENV !== "production" ? warning__default['default'](styles.length !== 0, "[JSS] <" + (options.name || 'Hook') + " />'s styles function doesn't rely on the \"theme\" argument. We recommend declaring styles as an object instead.") : void 0;
162 return styles(options.theme);
163};
164
165function getSheetOptions(options, link) {
166 var minify;
167
168 if (options.context.id && options.context.id.minify != null) {
169 minify = options.context.id.minify;
170 }
171
172 var classNamePrefix = options.context.classNamePrefix || '';
173
174 if (options.name && !minify) {
175 classNamePrefix += options.name.replace(/\s/g, '-') + "-";
176 }
177
178 var meta = '';
179 if (options.name) meta = options.name + ", ";
180 meta += typeof options.styles === 'function' ? 'Themed' : 'Unthemed';
181 return _extends__default['default']({}, options.sheetOptions, {
182 index: options.index,
183 meta: meta,
184 classNamePrefix: classNamePrefix,
185 link: link,
186 generateId: options.sheetOptions && options.sheetOptions.generateId ? options.sheetOptions.generateId : options.context.generateId
187 });
188}
189
190var createStyleSheet = function createStyleSheet(options) {
191 if (options.context.disableStylesGeneration) {
192 return undefined;
193 }
194
195 var manager = getManager(options.context, options.index);
196 var existingSheet = manager.get(options.theme);
197
198 if (existingSheet) {
199 return existingSheet;
200 }
201
202 var jss$1 = options.context.jss || defaultJss;
203 var styles = getStyles(options);
204 var dynamicStyles = jss.getDynamicStyles(styles);
205 var sheet = jss$1.createStyleSheet(styles, getSheetOptions(options, dynamicStyles !== null));
206 addMeta(sheet, {
207 dynamicStyles: dynamicStyles,
208 styles: styles
209 });
210 manager.add(options.theme, sheet);
211 return sheet;
212};
213var removeDynamicRules = function removeDynamicRules(sheet, rules) {
214 // Loop over each dynamic rule and remove the dynamic rule
215 // We can't just remove the whole sheet as this has all of the rules for every component instance
216 for (var key in rules) {
217 sheet.deleteRule(rules[key]);
218 }
219};
220var updateDynamicRules = function updateDynamicRules(data, sheet, rules) {
221 // Loop over each dynamic rule and update it
222 // We can't just update the whole sheet as this has all of the rules for every component instance
223 for (var key in rules) {
224 sheet.updateOne(rules[key], data);
225 }
226};
227var addDynamicRules = function addDynamicRules(sheet, data) {
228 var meta = getMeta(sheet);
229
230 if (!meta) {
231 return undefined;
232 }
233
234 var rules = {}; // Loop over each dynamic rule and add it to the stylesheet
235
236 for (var key in meta.dynamicStyles) {
237 var initialRuleCount = sheet.rules.index.length;
238 var originalRule = sheet.addRule(key, meta.dynamicStyles[key]); // Loop through all created rules, fixes updating dynamic rules
239
240 for (var i = initialRuleCount; i < sheet.rules.index.length; i++) {
241 var rule = sheet.rules.index[i];
242 sheet.updateOne(rule, data); // If it's the original rule, we need to add it by the correct key so the hook and hoc
243 // can correctly concat the dynamic class with the static one
244
245 rules[originalRule === rule ? key : rule.key] = rule;
246 }
247 }
248
249 return rules;
250};
251
252var getSheetClasses = function getSheetClasses(sheet, dynamicRules) {
253 if (!dynamicRules) {
254 return sheet.classes;
255 }
256
257 var meta = getMeta(sheet);
258
259 if (!meta) {
260 return sheet.classes;
261 }
262
263 var classes = {};
264
265 for (var key in meta.styles) {
266 classes[key] = sheet.classes[key];
267
268 if (key in dynamicRules) {
269 classes[key] += " " + sheet.classes[dynamicRules[key].key];
270 }
271 }
272
273 return classes;
274};
275
276var useEffectOrLayoutEffect = isInBrowser__default['default'] ? React.useLayoutEffect : React.useEffect;
277var noTheme = {};
278
279var createUseStyles = function createUseStyles(styles, options) {
280 if (options === void 0) {
281 options = {};
282 }
283
284 var _options = options,
285 _options$index = _options.index,
286 index = _options$index === void 0 ? getSheetIndex() : _options$index,
287 theming$1 = _options.theming,
288 name = _options.name,
289 sheetOptions = _objectWithoutPropertiesLoose__default['default'](_options, ["index", "theming", "name"]);
290
291 var ThemeContext = theming$1 && theming$1.context || theming.ThemeContext;
292
293 var useTheme = function useTheme(theme) {
294 if (typeof styles === 'function') {
295 return theme || React.useContext(ThemeContext) || noTheme;
296 }
297
298 return noTheme;
299 };
300
301 var emptyObject = {};
302 return function useStyles(data) {
303 var isFirstMount = React.useRef(true);
304 var context = React.useContext(JssContext);
305 var theme = useTheme(data && data.theme);
306
307 var _React$useMemo = React.useMemo(function () {
308 var newSheet = createStyleSheet({
309 context: context,
310 styles: styles,
311 name: name,
312 theme: theme,
313 index: index,
314 sheetOptions: sheetOptions
315 });
316 var newDynamicRules = newSheet ? addDynamicRules(newSheet, data) : null;
317
318 if (newSheet) {
319 manageSheet({
320 index: index,
321 context: context,
322 sheet: newSheet,
323 theme: theme
324 });
325 }
326
327 return [newSheet, newDynamicRules];
328 }, [context, theme]),
329 sheet = _React$useMemo[0],
330 dynamicRules = _React$useMemo[1];
331
332 useEffectOrLayoutEffect(function () {
333 // We only need to update the rules on a subsequent update and not in the first mount
334 if (sheet && dynamicRules && !isFirstMount.current) {
335 updateDynamicRules(data, sheet, dynamicRules);
336 }
337 }, [data]);
338 useEffectOrLayoutEffect(function () {
339 return (// cleanup only
340 function () {
341 if (sheet) {
342 unmanageSheet({
343 index: index,
344 context: context,
345 sheet: sheet,
346 theme: theme
347 });
348 }
349
350 if (sheet && dynamicRules) {
351 removeDynamicRules(sheet, dynamicRules);
352 }
353 }
354 );
355 }, [sheet]);
356 var classes = React.useMemo(function () {
357 return sheet && dynamicRules ? getSheetClasses(sheet, dynamicRules) : emptyObject;
358 }, [sheet, dynamicRules]);
359 React.useDebugValue(classes);
360 React.useDebugValue(theme === noTheme ? 'No theme' : theme);
361 React.useEffect(function () {
362 isFirstMount.current = false;
363 });
364 return classes;
365 };
366};
367
368var NoRenderer = function NoRenderer(props) {
369 return props.children || null;
370};
371/**
372 * HOC creator function that wrapps the user component.
373 *
374 * `withStyles(styles, [options])(Component)`
375 */
376
377
378var createWithStyles = function createWithStyles(styles, options) {
379 if (options === void 0) {
380 options = {};
381 }
382
383 var _options = options,
384 _options$index = _options.index,
385 index = _options$index === void 0 ? getSheetIndex() : _options$index,
386 theming$1 = _options.theming,
387 injectTheme = _options.injectTheme,
388 sheetOptions = _objectWithoutPropertiesLoose__default['default'](_options, ["index", "theming", "injectTheme"]);
389
390 var ThemeContext = theming$1 ? theming$1.context : theming.ThemeContext;
391 return function (InnerComponent) {
392 if (InnerComponent === void 0) {
393 InnerComponent = NoRenderer;
394 }
395
396 var displayName = getDisplayName(InnerComponent);
397 var mergeClassesProp = memoize(function (sheetClasses, classesProp) {
398 return classesProp ? mergeClasses(sheetClasses, classesProp) : sheetClasses;
399 });
400 var hookOptions = Object.assign(sheetOptions, {
401 theming: theming$1,
402 index: index,
403 name: displayName
404 });
405 var useStyles = createUseStyles(styles, hookOptions);
406 var WithStyles = React.forwardRef(function (props, ref) {
407 var theme = React.useContext(ThemeContext);
408
409 var newProps = _extends__default['default']({}, props);
410
411 if (injectTheme && newProps.theme == null) {
412 newProps.theme = theme;
413 }
414
415 var sheetClasses = useStyles(newProps);
416 var classes = mergeClassesProp(sheetClasses, props.classes);
417 return React.createElement(InnerComponent, _extends__default['default']({}, newProps, {
418 classes: classes,
419 ref: ref
420 }));
421 });
422 WithStyles.displayName = "WithStyles(" + displayName + ")";
423 WithStyles.defaultProps = _extends__default['default']({}, InnerComponent.defaultProps);
424 WithStyles.InnerComponent = InnerComponent;
425 return hoistNonReactStatics__default['default'](WithStyles, InnerComponent);
426 };
427};
428
429var initialContext = {};
430function JssProvider(props) {
431 var managersRef = React.useRef({});
432 var prevContextRef = React.useRef();
433 var registryRef = React.useRef(null);
434
435 var createContext = function createContext(parentContext, prevContext) {
436 if (prevContext === void 0) {
437 prevContext = initialContext;
438 }
439
440 var registry = props.registry,
441 classNamePrefix = props.classNamePrefix,
442 jss$1 = props.jss,
443 generateId = props.generateId,
444 disableStylesGeneration = props.disableStylesGeneration,
445 media = props.media,
446 id = props.id;
447
448 var context = _extends__default['default']({}, parentContext);
449
450 if (registry) {
451 context.registry = registry; // This way we identify a new request on the server, because user will create
452 // a new Registry instance for each.
453
454 if (registry !== registryRef.current) {
455 // We reset managers because we have to regenerate all sheets for the new request.
456 managersRef.current = {};
457 registryRef.current = registry;
458 }
459 }
460
461 context.managers = managersRef.current;
462
463 if (id !== undefined) {
464 context.id = id;
465 }
466
467 if (generateId !== undefined) {
468 context.generateId = generateId;
469 } else if (!context.generateId || !prevContext || context.id !== prevContext.id) {
470 context.generateId = jss.createGenerateId(context.id);
471 }
472
473 if (classNamePrefix) {
474 context.classNamePrefix = (context.classNamePrefix || '') + classNamePrefix;
475 }
476
477 if (media !== undefined) {
478 context.media = media;
479 }
480
481 if (jss$1) {
482 context.jss = jss$1;
483 }
484
485 if (disableStylesGeneration !== undefined) {
486 context.disableStylesGeneration = disableStylesGeneration;
487 }
488
489 if (prevContext && shallowEqual.shallowEqualObjects(prevContext, context)) {
490 return prevContext;
491 }
492
493 return context;
494 };
495
496 var renderProvider = function renderProvider(parentContext) {
497 var children = props.children;
498 var context = createContext(parentContext, prevContextRef.current);
499 prevContextRef.current = context;
500 return React.createElement(JssContext.Provider, {
501 value: context
502 }, children);
503 };
504
505 return React.createElement(JssContext.Consumer, null, renderProvider);
506}
507
508var parseStyles = function parseStyles(args) {
509 var dynamicStyles = [];
510 var staticStyle;
511 var labels = []; // Not using ...rest to optimize perf.
512
513 for (var key in args) {
514 var style = args[key];
515 if (!style) continue;
516
517 if (typeof style === 'function') {
518 dynamicStyles.push(style);
519 } else {
520 if (!staticStyle) staticStyle = {};
521 Object.assign(staticStyle, style);
522 var _staticStyle = staticStyle,
523 _label = _staticStyle.label;
524
525 if (_label) {
526 if (labels.indexOf(_label) === -1) labels.push(_label);
527 }
528 }
529 }
530
531 var styles = {};
532 var label = labels.length === 0 ? 'sc' : labels.join('-');
533
534 if (staticStyle) {
535 // Label should not leak to the core.
536 if ('label' in staticStyle) delete staticStyle.label;
537 styles[label] = staticStyle;
538 } // When there is only one function rule, we don't need to wrap it.
539
540
541 if (dynamicStyles.length === 1) {
542 styles.scd = dynamicStyles[0];
543 } // We create a new function rule which will call all other function rules
544 // and merge the styles they return.
545
546
547 if (dynamicStyles.length > 1) {
548 styles.scd = function (props) {
549 var merged = {};
550
551 for (var i = 0; i < dynamicStyles.length; i++) {
552 var dynamicStyle = dynamicStyles[i](props);
553 if (dynamicStyle) Object.assign(merged, dynamicStyle);
554 }
555
556 return merged;
557 };
558 }
559
560 return {
561 styles: styles,
562 label: label
563 };
564};
565
566var shouldForwardPropSymbol = Symbol('react-jss-styled');
567
568var getShouldForwardProp = function getShouldForwardProp(tagOrComponent, options) {
569 var shouldForwardProp = options.shouldForwardProp;
570 var childShouldForwardProp = tagOrComponent[shouldForwardPropSymbol];
571 var finalShouldForwardProp = shouldForwardProp || childShouldForwardProp;
572
573 if (shouldForwardProp && childShouldForwardProp) {
574 finalShouldForwardProp = function finalShouldForwardProp(prop) {
575 return childShouldForwardProp(prop) && shouldForwardProp(prop);
576 };
577 }
578
579 return finalShouldForwardProp;
580};
581
582var getChildProps = function getChildProps(props, shouldForwardProp, isTag) {
583 var childProps = {};
584
585 for (var prop in props) {
586 if (shouldForwardProp) {
587 if (shouldForwardProp(prop) === true) {
588 childProps[prop] = props[prop];
589 }
590
591 continue;
592 } // We don't want to pass non-dom props to the DOM.
593
594
595 if (isTag) {
596 if (isPropValid__default['default'](prop)) {
597 childProps[prop] = props[prop];
598 }
599
600 continue;
601 }
602
603 childProps[prop] = props[prop];
604 }
605
606 return childProps;
607}; // eslint-disable-next-line no-unused-vars
608
609
610var configureStyled = function configureStyled(tagOrComponent, options) {
611 if (options === void 0) {
612 options = {};
613 }
614
615 var _options = options,
616 theming$1 = _options.theming;
617 var isTag = typeof tagOrComponent === 'string';
618 var ThemeContext = theming$1 ? theming$1.context : theming.ThemeContext;
619 var shouldForwardProp = getShouldForwardProp(tagOrComponent, options);
620
621 var _options2 = options,
622 _ = _options2.shouldForwardProp,
623 hookOptions = _objectWithoutPropertiesLoose__default['default'](_options2, ["shouldForwardProp"]);
624
625 return function createStyledComponent() {
626 // eslint-disable-next-line prefer-rest-params
627 var _parseStyles = parseStyles(arguments),
628 styles = _parseStyles.styles,
629 label = _parseStyles.label;
630
631 var useStyles = createUseStyles(styles, hookOptions);
632
633 var Styled = function Styled(props) {
634 var as = props.as,
635 className = props.className;
636 var theme = React.useContext(ThemeContext);
637 var propsWithTheme = Object.assign({
638 theme: theme
639 }, props);
640 var classes = useStyles(propsWithTheme);
641 var childProps = getChildProps(props, shouldForwardProp, isTag);
642 var classNames = ((classes[label] || classes.sc || '') + " " + (classes.scd || '')).trim();
643 childProps.className = className ? className + " " + classNames : classNames;
644
645 if (!isTag && shouldForwardProp) {
646 tagOrComponent[shouldForwardPropSymbol] = shouldForwardProp;
647 }
648
649 if (isTag && as) {
650 return React.createElement(as, childProps);
651 }
652
653 return React.createElement(tagOrComponent, childProps);
654 };
655
656 return Styled;
657 };
658};
659
660/* eslint-disable prefer-rest-params, prefer-spread */
661var create = function create(css) {
662 if (css === void 0) {
663 css = defaultCss__default['default'];
664 }
665
666 return function createElement(type, props) {
667 var args = arguments;
668
669 if (props && props.css) {
670 var className = css(props.css);
671 var newProps = Object.assign({}, props);
672 newProps.className = props.className ? props.className + " " + className : className;
673 delete newProps.css;
674 args[1] = newProps;
675 }
676
677 return React.createElement.apply(undefined, args);
678 };
679};
680var jsx = create();
681
682Object.defineProperty(exports, 'ThemeProvider', {
683 enumerable: true,
684 get: function () {
685 return theming.ThemeProvider;
686 }
687});
688Object.defineProperty(exports, 'createTheming', {
689 enumerable: true,
690 get: function () {
691 return theming.createTheming;
692 }
693});
694Object.defineProperty(exports, 'useTheme', {
695 enumerable: true,
696 get: function () {
697 return theming.useTheme;
698 }
699});
700Object.defineProperty(exports, 'withTheme', {
701 enumerable: true,
702 get: function () {
703 return theming.withTheme;
704 }
705});
706Object.defineProperty(exports, 'SheetsRegistry', {
707 enumerable: true,
708 get: function () {
709 return jss.SheetsRegistry;
710 }
711});
712Object.defineProperty(exports, 'createGenerateId', {
713 enumerable: true,
714 get: function () {
715 return jss.createGenerateId;
716 }
717});
718exports.JssContext = JssContext;
719exports.JssProvider = JssProvider;
720exports.createJsx = create;
721exports.createUseStyles = createUseStyles;
722exports.default = createWithStyles;
723exports.jss = defaultJss;
724exports.jsx = jsx;
725exports.styled = configureStyled;
726exports.withStyles = createWithStyles;