kopia lustrzana https://gitlab.com/soapbox-pub/soapbox
Merge branch 'next-sb-normalizer' into 'next'
Next: Normalize SoapboxConfig, small bug fixes See merge request soapbox-pub/soapbox-fe!1158virtualized-window
commit
56e51e265b
|
@ -2,6 +2,7 @@ import { Map as ImmutableMap, List as ImmutableList } from 'immutable';
|
|||
import { createSelector } from 'reselect';
|
||||
|
||||
import { getHost } from 'soapbox/actions/instance';
|
||||
import { normalizeSoapboxConfig } from 'soapbox/normalizers';
|
||||
import KVStore from 'soapbox/storage/kv_store';
|
||||
import { getFeatures } from 'soapbox/utils/features';
|
||||
|
||||
|
@ -33,79 +34,10 @@ const allowedEmojiRGI = ImmutableList([
|
|||
'😩',
|
||||
]);
|
||||
|
||||
const year = new Date().getFullYear();
|
||||
|
||||
export const makeDefaultConfig = features => {
|
||||
return ImmutableMap({
|
||||
logo: '',
|
||||
banner: '',
|
||||
brandColor: '', // Empty
|
||||
accentColor: '',
|
||||
colors: ImmutableMap({
|
||||
gray: ImmutableMap({
|
||||
50: '#f9fafb',
|
||||
100: '#f3f4f6',
|
||||
200: '#e5e7eb',
|
||||
300: '#d1d5db',
|
||||
400: '#9ca3af',
|
||||
500: '#6b7280',
|
||||
600: '#4b5563',
|
||||
700: '#374151',
|
||||
800: '#1f2937',
|
||||
900: '#111827',
|
||||
}),
|
||||
success: ImmutableMap({
|
||||
50: '#f0fdf4',
|
||||
100: '#dcfce7',
|
||||
200: '#bbf7d0',
|
||||
300: '#86efac',
|
||||
400: '#4ade80',
|
||||
500: '#22c55e',
|
||||
600: '#16a34a',
|
||||
700: '#15803d',
|
||||
800: '#166534',
|
||||
900: '#14532d',
|
||||
}),
|
||||
danger: ImmutableMap({
|
||||
50: '#fef2f2',
|
||||
100: '#fee2e2',
|
||||
200: '#fecaca',
|
||||
300: '#fca5a5',
|
||||
400: '#f87171',
|
||||
500: '#ef4444',
|
||||
600: '#dc2626',
|
||||
700: '#b91c1c',
|
||||
800: '#991b1b',
|
||||
900: '#7f1d1d',
|
||||
}),
|
||||
'gradient-purple': '#b8a3f9',
|
||||
'gradient-blue': '#9bd5ff',
|
||||
'sea-blue': '#2feecc',
|
||||
}),
|
||||
customCss: ImmutableList(),
|
||||
promoPanel: ImmutableMap({
|
||||
items: ImmutableList(),
|
||||
}),
|
||||
extensions: ImmutableMap(),
|
||||
defaultSettings: ImmutableMap(),
|
||||
copyright: `♥${year}. Copying is an act of love. Please copy and share.`,
|
||||
navlinks: ImmutableMap({
|
||||
homeFooter: ImmutableList(),
|
||||
}),
|
||||
allowedEmoji: features.emojiReactsRGI ? allowedEmojiRGI : allowedEmoji,
|
||||
verifiedIcon: '',
|
||||
verifiedCanEditName: false,
|
||||
displayFqn: Boolean(features.federating),
|
||||
cryptoAddresses: ImmutableList(),
|
||||
cryptoDonatePanel: ImmutableMap({
|
||||
limit: 1,
|
||||
}),
|
||||
aboutPages: ImmutableMap(),
|
||||
betaPages: ImmutableMap(),
|
||||
mobilePages: ImmutableMap(),
|
||||
authenticatedProfile: true,
|
||||
singleUserMode: false,
|
||||
singleUserModeProfile: '',
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -114,7 +46,7 @@ export const getSoapboxConfig = createSelector([
|
|||
state => getFeatures(state.get('instance')),
|
||||
], (soapbox, features) => {
|
||||
const defaultConfig = makeDefaultConfig(features);
|
||||
return soapbox.mergeDeepWith((o, n) => o || n, defaultConfig);
|
||||
return normalizeSoapboxConfig(soapbox).merge(defaultConfig);
|
||||
});
|
||||
|
||||
export function rememberSoapboxConfig(host) {
|
||||
|
|
|
@ -157,8 +157,6 @@ class Item extends React.PureComponent {
|
|||
</div>
|
||||
);
|
||||
} else if (attachment.get('type') === 'image') {
|
||||
const previewUrl = attachment.get('preview_url');
|
||||
|
||||
const originalUrl = attachment.get('url');
|
||||
const letterboxed = shouldLetterbox(attachment);
|
||||
|
||||
|
@ -169,7 +167,7 @@ class Item extends React.PureComponent {
|
|||
onClick={this.handleClick}
|
||||
target='_blank'
|
||||
>
|
||||
<StillImage src={previewUrl} alt={attachment.get('description')} />
|
||||
<StillImage src={originalUrl} alt={attachment.get('description')} />
|
||||
</a>
|
||||
);
|
||||
} else if (attachment.get('type') === 'gifv') {
|
||||
|
|
|
@ -8,7 +8,6 @@ import { fetchChats, launchChat } from 'soapbox/actions/chats';
|
|||
import AccountSearch from 'soapbox/components/account_search';
|
||||
import AudioToggle from 'soapbox/features/chats/components/audio_toggle';
|
||||
|
||||
import ColumnHeader from '../../components/column_header';
|
||||
import { Column } from '../../components/ui';
|
||||
|
||||
import ChatList from './components/chat_list';
|
||||
|
@ -47,11 +46,6 @@ class ChatIndex extends React.PureComponent {
|
|||
|
||||
return (
|
||||
<Column label={intl.formatMessage(messages.title)}>
|
||||
<ColumnHeader
|
||||
icon='comment'
|
||||
title={intl.formatMessage(messages.title)}
|
||||
/>
|
||||
|
||||
<div className='column__switch'>
|
||||
<AudioToggle />
|
||||
</div>
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
import { trimStart } from 'lodash';
|
||||
import React from 'react';
|
||||
|
||||
import { Stack } from 'soapbox/components/ui';
|
||||
|
@ -6,36 +5,22 @@ import { useSoapboxConfig } from 'soapbox/hooks';
|
|||
|
||||
import CryptoAddress from './crypto_address';
|
||||
|
||||
import type { Map as ImmutableMap, List as ImmutableList } from 'immutable';
|
||||
|
||||
type Address = ImmutableMap<string, any>;
|
||||
|
||||
// Address example:
|
||||
// {"ticker": "btc", "address": "bc1q9cx35adpm73aq2fw40ye6ts8hfxqzjr5unwg0n", "note": "This is our main address"}
|
||||
const normalizeAddress = (address: Address): Address => {
|
||||
return address.update('ticker', '', ticker => {
|
||||
return trimStart(ticker, '$').toLowerCase();
|
||||
});
|
||||
};
|
||||
|
||||
interface ISiteWallet {
|
||||
limit?: number,
|
||||
}
|
||||
|
||||
const SiteWallet: React.FC<ISiteWallet> = ({ limit }): JSX.Element => {
|
||||
const addresses: ImmutableList<Address> =
|
||||
useSoapboxConfig().get('cryptoAddresses').map(normalizeAddress);
|
||||
|
||||
const coinList = typeof limit === 'number' ? addresses.take(limit) : addresses;
|
||||
const { cryptoAddresses } = useSoapboxConfig();
|
||||
const addresses = typeof limit === 'number' ? cryptoAddresses.take(limit) : cryptoAddresses;
|
||||
|
||||
return (
|
||||
<Stack space={4}>
|
||||
{coinList.map(coin => (
|
||||
{addresses.map(address => (
|
||||
<CryptoAddress
|
||||
key={coin.get('ticker')}
|
||||
address={coin.get('address')}
|
||||
ticker={coin.get('ticker')}
|
||||
note={coin.get('note')}
|
||||
key={address.ticker}
|
||||
address={address.address}
|
||||
ticker={address.ticker}
|
||||
note={address.note}
|
||||
/>
|
||||
))}
|
||||
</Stack>
|
||||
|
|
|
@ -12,8 +12,8 @@ import { connect } from 'react-redux';
|
|||
import { updateConfig } from 'soapbox/actions/admin';
|
||||
import { uploadMedia } from 'soapbox/actions/media';
|
||||
import snackbar from 'soapbox/actions/snackbar';
|
||||
import { makeDefaultConfig } from 'soapbox/actions/soapbox';
|
||||
import Icon from 'soapbox/components/icon';
|
||||
import { Column } from 'soapbox/components/ui';
|
||||
import {
|
||||
SimpleForm,
|
||||
FieldsGroup,
|
||||
|
@ -26,10 +26,9 @@ import {
|
|||
} from 'soapbox/features/forms';
|
||||
import ThemeToggle from 'soapbox/features/ui/components/theme_toggle';
|
||||
import { isMobile } from 'soapbox/is_mobile';
|
||||
import { getFeatures } from 'soapbox/utils/features';
|
||||
import { normalizeSoapboxConfig } from 'soapbox/normalizers';
|
||||
|
||||
import Accordion from '../ui/components/accordion';
|
||||
import Column from '../ui/components/column';
|
||||
|
||||
import IconPickerDropdown from './components/icon_picker_dropdown';
|
||||
import SitePreview from './components/site_preview';
|
||||
|
@ -71,11 +70,8 @@ const templates = {
|
|||
};
|
||||
|
||||
const mapStateToProps = state => {
|
||||
const instance = state.get('instance');
|
||||
|
||||
return {
|
||||
soapbox: state.get('soapbox'),
|
||||
features: getFeatures(instance),
|
||||
initialData: state.soapbox,
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -84,37 +80,36 @@ export default @connect(mapStateToProps)
|
|||
class SoapboxConfig extends ImmutablePureComponent {
|
||||
|
||||
static propTypes = {
|
||||
soapbox: ImmutablePropTypes.map.isRequired,
|
||||
features: PropTypes.object.isRequired,
|
||||
initialData: ImmutablePropTypes.map.isRequired,
|
||||
dispatch: PropTypes.func.isRequired,
|
||||
intl: PropTypes.object.isRequired,
|
||||
};
|
||||
|
||||
state = {
|
||||
isLoading: false,
|
||||
soapbox: this.props.soapbox,
|
||||
data: this.props.initialData,
|
||||
jsonEditorExpanded: false,
|
||||
rawJSON: JSON.stringify(this.props.soapbox, null, 2),
|
||||
jsonValid: true,
|
||||
}
|
||||
|
||||
setConfig = (path, value) => {
|
||||
const { soapbox } = this.state;
|
||||
const config = soapbox.setIn(path, value);
|
||||
this.setState({ soapbox: config, jsonValid: true });
|
||||
const { data } = this.state;
|
||||
const newData = data.setIn(path, value);
|
||||
this.setState({ data: newData, jsonValid: true });
|
||||
};
|
||||
|
||||
putConfig = config => {
|
||||
this.setState({ soapbox: config, jsonValid: true });
|
||||
putConfig = data => {
|
||||
this.setState({ data, jsonValid: true });
|
||||
};
|
||||
|
||||
getParams = () => {
|
||||
const { soapbox } = this.state;
|
||||
const { data } = this.state;
|
||||
return [{
|
||||
group: ':pleroma',
|
||||
key: ':frontend_configurations',
|
||||
value: [{
|
||||
tuple: [':soapbox_fe', soapbox.toJS()],
|
||||
tuple: [':soapbox_fe', data.toJS()],
|
||||
}],
|
||||
}];
|
||||
}
|
||||
|
@ -158,8 +153,8 @@ class SoapboxConfig extends ImmutablePureComponent {
|
|||
|
||||
handleDeleteItem = path => {
|
||||
return e => {
|
||||
const soapbox = this.state.soapbox.deleteIn(path);
|
||||
this.setState({ soapbox });
|
||||
const data = this.state.data.deleteIn(path);
|
||||
this.setState({ data });
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -195,20 +190,18 @@ class SoapboxConfig extends ImmutablePureComponent {
|
|||
}
|
||||
|
||||
getSoapboxConfig = () => {
|
||||
const { features } = this.props;
|
||||
const { soapbox } = this.state;
|
||||
return makeDefaultConfig(features).mergeDeep(soapbox);
|
||||
return normalizeSoapboxConfig(this.state.data);
|
||||
}
|
||||
|
||||
toggleJSONEditor = (value) => this.setState({ jsonEditorExpanded: value });
|
||||
|
||||
componentDidUpdate(prevProps, prevState) {
|
||||
if (prevProps.soapbox !== this.props.soapbox) {
|
||||
this.putConfig(this.props.soapbox);
|
||||
if (prevProps.initialData !== this.props.initialData) {
|
||||
this.putConfig(this.props.initialData);
|
||||
}
|
||||
|
||||
if (prevState.soapbox !== this.state.soapbox) {
|
||||
this.setState({ rawJSON: JSON.stringify(this.state.soapbox, null, 2) });
|
||||
if (prevState.data !== this.state.data) {
|
||||
this.setState({ rawJSON: JSON.stringify(this.state.data, null, 2) });
|
||||
}
|
||||
|
||||
if (prevState.rawJSON !== this.state.rawJSON) {
|
||||
|
@ -226,7 +219,7 @@ class SoapboxConfig extends ImmutablePureComponent {
|
|||
const soapbox = this.getSoapboxConfig();
|
||||
|
||||
return (
|
||||
<Column icon='cog' heading={intl.formatMessage(messages.heading)}>
|
||||
<Column label={intl.formatMessage(messages.heading)}>
|
||||
<SimpleForm onSubmit={this.handleSubmit}>
|
||||
<fieldset disabled={this.state.isLoading}>
|
||||
<SitePreview soapbox={soapbox} />
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
import { getSoapboxConfig } from 'soapbox/actions/soapbox';
|
||||
import { useAppSelector } from 'soapbox/hooks';
|
||||
|
||||
import type { Map as ImmutableMap } from 'immutable';
|
||||
import type { SoapboxConfig } from 'soapbox/types/soapbox';
|
||||
|
||||
/** Get the Soapbox config from the store */
|
||||
export const useSoapboxConfig = (): ImmutableMap<string, any> => {
|
||||
export const useSoapboxConfig = (): SoapboxConfig => {
|
||||
return useAppSelector((state) => getSoapboxConfig(state));
|
||||
};
|
||||
|
|
|
@ -7,3 +7,5 @@ export { MentionRecord, normalizeMention } from './mention';
|
|||
export { NotificationRecord, normalizeNotification } from './notification';
|
||||
export { PollRecord, PollOptionRecord, normalizePoll } from './poll';
|
||||
export { StatusRecord, normalizeStatus } from './status';
|
||||
|
||||
export { SoapboxConfigRecord, normalizeSoapboxConfig } from './soapbox/soapbox_config';
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
import { Record as ImmutableRecord } from 'immutable';
|
||||
|
||||
import { normalizeSoapboxConfig } from '../soapbox_config';
|
||||
|
||||
describe('normalizeSoapboxConfig()', () => {
|
||||
it('adds base fields', () => {
|
||||
const result = normalizeSoapboxConfig({});
|
||||
expect(result.brandColor).toBe('');
|
||||
expect(ImmutableRecord.isRecord(result)).toBe(true);
|
||||
});
|
||||
|
||||
it('normalizes cryptoAddresses', () => {
|
||||
const soapboxConfig = {
|
||||
cryptoAddresses: [
|
||||
{ ticker: '$BTC', address: 'bc1q9cx35adpm73aq2fw40ye6ts8hfxqzjr5unwg0n' },
|
||||
],
|
||||
};
|
||||
|
||||
const expected = {
|
||||
cryptoAddresses: [
|
||||
{ ticker: 'btc', address: 'bc1q9cx35adpm73aq2fw40ye6ts8hfxqzjr5unwg0n', note: '' },
|
||||
],
|
||||
};
|
||||
|
||||
const result = normalizeSoapboxConfig(soapboxConfig);
|
||||
expect(result.cryptoAddresses.size).toBe(1);
|
||||
expect(ImmutableRecord.isRecord(result.cryptoAddresses.get(0))).toBe(true);
|
||||
expect(result.toJS()).toMatchObject(expected);
|
||||
});
|
||||
});
|
|
@ -0,0 +1,171 @@
|
|||
import {
|
||||
Map as ImmutableMap,
|
||||
List as ImmutableList,
|
||||
Record as ImmutableRecord,
|
||||
fromJS,
|
||||
} from 'immutable';
|
||||
import { trimStart } from 'lodash';
|
||||
|
||||
import { toTailwind } from 'soapbox/utils/tailwind';
|
||||
import { generateAccent } from 'soapbox/utils/theme';
|
||||
|
||||
import type {
|
||||
PromoPanelItem,
|
||||
FooterItem,
|
||||
CryptoAddress,
|
||||
} from 'soapbox/types/soapbox';
|
||||
|
||||
const DEFAULT_COLORS = ImmutableMap<string, any>({
|
||||
gray: ImmutableMap({
|
||||
50: '#f9fafb',
|
||||
100: '#f3f4f6',
|
||||
200: '#e5e7eb',
|
||||
300: '#d1d5db',
|
||||
400: '#9ca3af',
|
||||
500: '#6b7280',
|
||||
600: '#4b5563',
|
||||
700: '#374151',
|
||||
800: '#1f2937',
|
||||
900: '#111827',
|
||||
}),
|
||||
success: ImmutableMap({
|
||||
50: '#f0fdf4',
|
||||
100: '#dcfce7',
|
||||
200: '#bbf7d0',
|
||||
300: '#86efac',
|
||||
400: '#4ade80',
|
||||
500: '#22c55e',
|
||||
600: '#16a34a',
|
||||
700: '#15803d',
|
||||
800: '#166534',
|
||||
900: '#14532d',
|
||||
}),
|
||||
danger: ImmutableMap({
|
||||
50: '#fef2f2',
|
||||
100: '#fee2e2',
|
||||
200: '#fecaca',
|
||||
300: '#fca5a5',
|
||||
400: '#f87171',
|
||||
500: '#ef4444',
|
||||
600: '#dc2626',
|
||||
700: '#b91c1c',
|
||||
800: '#991b1b',
|
||||
900: '#7f1d1d',
|
||||
}),
|
||||
'gradient-purple': '#b8a3f9',
|
||||
'gradient-blue': '#9bd5ff',
|
||||
'sea-blue': '#2feecc',
|
||||
});
|
||||
|
||||
export const PromoPanelItemRecord = ImmutableRecord({
|
||||
icon: '',
|
||||
text: '',
|
||||
url: '',
|
||||
});
|
||||
|
||||
export const FooterItemRecord = ImmutableRecord({
|
||||
title: '',
|
||||
url: '',
|
||||
});
|
||||
|
||||
export const CryptoAddressRecord = ImmutableRecord({
|
||||
address: '',
|
||||
note: '',
|
||||
ticker: '',
|
||||
});
|
||||
|
||||
export const SoapboxConfigRecord = ImmutableRecord({
|
||||
logo: '',
|
||||
banner: '',
|
||||
brandColor: '', // Empty
|
||||
accentColor: '',
|
||||
colors: ImmutableMap(),
|
||||
copyright: `♥${new Date().getFullYear()}. Copying is an act of love. Please copy and share.`,
|
||||
customCss: ImmutableList<string>(),
|
||||
defaultSettings: ImmutableMap(),
|
||||
extensions: ImmutableMap(),
|
||||
greentext: false,
|
||||
promoPanel: ImmutableMap({
|
||||
items: ImmutableList<PromoPanelItem>(),
|
||||
}),
|
||||
navlinks: ImmutableMap({
|
||||
homeFooter: ImmutableList<FooterItem>(),
|
||||
}),
|
||||
allowedEmoji: ImmutableList<string>([
|
||||
'👍',
|
||||
'❤️',
|
||||
'😆',
|
||||
'😮',
|
||||
'😢',
|
||||
'😩',
|
||||
]),
|
||||
verifiedIcon: '',
|
||||
verifiedCanEditName: false,
|
||||
displayFqn: true,
|
||||
cryptoAddresses: ImmutableList<CryptoAddress>(),
|
||||
cryptoDonatePanel: ImmutableMap({
|
||||
limit: 1,
|
||||
}),
|
||||
aboutPages: ImmutableMap(),
|
||||
betaPages: ImmutableMap(),
|
||||
mobilePages: ImmutableMap(),
|
||||
authenticatedProfile: true,
|
||||
singleUserMode: false,
|
||||
singleUserModeProfile: '',
|
||||
}, 'SoapboxConfig');
|
||||
|
||||
type SoapboxConfigMap = ImmutableMap<string, any>;
|
||||
|
||||
const normalizeCryptoAddress = (address: unknown): CryptoAddress => {
|
||||
return CryptoAddressRecord(ImmutableMap(fromJS(address))).update('ticker', ticker => {
|
||||
return trimStart(ticker, '$').toLowerCase();
|
||||
});
|
||||
};
|
||||
|
||||
const normalizeCryptoAddresses = (soapboxConfig: SoapboxConfigMap): SoapboxConfigMap => {
|
||||
const addresses = ImmutableList(soapboxConfig.get('cryptoAddresses'));
|
||||
return soapboxConfig.set('cryptoAddresses', addresses.map(normalizeCryptoAddress));
|
||||
};
|
||||
|
||||
const normalizeBrandColor = (soapboxConfig: SoapboxConfigMap): SoapboxConfigMap => {
|
||||
const brandColor = soapboxConfig.get('brandColor') || soapboxConfig.getIn(['colors', 'primary', '500']) || '';
|
||||
return soapboxConfig.set('brandColor', brandColor);
|
||||
};
|
||||
|
||||
const normalizeAccentColor = (soapboxConfig: SoapboxConfigMap): SoapboxConfigMap => {
|
||||
const brandColor = soapboxConfig.get('brandColor');
|
||||
|
||||
const accentColor = soapboxConfig.get('accentColor')
|
||||
|| soapboxConfig.getIn(['colors', 'accent', '500'])
|
||||
|| (brandColor ? generateAccent(brandColor) : '');
|
||||
|
||||
return soapboxConfig.set('accentColor', accentColor);
|
||||
};
|
||||
|
||||
const normalizeColors = (soapboxConfig: SoapboxConfigMap): SoapboxConfigMap => {
|
||||
const colors = DEFAULT_COLORS.mergeDeep(soapboxConfig.get('colors'));
|
||||
return toTailwind(soapboxConfig.set('colors', colors));
|
||||
};
|
||||
|
||||
const maybeAddMissingColors = (soapboxConfig: SoapboxConfigMap): SoapboxConfigMap => {
|
||||
const colors = soapboxConfig.get('colors');
|
||||
|
||||
const missing = {
|
||||
'bg-shape-1': colors.getIn(['accent', '50']),
|
||||
'bg-shape-2': colors.getIn(['primary', '500']),
|
||||
};
|
||||
|
||||
return soapboxConfig.set('colors', colors.mergeDeep(missing));
|
||||
};
|
||||
|
||||
export const normalizeSoapboxConfig = (soapboxConfig: Record<string, any>) => {
|
||||
return SoapboxConfigRecord(
|
||||
ImmutableMap(fromJS(soapboxConfig)).withMutations(soapboxConfig => {
|
||||
normalizeBrandColor(soapboxConfig);
|
||||
normalizeAccentColor(soapboxConfig);
|
||||
normalizeColors(soapboxConfig);
|
||||
maybeAddMissingColors(soapboxConfig);
|
||||
normalizeCryptoAddresses(soapboxConfig);
|
||||
}),
|
||||
);
|
||||
};
|
|
@ -0,0 +1,18 @@
|
|||
import {
|
||||
PromoPanelItemRecord,
|
||||
FooterItemRecord,
|
||||
CryptoAddressRecord,
|
||||
SoapboxConfigRecord,
|
||||
} from 'soapbox/normalizers/soapbox/soapbox_config';
|
||||
|
||||
type PromoPanelItem = ReturnType<typeof PromoPanelItemRecord>;
|
||||
type FooterItem = ReturnType<typeof FooterItemRecord>;
|
||||
type CryptoAddress = ReturnType<typeof CryptoAddressRecord>;
|
||||
type SoapboxConfig = ReturnType<typeof SoapboxConfigRecord>;
|
||||
|
||||
export {
|
||||
PromoPanelItem,
|
||||
FooterItem,
|
||||
CryptoAddress,
|
||||
SoapboxConfig,
|
||||
};
|
|
@ -9,8 +9,8 @@ describe('tintify()', () => {
|
|||
expect(result).toEqual({
|
||||
'100': '#e6f3fb',
|
||||
'200': '#c0e0f5',
|
||||
'300': '#9bcdef',
|
||||
'400': '#4fa8e4',
|
||||
'300': '#4fa8e4',
|
||||
'400': '#369be0',
|
||||
'50': '#f2f9fd',
|
||||
'500': '#0482d8',
|
||||
'600': '#0475c2',
|
||||
|
|
|
@ -20,8 +20,8 @@ describe('toTailwind()', () => {
|
|||
50: '#f2f9fd',
|
||||
100: '#e6f3fb',
|
||||
200: '#c0e0f5',
|
||||
300: '#9bcdef',
|
||||
400: '#4fa8e4',
|
||||
300: '#4fa8e4',
|
||||
400: '#369be0',
|
||||
500: '#0482d8',
|
||||
600: '#0475c2',
|
||||
700: '#0362a2',
|
||||
|
@ -53,7 +53,7 @@ describe('toTailwind()', () => {
|
|||
100: '#e6f3fb',
|
||||
200: '#c0e0f5',
|
||||
300: '#ff0000', // <--
|
||||
400: '#4fa8e4',
|
||||
400: '#369be0',
|
||||
500: '#0482d8',
|
||||
600: '#0475c2',
|
||||
700: '#0362a2',
|
||||
|
@ -77,8 +77,8 @@ describe('fromLegacyColors()', () => {
|
|||
50: '#f2f9fd',
|
||||
100: '#e6f3fb',
|
||||
200: '#c0e0f5',
|
||||
300: '#9bcdef',
|
||||
400: '#4fa8e4',
|
||||
300: '#4fa8e4',
|
||||
400: '#369be0',
|
||||
500: '#0482d8',
|
||||
600: '#0475c2',
|
||||
700: '#0362a2',
|
||||
|
@ -90,8 +90,8 @@ describe('fromLegacyColors()', () => {
|
|||
50: '#f3fbfd',
|
||||
100: '#e7f7fa',
|
||||
200: '#c3ecf4',
|
||||
300: '#9fe1ed',
|
||||
400: '#58cadf',
|
||||
300: '#58cadf',
|
||||
400: '#40c2da',
|
||||
500: '#10b3d1',
|
||||
600: '#0ea1bc',
|
||||
700: '#0c869d',
|
||||
|
@ -115,8 +115,8 @@ describe('fromLegacyColors()', () => {
|
|||
50: '#f2f9fd',
|
||||
100: '#e6f3fb',
|
||||
200: '#c0e0f5',
|
||||
300: '#9bcdef',
|
||||
400: '#4fa8e4',
|
||||
300: '#4fa8e4',
|
||||
400: '#369be0',
|
||||
500: '#0482d8',
|
||||
600: '#0475c2',
|
||||
700: '#0362a2',
|
||||
|
@ -127,8 +127,8 @@ describe('fromLegacyColors()', () => {
|
|||
50: '#f4fdf3',
|
||||
100: '#eafae7',
|
||||
200: '#caf4c3',
|
||||
300: '#aaed9f',
|
||||
400: '#6bdf58',
|
||||
300: '#6bdf58',
|
||||
400: '#55da40',
|
||||
500: '#2bd110',
|
||||
600: '#27bc0e',
|
||||
700: '#209d0c',
|
||||
|
@ -151,8 +151,8 @@ describe('expandPalette()', () => {
|
|||
50: '#f2f9fd',
|
||||
100: '#e6f3fb',
|
||||
200: '#c0e0f5',
|
||||
300: '#9bcdef',
|
||||
400: '#4fa8e4',
|
||||
300: '#4fa8e4',
|
||||
400: '#369be0',
|
||||
500: '#0482d8',
|
||||
600: '#0475c2',
|
||||
700: '#0362a2',
|
||||
|
@ -171,8 +171,8 @@ describe('expandPalette()', () => {
|
|||
50: '#f2f9fd',
|
||||
100: '#e6f3fb',
|
||||
200: '#c0e0f5',
|
||||
300: '#9bcdef',
|
||||
400: '#4fa8e4',
|
||||
300: '#4fa8e4',
|
||||
400: '#369be0',
|
||||
500: '#0482d8',
|
||||
600: '#0475c2',
|
||||
700: '#0362a2',
|
||||
|
@ -187,8 +187,8 @@ describe('expandPalette()', () => {
|
|||
50: '#f2f9fd',
|
||||
100: '#e6f3fb',
|
||||
200: '#c0e0f5',
|
||||
300: '#9bcdef',
|
||||
400: '#4fa8e4',
|
||||
300: '#4fa8e4',
|
||||
400: '#369be0',
|
||||
500: '#0482d8',
|
||||
600: '#0475c2',
|
||||
700: '#0362a2',
|
||||
|
@ -199,8 +199,8 @@ describe('expandPalette()', () => {
|
|||
50: '#f4fdf3',
|
||||
100: '#eafae7',
|
||||
200: '#caf4c3',
|
||||
300: '#aaed9f',
|
||||
400: '#6bdf58',
|
||||
300: '#6bdf58',
|
||||
400: '#55da40',
|
||||
500: '#2bd110',
|
||||
600: '#27bc0e',
|
||||
700: '#209d0c',
|
||||
|
|
|
@ -103,8 +103,8 @@ export default function(baseColor: string): TailwindColorObject {
|
|||
50: 0.95,
|
||||
100: 0.9,
|
||||
200: 0.75,
|
||||
300: 0.6,
|
||||
400: 0.3,
|
||||
300: 0.3,
|
||||
400: 0.2,
|
||||
600: 0.9,
|
||||
700: 0.75,
|
||||
800: 0.6,
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
import { hexToRgb } from './colors';
|
||||
import { toTailwind } from './tailwind';
|
||||
|
||||
import type { Map as ImmutableMap } from 'immutable';
|
||||
import type { Rgb, Hsl, TailwindColorPalette, TailwindColorObject } from 'soapbox/types/colors';
|
||||
import type { SoapboxConfig } from 'soapbox/types/soapbox';
|
||||
|
||||
// Taken from chromatism.js
|
||||
// https://github.com/graypegg/chromatism/blob/master/src/conversions/rgb.js
|
||||
|
@ -69,16 +68,19 @@ export const generateAccent = (brandColor: string): string | null => {
|
|||
return hslToHex({ h: h - 15, s: 86, l: 44 });
|
||||
};
|
||||
|
||||
const parseShades = (obj: Record<string, any>, color: string, shades: Record<string, any>) => {
|
||||
const parseShades = (obj: Record<string, any>, color: string, shades: Record<string, any>): void => {
|
||||
if (!shades) return;
|
||||
|
||||
if (typeof shades === 'string') {
|
||||
const rgb = hexToRgb(shades);
|
||||
if (!rgb) return obj;
|
||||
if (!rgb) return;
|
||||
|
||||
const { r, g, b } = rgb;
|
||||
return obj[`--color-${color}`] = `${r} ${g} ${b}`;
|
||||
obj[`--color-${color}`] = `${r} ${g} ${b}`;
|
||||
return;
|
||||
}
|
||||
|
||||
return Object.keys(shades).forEach(shade => {
|
||||
Object.keys(shades).forEach(shade => {
|
||||
const rgb = hexToRgb(shades[shade]);
|
||||
if (!rgb) return;
|
||||
|
||||
|
@ -102,6 +104,6 @@ export const colorsToCss = (colors: TailwindColorPalette): string => {
|
|||
}, '');
|
||||
};
|
||||
|
||||
export const generateThemeCss = (soapboxConfig: ImmutableMap<string, any>): string => {
|
||||
return colorsToCss(toTailwind(soapboxConfig).get('colors').toJS() as TailwindColorPalette);
|
||||
export const generateThemeCss = (soapboxConfig: SoapboxConfig): string => {
|
||||
return colorsToCss(soapboxConfig.colors.toJS() as TailwindColorPalette);
|
||||
};
|
||||
|
|
Ładowanie…
Reference in New Issue