mirror of
https://github.com/idanoo/GoScrobble.git
synced 2024-11-25 09:55:15 +00:00
257 lines
6.7 KiB
JavaScript
257 lines
6.7 KiB
JavaScript
|
import _objectWithoutPropertiesLoose from "@babel/runtime/helpers/esm/objectWithoutPropertiesLoose";
|
||
|
import _extends from "@babel/runtime/helpers/esm/extends";
|
||
|
import React from 'react';
|
||
|
import { getDynamicStyles } from 'jss';
|
||
|
import mergeClasses from '../mergeClasses';
|
||
|
import multiKeyStore from './multiKeyStore';
|
||
|
import useTheme from '../useTheme';
|
||
|
import { StylesContext } from '../StylesProvider';
|
||
|
import { increment } from './indexCounter';
|
||
|
import getStylesCreator from '../getStylesCreator';
|
||
|
import noopTheme from '../getStylesCreator/noopTheme';
|
||
|
|
||
|
function getClasses({
|
||
|
state,
|
||
|
stylesOptions
|
||
|
}, classes, Component) {
|
||
|
if (stylesOptions.disableGeneration) {
|
||
|
return classes || {};
|
||
|
}
|
||
|
|
||
|
if (!state.cacheClasses) {
|
||
|
state.cacheClasses = {
|
||
|
// Cache for the finalized classes value.
|
||
|
value: null,
|
||
|
// Cache for the last used classes prop pointer.
|
||
|
lastProp: null,
|
||
|
// Cache for the last used rendered classes pointer.
|
||
|
lastJSS: {}
|
||
|
};
|
||
|
} // Tracks if either the rendered classes or classes prop has changed,
|
||
|
// requiring the generation of a new finalized classes object.
|
||
|
|
||
|
|
||
|
let generate = false;
|
||
|
|
||
|
if (state.classes !== state.cacheClasses.lastJSS) {
|
||
|
state.cacheClasses.lastJSS = state.classes;
|
||
|
generate = true;
|
||
|
}
|
||
|
|
||
|
if (classes !== state.cacheClasses.lastProp) {
|
||
|
state.cacheClasses.lastProp = classes;
|
||
|
generate = true;
|
||
|
}
|
||
|
|
||
|
if (generate) {
|
||
|
state.cacheClasses.value = mergeClasses({
|
||
|
baseClasses: state.cacheClasses.lastJSS,
|
||
|
newClasses: classes,
|
||
|
Component
|
||
|
});
|
||
|
}
|
||
|
|
||
|
return state.cacheClasses.value;
|
||
|
}
|
||
|
|
||
|
function attach({
|
||
|
state,
|
||
|
theme,
|
||
|
stylesOptions,
|
||
|
stylesCreator,
|
||
|
name
|
||
|
}, props) {
|
||
|
if (stylesOptions.disableGeneration) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
let sheetManager = multiKeyStore.get(stylesOptions.sheetsManager, stylesCreator, theme);
|
||
|
|
||
|
if (!sheetManager) {
|
||
|
sheetManager = {
|
||
|
refs: 0,
|
||
|
staticSheet: null,
|
||
|
dynamicStyles: null
|
||
|
};
|
||
|
multiKeyStore.set(stylesOptions.sheetsManager, stylesCreator, theme, sheetManager);
|
||
|
}
|
||
|
|
||
|
const options = _extends({}, stylesCreator.options, stylesOptions, {
|
||
|
theme,
|
||
|
flip: typeof stylesOptions.flip === 'boolean' ? stylesOptions.flip : theme.direction === 'rtl'
|
||
|
});
|
||
|
|
||
|
options.generateId = options.serverGenerateClassName || options.generateClassName;
|
||
|
const sheetsRegistry = stylesOptions.sheetsRegistry;
|
||
|
|
||
|
if (sheetManager.refs === 0) {
|
||
|
let staticSheet;
|
||
|
|
||
|
if (stylesOptions.sheetsCache) {
|
||
|
staticSheet = multiKeyStore.get(stylesOptions.sheetsCache, stylesCreator, theme);
|
||
|
}
|
||
|
|
||
|
const styles = stylesCreator.create(theme, name);
|
||
|
|
||
|
if (!staticSheet) {
|
||
|
staticSheet = stylesOptions.jss.createStyleSheet(styles, _extends({
|
||
|
link: false
|
||
|
}, options));
|
||
|
staticSheet.attach();
|
||
|
|
||
|
if (stylesOptions.sheetsCache) {
|
||
|
multiKeyStore.set(stylesOptions.sheetsCache, stylesCreator, theme, staticSheet);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (sheetsRegistry) {
|
||
|
sheetsRegistry.add(staticSheet);
|
||
|
}
|
||
|
|
||
|
sheetManager.staticSheet = staticSheet;
|
||
|
sheetManager.dynamicStyles = getDynamicStyles(styles);
|
||
|
}
|
||
|
|
||
|
if (sheetManager.dynamicStyles) {
|
||
|
const dynamicSheet = stylesOptions.jss.createStyleSheet(sheetManager.dynamicStyles, _extends({
|
||
|
link: true
|
||
|
}, options));
|
||
|
dynamicSheet.update(props);
|
||
|
dynamicSheet.attach();
|
||
|
state.dynamicSheet = dynamicSheet;
|
||
|
state.classes = mergeClasses({
|
||
|
baseClasses: sheetManager.staticSheet.classes,
|
||
|
newClasses: dynamicSheet.classes
|
||
|
});
|
||
|
|
||
|
if (sheetsRegistry) {
|
||
|
sheetsRegistry.add(dynamicSheet);
|
||
|
}
|
||
|
} else {
|
||
|
state.classes = sheetManager.staticSheet.classes;
|
||
|
}
|
||
|
|
||
|
sheetManager.refs += 1;
|
||
|
}
|
||
|
|
||
|
function update({
|
||
|
state
|
||
|
}, props) {
|
||
|
if (state.dynamicSheet) {
|
||
|
state.dynamicSheet.update(props);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function detach({
|
||
|
state,
|
||
|
theme,
|
||
|
stylesOptions,
|
||
|
stylesCreator
|
||
|
}) {
|
||
|
if (stylesOptions.disableGeneration) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
const sheetManager = multiKeyStore.get(stylesOptions.sheetsManager, stylesCreator, theme);
|
||
|
sheetManager.refs -= 1;
|
||
|
const sheetsRegistry = stylesOptions.sheetsRegistry;
|
||
|
|
||
|
if (sheetManager.refs === 0) {
|
||
|
multiKeyStore.delete(stylesOptions.sheetsManager, stylesCreator, theme);
|
||
|
stylesOptions.jss.removeStyleSheet(sheetManager.staticSheet);
|
||
|
|
||
|
if (sheetsRegistry) {
|
||
|
sheetsRegistry.remove(sheetManager.staticSheet);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (state.dynamicSheet) {
|
||
|
stylesOptions.jss.removeStyleSheet(state.dynamicSheet);
|
||
|
|
||
|
if (sheetsRegistry) {
|
||
|
sheetsRegistry.remove(state.dynamicSheet);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function useSynchronousEffect(func, values) {
|
||
|
const key = React.useRef([]);
|
||
|
let output; // Store "generation" key. Just returns a new object every time
|
||
|
|
||
|
const currentKey = React.useMemo(() => ({}), values); // eslint-disable-line react-hooks/exhaustive-deps
|
||
|
// "the first render", or "memo dropped the value"
|
||
|
|
||
|
if (key.current !== currentKey) {
|
||
|
key.current = currentKey;
|
||
|
output = func();
|
||
|
}
|
||
|
|
||
|
React.useEffect(() => () => {
|
||
|
if (output) {
|
||
|
output();
|
||
|
}
|
||
|
}, [currentKey] // eslint-disable-line react-hooks/exhaustive-deps
|
||
|
);
|
||
|
}
|
||
|
|
||
|
export default function makeStyles(stylesOrCreator, options = {}) {
|
||
|
const {
|
||
|
// alias for classNamePrefix, if provided will listen to theme (required for theme.overrides)
|
||
|
name,
|
||
|
// Help with debuggability.
|
||
|
classNamePrefix: classNamePrefixOption,
|
||
|
Component,
|
||
|
defaultTheme = noopTheme
|
||
|
} = options,
|
||
|
stylesOptions2 = _objectWithoutPropertiesLoose(options, ["name", "classNamePrefix", "Component", "defaultTheme"]);
|
||
|
|
||
|
const stylesCreator = getStylesCreator(stylesOrCreator);
|
||
|
const classNamePrefix = name || classNamePrefixOption || 'makeStyles';
|
||
|
stylesCreator.options = {
|
||
|
index: increment(),
|
||
|
name,
|
||
|
meta: classNamePrefix,
|
||
|
classNamePrefix
|
||
|
};
|
||
|
|
||
|
const useStyles = (props = {}) => {
|
||
|
const theme = useTheme() || defaultTheme;
|
||
|
|
||
|
const stylesOptions = _extends({}, React.useContext(StylesContext), stylesOptions2);
|
||
|
|
||
|
const instance = React.useRef();
|
||
|
const shouldUpdate = React.useRef();
|
||
|
useSynchronousEffect(() => {
|
||
|
const current = {
|
||
|
name,
|
||
|
state: {},
|
||
|
stylesCreator,
|
||
|
stylesOptions,
|
||
|
theme
|
||
|
};
|
||
|
attach(current, props);
|
||
|
shouldUpdate.current = false;
|
||
|
instance.current = current;
|
||
|
return () => {
|
||
|
detach(current);
|
||
|
};
|
||
|
}, [theme, stylesCreator]);
|
||
|
React.useEffect(() => {
|
||
|
if (shouldUpdate.current) {
|
||
|
update(instance.current, props);
|
||
|
}
|
||
|
|
||
|
shouldUpdate.current = true;
|
||
|
});
|
||
|
const classes = getClasses(instance.current, props.classes, Component);
|
||
|
|
||
|
if (process.env.NODE_ENV !== 'production') {
|
||
|
// eslint-disable-next-line react-hooks/rules-of-hooks
|
||
|
React.useDebugValue(classes);
|
||
|
}
|
||
|
|
||
|
return classes;
|
||
|
};
|
||
|
|
||
|
return useStyles;
|
||
|
}
|