@selfcommunity/react-core
Version:
React Core Components useful for integrating UI Community components (react-ui).
93 lines (91 loc) • 3.56 kB
JavaScript
import { jsx as _jsx } from "react/jsx-runtime";
import { createContext, useContext, useMemo, useState } from 'react';
import { useSCContext } from '../SCContextProvider';
import { loadLocaleData } from '../../../utils/locale';
import { DEFAULT_LANGUAGE_UI } from '../../../constants/Locale';
import { IntlProvider } from 'react-intl';
import { Logger } from '@selfcommunity/utils';
import { SCOPE_SC_CORE } from '../../../constants/Errors';
import { useDeepCompareEffectNoCheck } from 'use-deep-compare-effect';
/**
* Creates Global Context
*
:::tip Context can be consumed in one of the following ways:
```jsx
1. <SCLocaleContext.Consumer>{(locale,) => (...)}</SCLocaleContext.Consumer>
```
```jsx
2. const scLocaleContext: SCLocaleContextType = useContext(SCLocaleContext);
```
```jsx
3. const scLocaleContext: SCLocaleContextType = useSCLocale();
````
:::
*/
export const SCLocaleContext = createContext({});
/**
* #### Description:
* This component makes the `intl` available down the React tree.
* @param children
* @return
* ```jsx
* <SCLocaleContext.Provider value={{locale, messages, selectLocale}}>
* ```
*/
export default function SCLocaleProvider({ children = null }) {
var _a;
const scContext = useSCContext();
const initialLocale = ((_a = scContext.settings.locale) === null || _a === void 0 ? void 0 : _a.default) ? scContext.settings.locale.default : DEFAULT_LANGUAGE_UI;
const initial = loadLocaleData(initialLocale, scContext.settings);
const [locale, setLocale] = useState(initial.locale);
const [messages, setMessages] = useState(initial.messages);
/**
* Update current locale state
* @param _intl
*/
const updateLocale = (_intl) => {
setLocale(_intl.locale);
setMessages(_intl.messages);
};
/**
* Select locale loading data
*/
const selectLocale = useMemo(() => (l) => {
const { messages, locale } = loadLocaleData(l, scContext.settings);
updateLocale({ messages, locale });
}, [locale]);
/**
* Update locale and messages if initial conf changes
*/
useDeepCompareEffectNoCheck(() => {
var _a;
selectLocale(((_a = scContext.settings.locale) === null || _a === void 0 ? void 0 : _a.default) ? scContext.settings.locale.default : DEFAULT_LANGUAGE_UI);
}, [scContext.settings.locale]);
/**
* handleIntlError
* @param error
*/
const handleIntlError = (error) => {
if (error.code === 'MISSING_TRANSLATION') {
Logger.warn(SCOPE_SC_CORE, `Missing translation: ${error.message}`);
return;
}
throw error;
};
return (_jsx(SCLocaleContext.Provider, Object.assign({ value: { locale, messages, selectLocale } }, { children: _jsx(IntlProvider, Object.assign({ locale: locale, messages: messages, onError: handleIntlError }, { children: children }), locale) })));
}
/**
* Export hoc to inject the base theme to components
* @param Component
*/
export const withSCLocale = (Component) => (props) => {
const scLocaleContext = useContext(SCLocaleContext);
return (_jsx(IntlProvider, Object.assign({ locale: scLocaleContext.locale, messages: scLocaleContext.messages }, { children: _jsx(Component, Object.assign({ setLanguage: scLocaleContext.selectLocale }, props)) })));
};
/**
* Let's only export the `useSCLocale` hook instead of the context.
* We only want to use the hook directly and never the context component.
*/
export function useSCLocale() {
return useContext(SCLocaleContext);
}