UNPKG

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