Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions docs/scripts/index.js

Large diffs are not rendered by default.

35 changes: 26 additions & 9 deletions playground/src/components/AppProvider/AppProvider.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React, { PropsWithChildren, createContext, useContext, useState, useEffect } from 'react';
import { PluginOptions, Mode, Source, Autorename } from 'postcss-rtlcss';
import { PluginOptions, Mode, Source, Autorename } from 'postcss-rtlcss/options';
import { useApi } from '@hooks/useApi';
import { breakpointSizes } from '@utilities/styles';

export interface WindowSizes {
Expand All @@ -11,9 +12,16 @@ export interface WindowSizes {
}

export interface AppProviderContext {
canShare: boolean;
ready: boolean;
token: string;
fetchCode: string;
code: string;
optionsOpen: boolean;
options: PluginOptions;
windowSizes: WindowSizes;
setCode: (code: string) => void;
share: (code: string) => void;
setOptionsOpen: React.Dispatch<React.SetStateAction<boolean>>;
changeOptionsMode: (mode: Mode) => void;
changeOptionsSource: (source: Source) => void;
Expand Down Expand Up @@ -54,17 +62,11 @@ export const AppContext = createContext<AppProviderContext>({} as AppProviderCon
export const AppProvider = (props: PropsWithChildren<{}>): JSX.Element => {

let delay: number;
const [ code, setCode ] = useState<string>(null);
const [ options, setOptions ] = useState<PluginOptions>(defaultOptions);
const [ sizes, setSizes ] = useState<WindowSizes>(windowSizes);
const [ optionsOpen, setOptionsOpen ] = useState<boolean>(false);

const resize = (): void => {
if (delay) window.clearTimeout(delay);
delay = window.setTimeout((): void => {
const windowSizes = getWindowSizes();
setSizes(windowSizes);
}, 100);
};
const { canShare, ready, token, fetchCode, share } = useApi();

useEffect(() => {
window.removeEventListener('resize', resize);
Expand All @@ -74,6 +76,14 @@ export const AppProvider = (props: PropsWithChildren<{}>): JSX.Element => {
};
}, []);

const resize = (): void => {
if (delay) window.clearTimeout(delay);
delay = window.setTimeout((): void => {
const windowSizes = getWindowSizes();
setSizes(windowSizes);
}, 100);
};

const changeOptionsMode = (mode: Mode): void => setOptions({ ...options, mode });
const changeOptionsSource = (source: Source): void => setOptions({ ...options, source });
const changeOptionsSafeBothPrefix = (safeBothPrefix: boolean): void => setOptions({...options, safeBothPrefix});
Expand All @@ -84,8 +94,15 @@ export const AppProvider = (props: PropsWithChildren<{}>): JSX.Element => {
const changeOptionsGreedy = (greedy: boolean): void => setOptions({ ...options, greedy });

const providerData = {
canShare,
ready,
token,
fetchCode,
code,
options,
optionsOpen,
setCode,
share,
setOptionsOpen,
changeOptionsMode,
changeOptionsSource,
Expand Down
23 changes: 19 additions & 4 deletions playground/src/components/Header/Header.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,27 @@
import React from 'react';
import React, { useCallback } from 'react';
import { Share } from '@icons/Share';
import { useAppContext } from '@components/AppProvider';
import { stylesheet } from './stylesheet';

export const Header = (): JSX.Element => {
const { canShare, token, share, code } = useAppContext();
const shareCallback = useCallback(() => {
share(code);
}, [share, code]);
return (
<header css={stylesheet.wrapper}>
<span>{ '{' }&nbsp;</span>
<h1 css={stylesheet.title}>PostCSS-RTLCSS online</h1>
<span>&nbsp;{ '}' }</span>
<div css={stylesheet.logo}>
<span>{ '{' }&nbsp;</span>
<h1 css={stylesheet.title}>PostCSS-RTLCSS online</h1>
<span>&nbsp;{ '}' }</span>
</div>
<div css={stylesheet.icons}>
{canShare && token && (
<button css={stylesheet.button} onClick={shareCallback}>
<Share size={20} />
</button>
)}
</div>
</header>
);
};
16 changes: 16 additions & 0 deletions playground/src/components/Header/stylesheet.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ export const stylesheet = parse({
wrapper: {
alignItems: 'center',
backgroundColor: COLORS.gray_darkest,
display: 'flex',
flexGrow: 0,
flexShrink: 0,
height: 50,
Expand All @@ -16,6 +17,21 @@ export const stylesheet = parse({
fontWeight: 400
}
},
logo: {
flexGrow: 0,
flexShrink: 0
},
icons: {
alignItems: 'center',
display: 'flex',
flexGrow: 1,
justifyContent: 'flex-end'
},
button: {
background: 'transparent',
border: 'none',
cursor: 'pointer'
},
title: {
color: COLORS.gray_light,
display: 'inline',
Expand Down
13 changes: 9 additions & 4 deletions playground/src/components/Playground/Playground.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ const flipLines = (lines: string, options: PluginOptions = {}): LazyResult => {

export const Playground = (): JSX.Element => {

const { options, windowSizes } = useAppContext();
const { ready, fetchCode, setCode, options, windowSizes } = useAppContext();
const { isSmallScreen, panelHeight, panelWidth } = windowSizes;
const [ lines, setLines ] = useState<string>(cssLines);
const [ linesFlipped, setLinesFlipped ] = useState<string>('');
Expand All @@ -23,10 +23,11 @@ export const Playground = (): JSX.Element => {
setLinesFlipped(result.css);
}).catch((error): void => {
setLinesFlipped(`/* ${error.name}: ${error.message} */`);
});
});
setCode(lines);
}, [ lines, options ]);

const onChangeCode = (code: string): void => {
const onChangeCode = (code: string): void => {
setLines(code);
};

Expand All @@ -40,7 +41,11 @@ export const Playground = (): JSX.Element => {
<div css={stylesheet.wrapper}>
<CSSPanel
title="css input"
lines={cssLines}
lines={
ready
? fetchCode || cssLines
: ''
}
readOnly={isSmallScreen}
onChange={onChangeCode}
{ ...comonProps }
Expand Down
143 changes: 143 additions & 0 deletions playground/src/hooks/useApi.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
import { env } from 'process';
import { useState, useEffect, useCallback, useMemo } from 'react';

interface UseApiProps {
token: string;
fetchCode: string;
ready: boolean;
canShare: boolean;
share: (code: string) => void;
}

interface FetchOptions {
method: 'POST' | 'GET';
headers: Record<string, string>;
body?: string;
}

interface FetchResponse {
token?: string;
success?: boolean;
done?: boolean;
id?: string;
code?: string;
}

const endpoint = 'https://xprimiendo.com/snippet';

const fetchApi = (data?: Record<string, string>): Promise<FetchResponse> => {

const options: FetchOptions = {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
};

if (data) {
const body = Object.entries(data)
.map(([key, value]): string => `${key}=${encodeURIComponent(value)}`)
.join('&');
options.body = body;
}

return new Promise((resolve, reject) => {
fetch(endpoint, options)
.then(result => {
if (result.ok) {
result
.json()
.then(data => resolve(data));
} else {
result
.text()
.then(data => reject(data));
}
})
.catch(() => {
reject(null);
});
});
};

export const useApi = (): UseApiProps => {

const [ id, setId ] = useState<string>(null);
const [ token, setToken ] = useState<string>(null);
const [ fetchCode, setFetchCode ] = useState<string>(null);
const [ ready, setReady ] = useState(false);

const canShare = useMemo(() => {
const UNDEFINED_TYPE = 'undefined';
const FUNCTION_TYPE = 'function';
if (process.env.NODE_ENV === 'development') return true;
return (
typeof window !== UNDEFINED_TYPE &&
typeof window.fetch === FUNCTION_TYPE &&
typeof window.location !== UNDEFINED_TYPE &&
typeof window.history !== UNDEFINED_TYPE &&
typeof navigator !== UNDEFINED_TYPE &&
typeof navigator.clipboard !== UNDEFINED_TYPE &&
typeof navigator.clipboard.writeText === FUNCTION_TYPE
);
}, []);

const share = useCallback((code: string): void => {
if (token) {
fetchApi({code, token})
.then((data: FetchResponse) => {
if (data.success && data.id && history) {
history.replaceState('', '', `#${data.id}`);
}
});
}
}, [token]);

useEffect(() => {
fetchApi()
.then((data: FetchResponse) => {
if (data.success && data.token) {
setToken(data.token);
} else {
setReady(true);
}
})
.catch(() => setReady(true));
}, []);

useEffect(() => {
if (token) {
if (
typeof window !== 'undefined' &&
window.location &&
window.location.hash
) {
setId(window.location.hash.slice(1));
} else {
setReady(true);
}
}
}, [token]);

useEffect(() => {
if (id && token) {
fetchApi({id, token})
.then((data: FetchResponse) => {
if (data.success && data.code) {
setFetchCode(data.code);
}
setReady(true);
})
.catch(() => setReady(true));
}
}, [id, token]);

return {
canShare,
token,
fetchCode,
ready,
share
};

};
26 changes: 26 additions & 0 deletions playground/src/icons/Share.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import React from 'react';

interface ShareProps {
color?: string;
size?: number;
}

export const Share = (props: ShareProps): JSX.Element => {
const { color = '#FFF', size = 30 } = props;
return (
<svg
version="1.1"
xmlns="http://www.w3.org/2000/svg"
x="0px"
y="0px"
viewBox="0 0 30 30"
height={size}
width={size}
>
<path fill={color} d="M24.6,0c-3,0-5.4,2.4-5.4,5.4c0,0.1,0,0.3,0,0.4l-10,4.7C8.2,9.6,6.9,9,5.4,9C2.4,9,0,11.4,0,14.4c0,3,2.4,5.4,5.4,5.4
c0.9,0,1.8-0.2,2.6-0.7l4.3,3.7c-0.2,0.6-0.3,1.1-0.3,1.8c0,3,2.4,5.4,5.4,5.4c3,0,5.4-2.4,5.4-5.4s-2.4-5.4-5.4-5.4
c-0.9,0-1.8,0.2-2.6,0.7l-4.3-3.7c0.2-0.6,0.3-1.1,0.3-1.8c0-0.1,0-0.2,0-0.4l10-4.7c1,0.9,2.3,1.5,3.7,1.5c3,0,5.4-2.4,5.4-5.4
S27.6,0,24.6,0z"/>
</svg>
);
};
4 changes: 3 additions & 1 deletion playground/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@
"@types": ["@types"],
"@constants": ["constants"],
"@components/*": ["components/*"],
"@utilities/*": ["utilities/*"]
"@hooks/*": ["hooks/*"],
"@utilities/*": ["utilities/*"],
"@icons/*": ["icons/*"]
}
},
"include": ["src/**/*"],
Expand Down
2 changes: 1 addition & 1 deletion src/options.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Mode, Source, Autorename } from '@types';
import { PluginOptions, Mode, Source, Autorename } from '@types';

export default {
Mode,
Expand Down