ソースを参照

[update] fix for coding rule

RoyLiu 5 年 前
コミット
dd732b36c7
86 ファイル変更1011 行追加997 行削除
  1. 11 0
      .eslintrc.js
  2. 1 1
      actions/index.ts
  3. 7 3
      actions/main.ts
  4. 24 10
      actions/pdf.ts
  5. 43 40
      components/Annotations/index.tsx
  6. 11 10
      components/Box/index.tsx
  7. 6 0
      components/Box/styled.ts
  8. 20 32
      components/Button/index.tsx
  9. 5 5
      components/Button/styled.ts
  10. 14 16
      components/ColorSelect/index.tsx
  11. 30 32
      components/CreateForm/index.tsx
  12. 9 11
      components/Dialog/index.tsx
  13. 6 8
      components/Divider/index.tsx
  14. 10 12
      components/Divider/styled.ts
  15. 12 14
      components/Drawer/index.tsx
  16. 6 6
      components/Drawer/styled.ts
  17. 3 8
      components/ExpansionPanel/index.tsx
  18. 1 1
      components/ExpansionPanel/styled.ts
  19. 39 41
      components/Freehand/index.tsx
  20. 14 22
      components/Head.js
  21. 27 29
      components/HighlightTools/index.tsx
  22. 1 1
      components/Icon/data.ts
  23. 4 4
      components/Icon/index.tsx
  24. 2 2
      components/Icon/styled.ts
  25. 10 6
      components/MarkupTools/index.tsx
  26. 10 12
      components/Modal/index.tsx
  27. 18 20
      components/Navbar/index.tsx
  28. 15 11
      components/PageView/index.tsx
  29. 1 1
      components/PageView/styled.ts
  30. 18 12
      components/Pagination/index.tsx
  31. 5 5
      components/Pagination/styled.ts
  32. 29 31
      components/PdfSkeleton/index.tsx
  33. 3 3
      components/Portal/index.tsx
  34. 16 16
      components/Search/index.tsx
  35. 6 6
      components/Search/styled.ts
  36. 17 17
      components/SelectBox/index.tsx
  37. 4 4
      components/SelectBox/styled.ts
  38. 29 31
      components/Shape/index.tsx
  39. 10 10
      components/Skeleton/index.tsx
  40. 5 8
      components/Skeleton/styled.ts
  41. 15 13
      components/Sliders/index.tsx
  42. 4 4
      components/Sliders/styled.ts
  43. 3 3
      components/Tabs/index.tsx
  44. 2 2
      components/Tabs/styled.ts
  45. 12 29
      components/TextField/index.tsx
  46. 8 9
      components/TextField/styled.ts
  47. 50 0
      components/TextTools/data.ts
  48. 59 108
      components/TextTools/index.tsx
  49. 16 11
      components/Thumbnail/index.tsx
  50. 24 17
      components/ThumbnailViewer/index.tsx
  51. 1 1
      components/ThumbnailViewer/styled.ts
  52. 7 9
      components/Toasts/index.tsx
  53. 2 2
      components/Toasts/styled.ts
  54. 34 32
      components/Toolbar/data.ts
  55. 15 15
      components/Toolbar/index.tsx
  56. 6 4
      components/Tooltip/index.tsx
  57. 1 1
      components/Tooltip/styled.ts
  58. 6 7
      components/Typography/index.tsx
  59. 5 4
      components/Typography/styled.ts
  60. 15 15
      components/Viewer/index.tsx
  61. 71 75
      components/Watermark/index.tsx
  62. 1 1
      components/Watermark/styled.ts
  63. 4 4
      config/index.js
  64. 1 1
      constants/style.ts
  65. 5 5
      containers/Navbar.tsx
  66. 2 2
      containers/Placeholder.tsx
  67. 8 8
      containers/Sidebar.tsx
  68. 8 6
      containers/Thumbnails.tsx
  69. 10 8
      containers/Toolbar.tsx
  70. 6 6
      containers/Watermark.tsx
  71. 2 2
      global/toolStyled.ts
  72. 2 2
      helpers/dom.ts
  73. 4 4
      helpers/pdf.ts
  74. 5 3
      helpers/time.ts
  75. 28 23
      helpers/utility.ts
  76. 3 1
      middleware/index.ts
  77. 2 1
      package.json
  78. 0 17
      pages/demo.tsx
  79. 10 12
      pages/index.tsx
  80. 8 8
      pages/toasts.tsx
  81. 5 2
      reducers/index.ts
  82. 2 2
      reducers/main.ts
  83. 7 7
      reducers/pdf.ts
  84. 9 8
      store/index.tsx
  85. 2 2
      store/initialPdfState.ts
  86. 19 0
      yarn.lock

+ 11 - 0
.eslintrc.js

@@ -14,9 +14,20 @@ module.exports = {
       typescript: {},
     },
   },
+  "overrides": [
+    {
+     "files": ["*styled.js", "*styled.ts", "*Styled.ts"],
+      "rules": {
+        "@typescript-eslint/explicit-function-return-type": 0,
+        "import/prefer-default-export": 0
+      }
+    }
+  ],
   "rules": {
     "no-console": "off",
     "react/jsx-filename-extension": [2, { extensions: ['.js', '.jsx', '.ts', '.tsx'] }],
     "camelcase": [0, {properties: "never"}],
+    "@typescript-eslint/no-explicit-any": 0,
+    "@typescript-eslint/ban-ts-ignore": 0,
   }
 };

+ 1 - 1
actions/index.ts

@@ -2,7 +2,7 @@ import { Dispatch } from 'react';
 import pdfActions from './pdf';
 import mainActions from './main';
 
-const useActions = (dispatch: Dispatch<any>) => ({
+const useActions = (dispatch: Dispatch<any>): any => ({
   ...pdfActions(dispatch),
   ...mainActions(dispatch),
 });

+ 7 - 3
actions/main.ts

@@ -1,6 +1,10 @@
 import * as types from '../constants/actionTypes';
 
-export default (dispatch: any) => ({
-  switchNavbar: (state: string) => dispatch({ type: types.SWITCH_NAVBAR, payload: { state }}),
-  switchSidebar: (state: string) => dispatch({ type: types.SWITCH_SIDEBAR, payload: { state }}),
+export default (dispatch: any): any => ({
+  switchNavbar: (state: string): any => (
+    dispatch({ type: types.SWITCH_NAVBAR, payload: { state } })
+  ),
+  switchSidebar: (state: string): any => (
+    dispatch({ type: types.SWITCH_SIDEBAR, payload: { state } })
+  ),
 });

+ 24 - 10
actions/pdf.ts

@@ -1,12 +1,26 @@
 import * as types from '../constants/actionTypes';
-import { ProgressType, ViewportType} from '../constants/type';
+import { ProgressType, ViewportType } from '../constants/type';
 
-export default (dispatch: any) => ({
-  setTotalPage: (page: number) => dispatch({ type: types.SET_TOTAL_PAGE, payload: page }),
-  setCurrentPage: (page: number) => dispatch({ type: types.SET_CURRENT_PAGE, payload: page }),
-  setPdf: (pdf: Object) => dispatch({ type: types.SET_PDF, payload: pdf }),
-  setProgress: (progress: ProgressType) => dispatch({ type: types.SET_PROGRESS, payload: progress }),
-  setViewport: (viewport: ViewportType) => dispatch({ type: types.SET_VIEWPORT, payload: viewport }),
-  changeScale: (scale: number | string) => dispatch({ type: types.CHANGE_SCALE, payload: scale }),
-  changeRotate: (rotation: number) => dispatch({ type: types.CHANGE_ROTATE, payload: rotation }),
-})
+export default (dispatch: any): any => ({
+  setTotalPage: (page: number): any => (
+    dispatch({ type: types.SET_TOTAL_PAGE, payload: page })
+  ),
+  setCurrentPage: (page: number): any => (
+    dispatch({ type: types.SET_CURRENT_PAGE, payload: page })
+  ),
+  setPdf: (pdf: Record<string, any>): any => (
+    dispatch({ type: types.SET_PDF, payload: pdf })
+  ),
+  setProgress: (progress: ProgressType): any => (
+    dispatch({ type: types.SET_PROGRESS, payload: progress })
+  ),
+  setViewport: (viewport: ViewportType): any => (
+    dispatch({ type: types.SET_VIEWPORT, payload: viewport })
+  ),
+  changeScale: (scale: number | string): any => (
+    dispatch({ type: types.CHANGE_SCALE, payload: scale })
+  ),
+  changeRotate: (rotation: number): any => (
+    dispatch({ type: types.CHANGE_ROTATE, payload: rotation })
+  ),
+});

+ 43 - 40
components/Annotations/index.tsx

@@ -5,9 +5,13 @@ import Drawer from '../Drawer';
 import Typography from '../Typography';
 import Divider from '../Divider';
 
-import { AnnotationBox, PageNumber, Content, Info } from './styled';
+import {
+  AnnotationBox, PageNumber, Content, Info,
+} from './styled';
 import { Separator } from '../../global/otherStyled';
-import { Wrapper, Head, Body, IconWrapper } from '../../global/sidebarStyled'
+import {
+  Wrapper, Head, Body, IconWrapper,
+} from '../../global/sidebarStyled';
 
 type Props = {
   isActive?: boolean;
@@ -17,43 +21,42 @@ type Props = {
 const Annotations: React.FunctionComponent<Props> = ({
   isActive = false,
   close,
-}) => {
-  return (
-    <Drawer anchor="right" open={isActive}>
-      <Wrapper>
-        <Head>
-          <IconWrapper>
-            <Icon glyph="right-back" onClick={close} />
-          </IconWrapper>
-          <Separator />
-          <IconWrapper>
-            <Icon glyph="sort" />
-          </IconWrapper>
-          <IconWrapper>
-            <Icon glyph="annotation-export" />
-          </IconWrapper>
-          <IconWrapper>
-            <Icon glyph="import" />
-          </IconWrapper>
-        </Head>
-        <Body>
-          <Typography light>2 Annotations</Typography>
-          <Divider orientation="horizontal" />
-          <PageNumber>Page 1</PageNumber>
-          <AnnotationBox>
-            <Content>
-              If the Photographer fails to appear at the place and time specified above, the deposit shall be refunded to the Client.
-            </Content>
-            <Info>
-              Gameboy
-              <Separator />
-              2016/07/28 18:18
-            </Info>
-          </AnnotationBox>
-        </Body>
-      </Wrapper>
-    </Drawer>
-  );
-};
+}: Props) => (
+  <Drawer anchor="right" open={isActive}>
+    <Wrapper>
+      <Head>
+        <IconWrapper>
+          <Icon glyph="right-back" onClick={close} />
+        </IconWrapper>
+        <Separator />
+        <IconWrapper>
+          <Icon glyph="sort" />
+        </IconWrapper>
+        <IconWrapper>
+          <Icon glyph="annotation-export" />
+        </IconWrapper>
+        <IconWrapper>
+          <Icon glyph="import" />
+        </IconWrapper>
+      </Head>
+      <Body>
+        <Typography light>2 Annotations</Typography>
+        <Divider orientation="horizontal" />
+        <PageNumber>Page 1</PageNumber>
+        <AnnotationBox>
+          <Content>
+            If the Photographer fails to appear at the place and time specified above,
+            the deposit shall be refunded to the Client.
+          </Content>
+          <Info>
+            Gameboy
+            <Separator />
+            2016/07/28 18:18
+          </Info>
+        </AnnotationBox>
+      </Body>
+    </Wrapper>
+  </Drawer>
+);
 
 export default Annotations;

+ 11 - 10
components/Box/index.tsx

@@ -1,10 +1,6 @@
 import React from 'react';
-import styled from 'styled-components';
 
-const Wrapper = styled('div')<{styles?: string[]}>`
-  ${props => props.styles}
-  width: 100%;
-`;
+import { Wrapper } from './styled';
 
 const properties: {[index: string]: string} = {
   m: 'margin',
@@ -22,19 +18,24 @@ const directions: {[index: string]: string} = {
   l: 'Left',
 };
 
-type Props = any;
+type Props = {
+  [index: string]: React.ReactNode;
+  children: React.ReactNode;
+};
 
-const Box: React.FunctionComponent<Props> = (props) => {
-  const {children, ...rest} = props;
+const Box: React.FunctionComponent<Props> = ({
+  children,
+  ...rest
+}: Props) => {
   const args = Object.keys(rest);
 
   const styles = args.map((ele: string) => {
     const property = properties[ele[0]];
     const direction = directions[ele[1]];
     if (direction) {
-      return `${property}-${direction}: ${props[ele]}px;`;
+      return `${property}-${direction}: ${rest[ele]}px;`;
     }
-    return `${property}: ${props[ele]};`;
+    return `${property}: ${rest[ele]};`;
   });
 
   return (

+ 6 - 0
components/Box/styled.ts

@@ -0,0 +1,6 @@
+import styled from 'styled-components';
+
+export const Wrapper = styled('div')<{styles?: string[]}>`
+  ${props => props.styles}
+  width: 100%;
+`;

+ 20 - 32
components/Button/index.tsx

@@ -14,44 +14,32 @@ export type Props = {
   shouldFitContainer?: boolean;
   align?: 'left' | 'center' | 'right';
   children: React.ReactNode;
-  isActive?: boolean;
   style?: {};
 };
 
 const Button: React.FunctionComponent<Props> = ({
-  appearance = 'default',
-  isDisabled = false,
-  onClick,
-  onBlur,
-  id,
-  shouldFitContainer = false,
-  align = 'center',
   children,
-  style,
-}: Props): React.ReactElement => {
-  const transferProps = {
-    appearance,
-    onClick,
-    onBlur,
-    id,
-    shouldFitContainer,
-    align,
-    style,
-  };
+  isDisabled,
+  ...rest
+}: Props): React.ReactElement => (
+  isDisabled ? (
+    <DisableButton>
+      {children}
+    </DisableButton>
+  ) : (
+    <NormalButton
+      {...rest}
+    >
+      {children}
+    </NormalButton>
+  )
+);
 
-  return (
-    isDisabled ? (
-      <DisableButton>
-        {children}
-      </DisableButton>
-    ) : (
-      <NormalButton
-        {...transferProps}
-      >
-        {children}
-      </NormalButton>
-    )
-  );
+Button.defaultProps = {
+  appearance: 'default',
+  align: 'center',
+  shouldFitContainer: false,
+  isDisabled: false,
 };
 
 export default Button;

+ 5 - 5
components/Button/styled.ts

@@ -96,15 +96,15 @@ const theme: {[index: string]: any} = {
   `,
 };
 
-export const NormalButton = styled('button')<{appearance: string, shouldFitContainer: boolean, align: string}>`
+export const NormalButton = styled('button')<{appearance?: string; shouldFitContainer?: boolean; align?: string}>`
   ${staticStyles}
-  ${props => theme[props.appearance!]};
-  ${props => props.shouldFitContainer ? css`
+  ${props => theme[props.appearance || 'default']};
+  ${props => (props.shouldFitContainer ? css`
     width: 100%;
-  ` : null}
+  ` : null)}
 
   display: inline-flex;
-  justify-content: ${props => align[props.align!]};
+  justify-content: ${props => align[props.align || 'center']};
   align-items: center;
 `;
 

+ 14 - 16
components/ColorSelect/index.tsx

@@ -7,22 +7,20 @@ import { Group, Item, Circle } from '../../global/toolStyled';
 
 import data from './data';
 
-const ColorSelect = () => {
-  return (
-    <>
-      <Typography variant="subtitle" style={{marginTop: '8px'}}>Color</Typography>
-      <Group>
-        {data.map((ele) => (
-          <Item key={ele.key}>
-            <Circle color={ele.color} />
-          </Item>
-        ))}
-        <Item>
-          <Icon glyph="color-picker" />
+const ColorSelect: React.FunctionComponent = () => (
+  <>
+    <Typography variant="subtitle" style={{ marginTop: '8px' }}>Color</Typography>
+    <Group>
+      {data.map(ele => (
+        <Item key={ele.key}>
+          <Circle color={ele.color} />
         </Item>
-      </Group>
-    </>
-  );
-};
+      ))}
+      <Item>
+        <Icon glyph="color-picker" />
+      </Item>
+    </Group>
+  </>
+);
 
 export default ColorSelect;

+ 30 - 32
components/CreateForm/index.tsx

@@ -14,37 +14,35 @@ type Props = {
 const CreateForm: React.FunctionComponent<Props> = ({
   onClick,
   sidebarState,
-}) => {
-  return (
-    <ExpansionPanel
-      label={
-        <Button shouldFitContainer align="left" onClick={() => { onClick('create-form'); }}>
-          <Icon glyph="create-form" style={{marginRight: '10px'}}/>
-          Create Form
-        </Button>
-      }
-      isActive={sidebarState === 'create-form'}
-    >
-      <BtnWrapper>
-        <Button shouldFitContainer align="left">
-          <Icon glyph="text-field" style={{marginRight: '10px'}}/>
-          Text Field
-        </Button>
-      </BtnWrapper>
-      <BtnWrapper>
-        <Button shouldFitContainer align="left">
-          <Icon glyph="checkbox" style={{marginRight: '10px'}}/>
-          Check box
-        </Button>
-      </BtnWrapper>
-      <BtnWrapper>
-        <Button shouldFitContainer align="left">
-          <Icon glyph="radio-button" style={{marginRight: '10px'}}/>
-          Radio Button
-        </Button>
-      </BtnWrapper>
-    </ExpansionPanel>
-  );
-};
+}: Props) => (
+  <ExpansionPanel
+    label={(
+      <Button shouldFitContainer align="left" onClick={(): void => { onClick('create-form'); }}>
+        <Icon glyph="create-form" style={{ marginRight: '10px' }} />
+        Create Form
+      </Button>
+    )}
+    isActive={sidebarState === 'create-form'}
+  >
+    <BtnWrapper>
+      <Button shouldFitContainer align="left">
+        <Icon glyph="text-field" style={{ marginRight: '10px' }} />
+        Text Field
+      </Button>
+    </BtnWrapper>
+    <BtnWrapper>
+      <Button shouldFitContainer align="left">
+        <Icon glyph="checkbox" style={{ marginRight: '10px' }} />
+        Check box
+      </Button>
+    </BtnWrapper>
+    <BtnWrapper>
+      <Button shouldFitContainer align="left">
+        <Icon glyph="radio-button" style={{ marginRight: '10px' }} />
+        Radio Button
+      </Button>
+    </BtnWrapper>
+  </ExpansionPanel>
+);
 
 export default CreateForm;

+ 9 - 11
components/Dialog/index.tsx

@@ -10,16 +10,14 @@ type Props = {
 
 const Dialog: React.FunctionComponent<Props> = ({
   open,
-}) => {
-  return (
-    open ? (
-      <Modal>
-        <Wrapper>
-          aaaaaa
-        </Wrapper>
-      </Modal>
-    ) : null
-  );
-};
+}: Props) => (
+  open ? (
+    <Modal>
+      <Wrapper>
+        aaaaaa
+      </Wrapper>
+    </Modal>
+  ) : null
+);
 
 export default Dialog;

+ 6 - 8
components/Divider/index.tsx

@@ -7,16 +7,14 @@ export type Props = {
   orientation?: 'vertical' | 'horizontal';
   variant?: 'fullWidth' | 'inset' | 'middle';
   light?: boolean;
-  style?: Object;
+  style?: Record<string, any>;
 }
 
-const Divider: React.FunctionComponent<Props> = (props) => {
-  return (
-    <Component
-      {...props}
-    />
-  );
-};
+const Divider: React.FunctionComponent<Props> = props => (
+  <Component
+    {...props}
+  />
+);
 
 Divider.defaultProps = {
   absolute: false,

+ 10 - 12
components/Divider/styled.ts

@@ -2,34 +2,32 @@ import styled, { css } from 'styled-components';
 
 import { color } from '../../constants/style';
 
-import { Props } from './index';
-
-export const Component = styled('hr')<Props>`
+export const Component = styled('hr')<{light?: boolean; absolute?: boolean; orientation?: string; variant?: string}>`
   height: 1px;
   margin: 6px 0;
   border: none;
   flex-shrink: 0;
-  background-color: ${props => props.light ? 'white' : color["light-gray"] };
+  background-color: ${props => (props.light ? 'white' : color['light-gray'])};
 
-  ${props => props.absolute ? css`
+  ${props => (props.absolute ? css`
     position: absolute;
     bottom: 0;
     left: 0;
     width: 100%;
-  ` : ''}
+  ` : '')}
 
-  ${props => props.orientation === 'vertical' ? css`
+  ${props => (props.orientation === 'vertical' ? css`
     height: 100%;
     width: 1px;
     margin: 0 6px;
-  ` : ''}
+  ` : '')}
 
-  ${props => props.variant === 'inset' ? css`
+  ${props => (props.variant === 'inset' ? css`
     margin-left: 52px;
-  ` : ''}
+  ` : '')}
 
-  ${props => props.variant === 'middle' ? css`
+  ${props => (props.variant === 'middle' ? css`
     margin-left: 10px;
     margin-right: 10px;
-  ` : ''}
+  ` : '')}
 `;

+ 12 - 14
components/Drawer/index.tsx

@@ -14,19 +14,17 @@ const Drawer: React.FunctionComponent<Props> = ({
   anchor = 'bottom',
   children,
   open,
-}) => {
-  return (
-    <Portal>
-      <Slide
-        open={open}
-        anchor={anchor}
-      >
-        <Container>
-          {children}
-        </Container>
-      </Slide>
-    </Portal>
-  );
-};
+}: Props) => (
+  <Portal>
+    <Slide
+      open={open}
+      anchor={anchor}
+    >
+      <Container>
+        {children}
+      </Container>
+    </Slide>
+  </Portal>
+);
 
 export default Drawer;

+ 6 - 6
components/Drawer/styled.ts

@@ -1,6 +1,6 @@
-import styled, { css }from 'styled-components';
+import styled, { css } from 'styled-components';
 
-const position: {[index: string]:any} = {
+const position: {[index: string]: any} = {
   left: css`
     top: 0;
     bottom: 0;
@@ -27,7 +27,7 @@ const position: {[index: string]:any} = {
   `,
 };
 
-const close: {[index: string]:any} = {
+const close: {[index: string]: any} = {
   left: css`
     transform: translate(-267px, 0);
   `,
@@ -42,7 +42,7 @@ const close: {[index: string]:any} = {
   `,
 };
 
-export const Slide = styled('div')<{open: boolean, anchor: string}>`
+export const Slide = styled('div')<{open: boolean; anchor: string}>`
   position: fixed;
   transition: transform 225ms cubic-bezier(0, 0, 0.2, 1) 0ms;
   z-index: 3;
@@ -50,10 +50,10 @@ export const Slide = styled('div')<{open: boolean, anchor: string}>`
 
   ${props => position[props.anchor]}
 
-  ${props => props.open ? css`
+  ${props => (props.open ? css`
     transform: translate(0, 0);
   ` : close[props.anchor]
-  }
+  )}
 `;
 
 export const Container = styled.div`

+ 3 - 8
components/ExpansionPanel/index.tsx

@@ -11,13 +11,13 @@ type Props = {
 };
 
 const Collapse: React.FunctionComponent<Props> = ({
-  label,
+  label = '',
   children = '',
   isActive = false,
-}) => {
+}: Props) => {
   const [isCollapse, setCollapse] = useState(true);
 
-  const handleClick = () => {
+  const handleClick = (): void => {
     setCollapse(!isCollapse);
   };
 
@@ -41,9 +41,4 @@ const Collapse: React.FunctionComponent<Props> = ({
   );
 };
 
-Collapse.defaultProps = {
-  label: '',
-  children: '',
-};
-
 export default Collapse;

+ 1 - 1
components/ExpansionPanel/styled.ts

@@ -15,7 +15,7 @@ export const Label = styled.span`
 export const ContentWrapper = styled('div')<{isCollapse: boolean}>`
   display: inline-block;
   transition: max-height 0.35s cubic-bezier(0.4, 0, 0.2, 1) 0ms;
-  max-height: ${props => props.isCollapse ? '0px' : '800px'};
+  max-height: ${props => (props.isCollapse ? '0px' : '800px')};
   background-color: ${color['hyper-light-gray']};
   overflow: hidden;
 `;

+ 39 - 41
components/Freehand/index.tsx

@@ -23,46 +23,44 @@ const BrushOptions = [
   },
 ];
 
-const Freehand = () => {
-  return (
-    <ExpansionPanel 
-      label={
-        <Button shouldFitContainer align="left">
-          <Icon glyph="freehand" style={{marginRight: '10px'}} />
-          Freehand
-        </Button>
-      }
-    >
-      <Typography variant="subtitle" style={{marginTop: '4px'}}>Tools</Typography>
-      <Group>
-        <SelectBox options={BrushOptions} />
-        <Item size="small">
-          <Icon glyph="eraser" />
-        </Item>
-        <Item size="small">
-          <Icon glyph="redo" />
-        </Item>
-        <Item size="small">
-          <Icon glyph="undo" />
-        </Item>
-      </Group>
-      <ColorSelect />
-      <Typography variant="subtitle" style={{marginTop: '4px'}}>Opacity</Typography>
-      <Group>
-        <SliderWrapper>
-          <Sliders />
-        </SliderWrapper>
-        40%
-      </Group>
-      <Typography variant="subtitle" style={{marginTop: '8px'}}>Width</Typography>
-      <Group>
-        <SliderWrapper>
-          <Sliders />
-        </SliderWrapper>
-        12pt
-      </Group>
-    </ExpansionPanel>
-  );
-};
+const Freehand: React.FunctionComponent = () => (
+  <ExpansionPanel
+    label={(
+      <Button shouldFitContainer align="left">
+        <Icon glyph="freehand" style={{ marginRight: '10px' }} />
+        Freehand
+      </Button>
+    )}
+  >
+    <Typography variant="subtitle" style={{ marginTop: '4px' }}>Tools</Typography>
+    <Group>
+      <SelectBox options={BrushOptions} />
+      <Item size="small">
+        <Icon glyph="eraser" />
+      </Item>
+      <Item size="small">
+        <Icon glyph="redo" />
+      </Item>
+      <Item size="small">
+        <Icon glyph="undo" />
+      </Item>
+    </Group>
+    <ColorSelect />
+    <Typography variant="subtitle" style={{ marginTop: '4px' }}>Opacity</Typography>
+    <Group>
+      <SliderWrapper>
+        <Sliders />
+      </SliderWrapper>
+      40%
+    </Group>
+    <Typography variant="subtitle" style={{ marginTop: '8px' }}>Width</Typography>
+    <Group>
+      <SliderWrapper>
+        <Sliders />
+      </SliderWrapper>
+      12pt
+    </Group>
+  </ExpansionPanel>
+);
 
 export default Freehand;

+ 14 - 22
components/Head.js

@@ -1,18 +1,25 @@
 import React from 'react';
-import PropTypes from 'prop-types';
 import NextHead from 'next/head';
 import { withTranslation } from '../i18n';
 
 const defaultOGURL = '';
 const defaultOGImage = '';
 
-const Head = ({
+type Props = {
+  t: (key: string) => string;
+  title?: string;
+  description?: string;
+  url?: string;
+  ogImage?: string;
+};
+
+const Head: React.StatelessComponent<Props> = ({
   t,
-  title,
-  description,
-  url,
-  ogImage,
-}) => (
+  title = 'title',
+  description = 'description',
+  url = '',
+  ogImage = '',
+}: Props) => (
   <NextHead>
     <meta charSet="UTF-8" />
     <title>{t(title)}</title>
@@ -40,19 +47,4 @@ const Head = ({
   </NextHead>
 );
 
-Head.propTypes = {
-  t: PropTypes.func.isRequired,
-  title: PropTypes.string,
-  description: PropTypes.string,
-  url: PropTypes.string,
-  ogImage: PropTypes.string,
-};
-
-Head.defaultProps = {
-  title: 'title',
-  description: 'description',
-  url: '',
-  ogImage: '',
-};
-
 export default withTranslation('meta')(Head);

+ 27 - 29
components/HighlightTools/index.tsx

@@ -10,34 +10,32 @@ import ColorSelect from '../ColorSelect';
 import { Group, Item, SliderWrapper } from '../../global/toolStyled';
 import data from './data';
 
-const Highlight = () => {
-  return (
-    <ExpansionPanel 
-      label={
-        <Button shouldFitContainer align="left">
-          <Icon glyph="highlight" style={{marginRight: '10px'}}/>
-          Highlight Tools
-        </Button>
-      }
-    >
-      <Typography variant="subtitle" style={{marginTop: '8px'}}>Style</Typography>
-      <Group>
-        {data.lineType.map((ele) => (
-          <Item key={ele.key}>
-            <Icon glyph={ele.icon} />
-          </Item>
-        ))}
-      </Group>
-      <ColorSelect />
-      <Typography variant="subtitle" style={{marginTop: '8px'}}>Opacity</Typography>
-      <Group>
-        <SliderWrapper>
-          <Sliders />
-        </SliderWrapper>
-        40%
-      </Group>
-    </ExpansionPanel>
-  );
-};
+const Highlight: React.FunctionComponent = () => (
+  <ExpansionPanel
+    label={(
+      <Button shouldFitContainer align="left">
+        <Icon glyph="highlight" style={{ marginRight: '10px' }} />
+        Highlight Tools
+      </Button>
+    )}
+  >
+    <Typography variant="subtitle" style={{ marginTop: '8px' }}>Style</Typography>
+    <Group>
+      {data.lineType.map(ele => (
+        <Item key={ele.key}>
+          <Icon glyph={ele.icon} />
+        </Item>
+      ))}
+    </Group>
+    <ColorSelect />
+    <Typography variant="subtitle" style={{ marginTop: '8px' }}>Opacity</Typography>
+    <Group>
+      <SliderWrapper>
+        <Sliders />
+      </SliderWrapper>
+      40%
+    </Group>
+  </ExpansionPanel>
+);
 
 export default Highlight;

+ 1 - 1
components/Icon/data.ts

@@ -68,7 +68,7 @@ import Sort from '../../static/icons/annotation/sort.svg';
 import Import from '../../static/icons/annotation/import.svg';
 import AnnotationExport from '../../static/icons/annotation/Export.svg';
 
-const data : {[index: string]: any} = {
+const data: {[index: string]: any} = {
   close: {
     Normal: Close,
   },

+ 4 - 4
components/Icon/index.tsx

@@ -15,14 +15,14 @@ type Props = {
   isActive? : boolean;
 };
 
-const Icon : React.FunctionComponent<Props> = ({
+const Icon: React.FunctionComponent<Props> = ({
   glyph,
   id = '',
-  onClick = () => {},
-  onBlur = () => {},
+  onClick,
+  onBlur,
   style,
   isActive = false,
-}) => {
+}: Props) => {
   const {
     Normal,
     Hover,

+ 2 - 2
components/Icon/styled.ts

@@ -33,7 +33,7 @@ export const IconWrapper = styled('div')<{isHover: boolean}>`
     margin: auto;
   }
 
-  ${props => props.isHover ? css`
+  ${props => (props.isHover ? css`
     :hover {
       [data-status='hover'] {
         opacity: 1;
@@ -42,7 +42,7 @@ export const IconWrapper = styled('div')<{isHover: boolean}>`
         opacity: 0;
       }
     }
-  ` : null}
+  ` : null)}
 `;
 
 export const ClickZone = styled.div`

+ 10 - 6
components/MarkupTools/index.tsx

@@ -18,15 +18,19 @@ type Props = {
 const MarkupTools: React.FunctionComponent<Props> = ({
   onClick,
   sidebarState,
-}) => {
+}: Props) => {
+  const handleClick = (): void => {
+    onClick('markup-tools');
+  };
+
   return (
     <ExpansionPanel
-      label={
-        <Button shouldFitContainer align="left" onClick={() => { onClick('markup-tools'); }}>
-          <Icon glyph="markup-tools" style={{marginRight: '10px'}}/>
+      label={(
+        <Button shouldFitContainer align="left" onClick={handleClick}>
+          <Icon glyph="markup-tools" style={{ marginRight: '10px' }} />
           Markup Tools
         </Button>
-      }
+      )}
       isActive={sidebarState === 'markup-tools'}
     >
       <HighlightTools />
@@ -34,7 +38,7 @@ const MarkupTools: React.FunctionComponent<Props> = ({
       <TextTools />
       <BtnWrapper>
         <Button shouldFitContainer align="left">
-          <Icon glyph="sticky-note" style={{marginRight: '10px'}}/>
+          <Icon glyph="sticky-note" style={{ marginRight: '10px' }} />
           Sticky Note
         </Button>
       </BtnWrapper>

+ 10 - 12
components/Modal/index.tsx

@@ -12,17 +12,15 @@ type Props = {
 const Modal: React.FunctionComponent<Props> = ({
   children,
   hideBackdrop = false,
-}) => {
-  return (
-    <Portal>
-      <Container>
-        {hideBackdrop ? null : <Blanket />}
-        <Content>
-          {children}
-        </Content>
-      </Container>
-    </Portal>
-  );
-};
+}: Props) => (
+  <Portal>
+    <Container>
+      {hideBackdrop ? null : <Blanket />}
+      <Content>
+        {children}
+      </Content>
+    </Container>
+  </Portal>
+);
 
 export default Modal;

+ 18 - 20
components/Navbar/index.tsx

@@ -17,25 +17,23 @@ const Navbar: React.FunctionComponent<Props> = ({
   onClick,
   navbarState,
   children,
-}) => {
-  return (
-    <Wrapper>
-      <Typography variant="title">Title</Typography>
-      <Icon glyph="edit" />
-      <Separator />
-      {
-        data.btnGroup.map((ele) => (
-          <Icon
-            key={ele.key}
-            glyph={ele.content}
-            isActive={navbarState === ele.content}
-            onClick={() => { onClick(ele.content); }}
-          />
-        ))
-      }
-      {children}
-    </Wrapper>
-  );
-};
+}: Props) => (
+  <Wrapper>
+    <Typography variant="title">Title</Typography>
+    <Icon glyph="edit" />
+    <Separator />
+    {
+      data.btnGroup.map(ele => (
+        <Icon
+          key={ele.key}
+          glyph={ele.content}
+          isActive={navbarState === ele.content}
+          onClick={(): void => { onClick(ele.content); }}
+        />
+      ))
+    }
+    {children}
+  </Wrapper>
+);
 
 export default Navbar;

+ 15 - 11
components/PageView/index.tsx

@@ -21,10 +21,22 @@ const PageView: React.FunctionComponent<Props> = ({
   viewport,
   renderingState = 'PAUSED',
   rotation,
-}) => {
+}: Props) => {
   const rootEle = useRef<HTMLDivElement>(null);
   let page: any = null;
 
+  const renderPage = async (): Promise<any> => {
+    page = await getPage();
+
+    if (rootEle.current) {
+      await renderPdfPage({
+        rootEle: rootEle.current,
+        page,
+        viewport,
+      });
+    }
+  };
+
   useEffect(() => {
     if (renderingState === 'RENDERING') {
       renderPage();
@@ -33,18 +45,10 @@ const PageView: React.FunctionComponent<Props> = ({
     }
   }, [renderingState]);
 
-  useEffect(() => {
-    return () => {
-      if (page) page.cleanup();
-    }
+  useEffect(() => (): void => {
+    if (page) page.cleanup();
   }, []);
 
-  const renderPage = async () => {
-    page = await getPage();
-
-    await renderPdfPage({rootEle: rootEle.current!, page, viewport});
-  };
-
   return (
     <PageWrapper
       ref={rootEle}

+ 1 - 1
components/PageView/styled.ts

@@ -1,6 +1,6 @@
 import styled from 'styled-components';
 
-export const PageWrapper = styled('div')<{width: number, height: number, rotation?: number}>`
+export const PageWrapper = styled('div')<{width: number; height: number; rotation?: number}>`
   direction: ltr;
   position: relative;
   overflow: visible;

+ 18 - 12
components/Pagination/index.tsx

@@ -1,6 +1,8 @@
 import React, { useRef, useEffect, useState } from 'react';
 
-import { Wrapper, Text, Input, ArrowButton } from './styled';
+import {
+  Wrapper, Text, Input, ArrowButton,
+} from './styled';
 
 type Props = {
   currentPage: number;
@@ -12,39 +14,39 @@ const Pagination: React.FunctionComponent<Props> = ({
   currentPage = 1,
   totalPage = 1,
   onChange,
-}) => {
+}: Props) => {
   const inputRef = useRef(null);
   const [inputValue, setInputValue] = useState(currentPage);
 
-  const handleRightClick = () => {
+  const handleRightClick = (): void => {
     const nextPage = currentPage + 1;
-    
+
     if (nextPage <= totalPage) {
       onChange(nextPage);
     }
   };
 
-  const handleLeftClick = () => {
+  const handleLeftClick = (): void => {
     const prevPage = currentPage - 1;
-    
+
     if (prevPage > 0) {
       onChange(prevPage);
     }
   };
 
-  const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
-    const page = parseInt(e.target.value) || 0;
-    
+  const handleChange = (e: React.ChangeEvent<HTMLInputElement>): void => {
+    const page = parseInt(e.target.value, 10) || 0;
+
     if (page >= 0 && page <= totalPage) {
       setInputValue(page);
     }
   };
 
-  const handleKeyDown = (e: React.KeyboardEvent) => {
+  const handleKeyDown = (e: React.KeyboardEvent): void => {
     if (e.keyCode === 13) {
       onChange(inputValue);
     }
-  }
+  };
 
   useEffect(() => {
     setInputValue(currentPage);
@@ -62,7 +64,11 @@ const Pagination: React.FunctionComponent<Props> = ({
         value={inputValue}
       />
       <ArrowButton onClick={handleRightClick} variant="right" />
-      <Text>of {totalPage}</Text>
+      <Text>
+        of
+        {' '}
+        {totalPage}
+      </Text>
     </Wrapper>
   );
 };

+ 5 - 5
components/Pagination/styled.ts

@@ -1,4 +1,4 @@
-import styled, { css }from 'styled-components';
+import styled, { css } from 'styled-components';
 
 import { color } from '../../constants/style';
 
@@ -13,7 +13,7 @@ export const Text = styled.span`
 `;
 
 export const Input = styled.input`
-  background-color: ${color["light-gray"]};
+  background-color: ${color['light-gray']};
   outline: none;
   border: none;
   width: 70px;
@@ -28,14 +28,14 @@ export const ArrowButton = styled('button')<{variant: string}>`
   width: 26px;
   outline: none;
   border: none;
-  background-color: ${color["light-gray"]};
+  background-color: ${color['light-gray']};
   cursor: pointer;
   position: relative;
   display: flex;
   align-items: center;
   justify-content: center;
 
-  ${props => props.variant === 'left' ? css`
+  ${props => (props.variant === 'left' ? css`
     border-top-left-radius: 4px;
     border-bottom-left-radius: 4px;
     margin-right: 1px;
@@ -67,5 +67,5 @@ export const ArrowButton = styled('button')<{variant: string}>`
     :hover:after {
       border-left: 5px solid ${color.black38};
     }
-  `}
+  `)}
 `;

+ 29 - 31
components/PdfSkeleton/index.tsx

@@ -5,39 +5,37 @@ import Skeleton from '../Skeleton';
 
 import { Wrapper } from './styled';
 
-const PdfSkeleton = () => {
-  return (
-    <Wrapper>
-      <Skeleton variant="rect" width="50%" height="36px" />
-      <Skeleton variant="rect" width="45%" height="12px" />
-      <Skeleton variant="rect" width="40%" height="12px" />
+const PdfSkeleton: React.FunctionComponent = () => (
+  <Wrapper>
+    <Skeleton variant="rect" width="50%" height="36px" />
+    <Skeleton variant="rect" width="45%" height="12px" />
+    <Skeleton variant="rect" width="40%" height="12px" />
 
-      <Box mt="30">
-        <Skeleton variant="rect" width="100%" height="14px" />
-        <Skeleton variant="rect" width="100%" height="14px" />
-        <Skeleton variant="rect" width="100%" height="14px" />
-        <Skeleton variant="rect" width="90%" height="14px" />
-      </Box>
+    <Box mt="30">
+      <Skeleton variant="rect" width="100%" height="14px" />
+      <Skeleton variant="rect" width="100%" height="14px" />
+      <Skeleton variant="rect" width="100%" height="14px" />
+      <Skeleton variant="rect" width="90%" height="14px" />
+    </Box>
 
-      <Box mt="5" d="flex">
-        <Skeleton variant="rect" width="100%" height="120px" />
-        <Box ml="15">
-          <Skeleton variant="rect" width="70%" height="16px" />
-          <Skeleton variant="rect" width="100%" height="12px" />
-          <Skeleton variant="rect" width="100%" height="12px" />
-          <Skeleton variant="rect" width="100%" height="12px" />
-          <Skeleton variant="rect" width="80%" height="12px" />
-        </Box>
+    <Box mt="5" d="flex">
+      <Skeleton variant="rect" width="100%" height="120px" />
+      <Box ml="15">
+        <Skeleton variant="rect" width="70%" height="16px" />
+        <Skeleton variant="rect" width="100%" height="12px" />
+        <Skeleton variant="rect" width="100%" height="12px" />
+        <Skeleton variant="rect" width="100%" height="12px" />
+        <Skeleton variant="rect" width="80%" height="12px" />
       </Box>
+    </Box>
 
-      <Box mt="15">
-        <Skeleton variant="rect" width="100%" height="14px" />
-        <Skeleton variant="rect" width="100%" height="14px" />
-        <Skeleton variant="rect" width="90%" height="14px" />
-        <Skeleton variant="rect" width="85%" height="14px" />
-      </Box>
-    </Wrapper>
-  );
-};
+    <Box mt="15">
+      <Skeleton variant="rect" width="100%" height="14px" />
+      <Skeleton variant="rect" width="100%" height="14px" />
+      <Skeleton variant="rect" width="90%" height="14px" />
+      <Skeleton variant="rect" width="85%" height="14px" />
+    </Box>
+  </Wrapper>
+);
 
-export default PdfSkeleton;
+export default PdfSkeleton;

+ 3 - 3
components/Portal/index.tsx

@@ -14,7 +14,7 @@ type Props = {
   children: React.ReactNode;
 };
 
-const Portal : React.FunctionComponent<Props> = ({
+const Portal: React.FunctionComponent<Props> = ({
   zIndex = 0,
   children = '',
 }) => {
@@ -28,12 +28,12 @@ const Portal : React.FunctionComponent<Props> = ({
       setContainer(newContainer);
     }
 
-    return () => {
+    return (): void => {
       if (container) {
         document.body.removeChild(container);
       }
     };
-  }, [])
+  }, []);
 
   return container ? (
     ReactDOM.createPortal(children, container)

+ 16 - 16
components/Search/index.tsx

@@ -3,7 +3,9 @@ import React from 'react';
 import Button from '../Button';
 import Portal from '../Portal';
 
-import { Wrapper, InputWrapper, Input, ResultInfo, ArrowButton } from './styled';
+import {
+  Wrapper, InputWrapper, Input, ResultInfo, ArrowButton,
+} from './styled';
 
 type Props = {
   isActive?: boolean;
@@ -13,20 +15,18 @@ type Props = {
 const Search: React.FunctionComponent<Props> = ({
   isActive = false,
   close,
-}) => {
-  return (
-    <Portal>
-      <Wrapper open={isActive}>
-        <InputWrapper>
-          <Input />
-          <ResultInfo>2 of 14</ResultInfo>
-        </InputWrapper>
-        <ArrowButton variant="top" />
-        <ArrowButton variant="bottom" />
-        <Button appearance="primary" style={{marginLeft: '16px'}} onClick={close}>Close</Button>
-      </Wrapper>
-    </Portal>
-  );
-};
+}: Props) => (
+  <Portal>
+    <Wrapper open={isActive}>
+      <InputWrapper>
+        <Input />
+        <ResultInfo>2 of 14</ResultInfo>
+      </InputWrapper>
+      <ArrowButton variant="top" />
+      <ArrowButton variant="bottom" />
+      <Button appearance="primary" style={{ marginLeft: '16px' }} onClick={close}>Close</Button>
+    </Wrapper>
+  </Portal>
+);
 
 export default Search;

+ 6 - 6
components/Search/styled.ts

@@ -13,7 +13,7 @@ export const Wrapper = styled('div')<{open: boolean}>`
   padding: 9px 16px;
   box-shadow: 0 4px 10px 0 rgba(0, 0, 0, 0.38);
   z-index: 2;
-  transform: translateY(${props => props.open ? '0' : '-60px'});
+  transform: translateY(${props => (props.open ? '0' : '-60px')});
   transition: transform 225ms cubic-bezier(0, 0, 0.2, 1) 0ms;
 `;
 
@@ -23,7 +23,7 @@ export const InputWrapper = styled.div`
   border-top-left-radius: 4px;
   border-bottom-left-radius: 4px;
   overflow: hidden;
-  background-color: ${color["light-gray"]};
+  background-color: ${color['light-gray']};
   display: flex;
   justify-content: space-between;
   align-items: center;
@@ -31,7 +31,7 @@ export const InputWrapper = styled.div`
 `;
 
 export const Input = styled.input`
-  background-color: ${color["light-gray"]};
+  background-color: ${color['light-gray']};
   outline: none;
   border: none;
   width: auto;
@@ -51,14 +51,14 @@ export const ArrowButton = styled('button')<{variant: string}>`
   width: 30px;
   outline: none;
   border: none;
-  background-color: ${color["light-gray"]};
+  background-color: ${color['light-gray']};
   cursor: pointer;
   position: relative;
   display: flex;
   align-items: center;
   justify-content: center;
 
-  ${props => props.variant === 'top' ? css`
+  ${props => (props.variant === 'top' ? css`
     margin-left: 1px;
     :after {
       content: '';
@@ -88,5 +88,5 @@ export const ArrowButton = styled('button')<{variant: string}>`
     :hover:after {
       border-top: 5px solid ${color.black38};
     }
-  `}
+  `)}
 `;

+ 17 - 17
components/SelectBox/index.tsx

@@ -23,51 +23,51 @@ type Props = {
   style?: {};
 };
 
-const SelectBox: React.FunctionComponent<Props>= ({
-  onChange = () => {},
-  options ,
+const SelectBox: React.FunctionComponent<Props> = ({
+  onChange,
+  options,
   defaultValue,
   isDivide = false,
   width = 'auto',
   useInput = false,
   style,
-}) => {
+}: Props) => {
   const selectRef = useRef<HTMLDivElement>(null);
   const optionRef = useRef<HTMLDivElement>(null);
   const [isCollapse, setCollapse] = useState(true);
   const [value, setValue] = useState(defaultValue);
 
-  const handleClick = () => {
+  const handleClick = (): void => {
     setCollapse(!isCollapse);
-  }
+  };
 
-  const handleSelect = (index: number) => {
+  const handleSelect = (index: number): void => {
     setValue(options[index].content);
 
     if (onChange) {
       onChange(options[index]);
     }
-  }
+  };
 
-  const handleBlur = () => {
+  const handleBlur = (): void => {
     setCollapse(true);
-  }
+  };
 
-  const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
+  const handleChange = (e: React.ChangeEvent<HTMLInputElement>): void => {
     setValue(e.target.value || 0);
-  }
+  };
 
-  const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
+  const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>): void => {
     if (e.keyCode === 13 && onChange && value) {
       const param = {
         key: '',
         content: '',
-        value: parseInt(value as string),
+        value: parseInt(value as string, 10),
       };
       onChange(param);
       setCollapse(true);
     }
-  }
+  };
 
   useEffect(() => {
     if (defaultValue) {
@@ -96,7 +96,7 @@ const SelectBox: React.FunctionComponent<Props>= ({
         tabIndex={0}
       >
         {
-          useInput && (typeof value === "string" || typeof value === "number") ? (
+          useInput && (typeof value === 'string' || typeof value === 'number') ? (
             <InputContent
               value={value}
               onChange={handleChange}
@@ -118,7 +118,7 @@ const SelectBox: React.FunctionComponent<Props>= ({
               options.map((option: SelectOptionType, index: number) => (
                 <Option
                   key={option.key}
-                  onMouseDown={() => { handleSelect(index); }}
+                  onMouseDown={(): void => { handleSelect(index); }}
                 >
                   {option.content}
                 </Option>

+ 4 - 4
components/SelectBox/styled.ts

@@ -1,5 +1,5 @@
 // @ts-ignore
-import styled, { css } from 'styled-components';
+import styled from 'styled-components';
 import { color } from '../../constants/style';
 
 export const Wrapper = styled('div')<{width: string}>`
@@ -15,7 +15,7 @@ export const Selected = styled.div`
   box-sizing: border-box;
   display: inline-flex;
   align-items: center;
-  background-color: ${color['gray']};
+  background-color: ${color.gray};
   height: 32px;
   border-radius: 4px;
   padding: 0 6px 0 14px;
@@ -24,14 +24,14 @@ export const Selected = styled.div`
 `;
 
 export const InputContent = styled.input`
-  background-color: ${color['gray']};
+  background-color: ${color.gray};
   border: none;
   outline: none;
   width: 100%;
 `;
 
 export const Content = styled.div`
-  background-color: ${color['gray']};
+  background-color: ${color.gray};
   border: none;
   outline: none;
   width: 100%;

+ 29 - 31
components/Shape/index.tsx

@@ -45,36 +45,34 @@ const typeOptions = [
   },
 ];
 
-const Shape = () => {
-  return (
-    <ExpansionPanel 
-      label={
-        <Button shouldFitContainer align="left">
-          <Icon glyph="shape" style={{marginRight: '10px'}} />
-          Shape
-        </Button>
-      }
-    >
-      <Typography>Shape</Typography>
-      <SelectBox options={shapeOptions} style={{marginRight: '10px'}} />
-      <SelectBox options={typeOptions} />
-      <ColorSelect />
-      <Typography variant="subtitle" style={{marginTop: '8px'}}>Opacity</Typography>
-      <Group>
-        <SliderWrapper>
-          <Sliders />
-        </SliderWrapper>
-        40%
-      </Group>
-      <Typography variant="subtitle" style={{marginTop: '8px'}}>Width</Typography>
-      <Group>
-        <SliderWrapper>
-          <Sliders />
-        </SliderWrapper>
-        12pt
-      </Group>
-    </ExpansionPanel>
-  );
-};
+const Shape: React.FunctionComponent = () => (
+  <ExpansionPanel
+    label={(
+      <Button shouldFitContainer align="left">
+        <Icon glyph="shape" style={{ marginRight: '10px' }} />
+        Shape
+      </Button>
+    )}
+  >
+    <Typography>Shape</Typography>
+    <SelectBox options={shapeOptions} style={{ marginRight: '10px' }} />
+    <SelectBox options={typeOptions} />
+    <ColorSelect />
+    <Typography variant="subtitle" style={{ marginTop: '8px' }}>Opacity</Typography>
+    <Group>
+      <SliderWrapper>
+        <Sliders />
+      </SliderWrapper>
+      40%
+    </Group>
+    <Typography variant="subtitle" style={{ marginTop: '8px' }}>Width</Typography>
+    <Group>
+      <SliderWrapper>
+        <Sliders />
+      </SliderWrapper>
+      12pt
+    </Group>
+  </ExpansionPanel>
+);
 
 export default Shape;

+ 10 - 10
components/Skeleton/index.tsx

@@ -9,17 +9,17 @@ export type Props = {
 };
 
 const Skeleton: React.FunctionComponent<Props> = ({
-  variant,
+  variant = 'text',
   height = 'auto',
   width = 'auto',
-}) => {
-  return (
-    <Element
-      variant={variant}
-      height={height}
-      width={width}
-    />
-  );
-};
+}: Props) => (
+  <Element
+    variant={variant}
+    style={{
+      height,
+      width,
+    }}
+  />
+);
 
 export default Skeleton;

+ 5 - 8
components/Skeleton/styled.ts

@@ -2,8 +2,6 @@ import styled, { css, keyframes } from 'styled-components';
 
 import { color } from '../../constants/style';
 
-import { Props } from './index';
-
 const animate = keyframes`
   0% {
     opacity: 1;
@@ -16,7 +14,7 @@ const animate = keyframes`
   }
 `;
 
-const shape = {
+const shape: {[index: string]: any} = {
   rect: '',
   text: css`
     margin-top: 8px;
@@ -25,8 +23,9 @@ const shape = {
     transform: translateZ(0) scale(1, 0.65);
     border-radius: 4px;
     text-indent: -999px;
-    &:empty:before: {
-      content: "&nbsp;";
+    
+    &:empty:before {
+      content: " ";
     }
   `,
   circle: css`
@@ -34,10 +33,8 @@ const shape = {
   `,
 };
 
-export const Element = styled('div')<Props>`
+export const Element = styled('div')<{variant: string}>`
   display: block;
-  height: ${props => props.height || 'auto'};
-  width: ${props => props.width || 'auto'};
   background-color: ${color.gray};
   animation: ${animate} 1.5s ease-in-out infinite;
   margin: 5px 0;

+ 15 - 13
components/Sliders/index.tsx

@@ -1,6 +1,10 @@
-import React, { useEffect, useState, useRef, useCallback } from 'react';
+import React, {
+  useEffect, useState, useRef, useCallback,
+} from 'react';
 
-import { Container, Wrapper, Rail, Track } from './styled';
+import {
+  Container, Wrapper, Rail, Track,
+} from './styled';
 
 type Props = {
   color?: 'primary' | 'secondary';
@@ -11,34 +15,32 @@ type Props = {
   onChange?: (value: number | number[]) => void;
 };
 
-const Sliders : React.FunctionComponent<Props> = ({
+const Sliders: React.FunctionComponent<Props> = ({
   defaultValue = 0,
   onChange,
-}) => {
+}: Props) => {
   const sliderRef = useRef<HTMLDivElement>(null);
   const [valueState, setValueState] = useState(defaultValue);
   const [isActive, setActive] = useState(false);
 
-  const parseValueToPercent = (value: number): number => {
-    return Math.floor(value * 100);
-  }
+  const parseValueToPercent = (value: number): number => Math.floor(value * 100);
 
-  const getFingerMoveValue = (event: MouseEvent | React.MouseEvent<HTMLElement>) => {
+  const getFingerMoveValue = (event: MouseEvent | React.MouseEvent<HTMLElement>): void => {
     const { current: slider } = sliderRef;
-  
+
     if (slider) {
       const { width, left } = slider.getBoundingClientRect();
       const value = (event.clientX - left) / width;
       let percent = parseValueToPercent(value);
-      
+
       if (percent <= 0) {
-        percent = 0
+        percent = 0;
       } else if (percent >= 100) {
-        percent = 100
+        percent = 100;
       }
 
       setValueState(percent);
-      onChange && onChange(percent);
+      if (onChange) onChange(percent);
     }
   };
 

+ 4 - 4
components/Sliders/styled.ts

@@ -14,14 +14,14 @@ export const Wrapper = styled.div`
   cursor: pointer;
 `;
 
-export const Rail = styled("div")<{track: number}>`
+export const Rail = styled('div')<{track: number}>`
   height: 10px;
   width: ${props => props.track}%;
   border-radius: 7px;
   background-color: ${color.primary};
 `;
 
-export const Track = styled("span")<{track: number; isActive: boolean}>`
+export const Track = styled('span')<{track: number; isActive: boolean}>`
   display: block;
   width: 20px;
   height: 20px;
@@ -35,9 +35,9 @@ export const Track = styled("span")<{track: number; isActive: boolean}>`
   border: 2px solid white;
   box-sizing: border-box;
 
-  ${props => props.isActive ? css`
+  ${props => (props.isActive ? css`
     box-shadow: 0px 0px 0px 8px rgba(144, 202, 249, 0.23);
-  ` : ''}
+  ` : '')}
 
   &:hover {
     box-shadow: 0px 0px 0px 8px rgba(144, 202, 249, 0.23);

+ 3 - 3
components/Tabs/index.tsx

@@ -14,10 +14,10 @@ type Props = {
 
 const Tabs: React.FunctionComponent<Props> = ({
   options,
-}) => {
+}: Props) => {
   const [selectedIndex, setSelect] = useState(0);
 
-  const handleClick = (index: number) => {
+  const handleClick = (index: number): void => {
     setSelect(index);
   };
 
@@ -29,7 +29,7 @@ const Tabs: React.FunctionComponent<Props> = ({
             <Btn
               key={ele.key}
               isActive={index === selectedIndex}
-              onClick={() => { handleClick(index); }}
+              onClick={(): void => { handleClick(index); }}
             >
               {ele.content}
             </Btn>

+ 2 - 2
components/Tabs/styled.ts

@@ -27,8 +27,8 @@ export const Btn = styled('button')<{isActive?: boolean}>`
   font-weight: bold;
   box-sizing: border-box;
 
-  ${props => props.isActive ? css`
+  ${props => (props.isActive ? css`
     background-color: ${color.primary};
     color: white;
-  ` : null}
+  ` : null)}
 `;

+ 12 - 29
components/TextField/index.tsx

@@ -18,46 +18,29 @@ type Props = {
 type Ref = any;
 
 const TextField = forwardRef<Ref, Props>(({
-  id = '',
-  name = '',
-  onChange = () => {},
-  onBlur = () => {},
-  defaultValue = '',
-  placeholder = '',
-  disabled = false,
-  error = false,
-  shouldFitContainer = false,
   variant = 'standard',
-}, ref) => {
-
-  const handleChange = (e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => {
-    if (!disabled) {
-      onChange(e.target.value);  
+  onChange,
+  disabled = false,
+  ...rest
+}: Props, ref) => {
+  const handleChange = (e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>): void => {
+    if (onChange && !disabled) {
+      onChange(e.target.value);
     }
   };
 
-  const transferProps = {
-    id,
-    name,
-    defaultValue,
-    placeholder,
-    onChange: handleChange,
-    onBlur,
-    disabled,
-    error,
-    shouldFitContainer,
-  }
-
   return (
     variant === 'standard' ? (
       <Input
         ref={ref}
-        {...transferProps}
-      />  
+        onChange={handleChange}
+        {...rest}
+      />
     ) : (
       <TextArea
         ref={ref}
-        {...transferProps}
+        onChange={handleChange}
+        {...rest}
       />
     )
   );

+ 8 - 9
components/TextField/styled.ts

@@ -17,30 +17,29 @@ const baseStyles = css`
   }
 `;
 
-export const Input = styled('input')<{error: boolean, shouldFitContainer: boolean}>`
+export const Input = styled('input')<{error?: boolean; shouldFitContainer?: boolean}>`
   ${baseStyles}
-  width: ${props => props.shouldFitContainer ? '100%' : 'auto'};
+  width: ${props => (props.shouldFitContainer ? '100%' : 'auto')};
 
-  ${props => props.error ? css`
+  ${props => (props.error ? css`
     border: 1.5px solid ${color.error};
   ` : css`
     :focus {
       border: 1.5px solid ${color.primary};
     }
-  `}
+  `)}
 `;
 
-export const TextArea = styled('textarea')<{error: boolean, shouldFitContainer: boolean}>`
+export const TextArea = styled('textarea')<{error?: boolean; shouldFitContainer?: boolean}>`
   ${baseStyles}
   height: 54px;
-  width: ${props => props.shouldFitContainer ? '100%' : 'auto'};
+  width: ${props => (props.shouldFitContainer ? '100%' : 'auto')};
 
-  ${props => props.error ? css`
+  ${props => (props.error ? css`
     border: 1.5px solid ${color.error};
   ` : css`
     :focus {
       border: 1.5px solid ${color.primary};
     }
-  `}
+  `)}
 `;
-

+ 50 - 0
components/TextTools/data.ts

@@ -0,0 +1,50 @@
+export const fontOptions = [
+  {
+    key: 'helvetica',
+    content: 'Helvetica',
+    value: '',
+  },
+  {
+    key: 'arial',
+    content: 'Arial',
+    value: '',
+  },
+];
+
+export const sizeOptions = [
+  {
+    key: 'size_12',
+    content: 12,
+    value: '',
+  },
+  {
+    key: 'size_14',
+    content: 14,
+    value: '',
+  },
+  {
+    key: 'size_18',
+    content: 18,
+    value: '',
+  },
+  {
+    key: 'size_24',
+    content: 24,
+    value: '',
+  },
+  {
+    key: 'size_36',
+    content: 36,
+    value: '',
+  },
+  {
+    key: 'size_48',
+    content: 48,
+    value: '',
+  },
+  {
+    key: 'size_64',
+    content: 64,
+    value: '',
+  },
+];

+ 59 - 108
components/TextTools/index.tsx

@@ -8,115 +8,66 @@ import Sliders from '../Sliders';
 import ColorSelect from '../ColorSelect';
 import SelectBox from '../SelectBox';
 
-import { Wrapper, Group, Item, SliderWrapper } from '../../global/toolStyled';
+import {
+  Wrapper, Group, Item, SliderWrapper,
+} from '../../global/toolStyled';
 
-const fontOptions = [
-  {
-    key: 'helvetica',
-    content: 'Helvetica',
-    value: '',
-  },
-  {
-    key: 'arial',
-    content: 'Arial',
-    value: '',
-  },
-];
+import { fontOptions, sizeOptions } from './data';
 
-const sizeOptions = [
-  {
-    key: 'size_12',
-    content: 12,
-    value: '',
-  },
-  {
-    key: 'size_14',
-    content: 14,
-    value: '',
-  },
-  {
-    key: 'size_18',
-    content: 18,
-    value: '',
-  },
-  {
-    key: 'size_24',
-    content: 24,
-    value: '',
-  },
-  {
-    key: 'size_36',
-    content: 36,
-    value: '',
-  },
-  {
-    key: 'size_48',
-    content: 48,
-    value: '',
-  },
-  {
-    key: 'size_64',
-    content: 64,
-    value: '',
-  },
-];
-
-const TextTools = () => {
-  return (
-    <ExpansionPanel
-      label={
-        <Button shouldFitContainer align="left">
-          <Icon glyph="text" style={{marginRight: '10px'}}/>
-          Text
-        </Button>
-      }
-    >
-      <Wrapper>
-        <Typography variant="subtitle" style={{marginTop: '8px'}}>Fonts</Typography>
-        <Group>
-          <SelectBox options={fontOptions} />
-          <Item size="small">
-            <Icon glyph="bold" />
-          </Item>
-          <Item size="small">
-            <Icon glyph="italic" />
-          </Item>
-        </Group>
-      </Wrapper>
-      <Wrapper width="40%">
-        <Typography variant="subtitle" style={{marginTop: '8px'}}>Size</Typography>
-        <Group>
-          <SelectBox options={sizeOptions} />
-        </Group>
-      </Wrapper>
-      <Wrapper width="60%">
-        <Typography variant="subtitle" style={{marginTop: '8px'}}>Align</Typography>
-        <Group>
-          <Item size="small">
-            <Icon glyph="align-left" />
-          </Item>
-          <Item size="small">
-            <Icon glyph="align-center" />
-          </Item>
-          <Item size="small">
-            <Icon glyph="align-right" />
-          </Item>
-        </Group>
-      </Wrapper>
-      <Wrapper>
-        <ColorSelect />
-      </Wrapper>
-      <Wrapper>
-        <Typography variant="subtitle" style={{marginTop: '8px'}}>Opacity</Typography>
-        <Group>
-          <SliderWrapper>
-            <Sliders />
-          </SliderWrapper>
-          40%
-        </Group>
-      </Wrapper>
-    </ExpansionPanel>
-  );
-};
+const TextTools: React.FunctionComponent = () => (
+  <ExpansionPanel
+    label={(
+      <Button shouldFitContainer align="left">
+        <Icon glyph="text" style={{ marginRight: '10px' }} />
+        Text
+      </Button>
+    )}
+  >
+    <Wrapper>
+      <Typography variant="subtitle" style={{ marginTop: '8px' }}>Fonts</Typography>
+      <Group>
+        <SelectBox options={fontOptions} />
+        <Item size="small">
+          <Icon glyph="bold" />
+        </Item>
+        <Item size="small">
+          <Icon glyph="italic" />
+        </Item>
+      </Group>
+    </Wrapper>
+    <Wrapper width="40%">
+      <Typography variant="subtitle" style={{ marginTop: '8px' }}>Size</Typography>
+      <Group>
+        <SelectBox options={sizeOptions} />
+      </Group>
+    </Wrapper>
+    <Wrapper width="60%">
+      <Typography variant="subtitle" style={{ marginTop: '8px' }}>Align</Typography>
+      <Group>
+        <Item size="small">
+          <Icon glyph="align-left" />
+        </Item>
+        <Item size="small">
+          <Icon glyph="align-center" />
+        </Item>
+        <Item size="small">
+          <Icon glyph="align-right" />
+        </Item>
+      </Group>
+    </Wrapper>
+    <Wrapper>
+      <ColorSelect />
+    </Wrapper>
+    <Wrapper>
+      <Typography variant="subtitle" style={{ marginTop: '8px' }}>Opacity</Typography>
+      <Group>
+        <SliderWrapper>
+          <Sliders />
+        </SliderWrapper>
+        40%
+      </Group>
+    </Wrapper>
+  </ExpansionPanel>
+);
 
 export default TextTools;

+ 16 - 11
components/Thumbnail/index.tsx

@@ -2,7 +2,9 @@ import React, { useEffect, useState } from 'react';
 
 import { scrollIntoView } from '../../helpers/utility';
 
-import { Wrapper, PageNum, Img, Loading } from './styled';
+import {
+  Wrapper, PageNum, Img, Loading,
+} from './styled';
 
 type Props = {
   pageNum: number;
@@ -14,21 +16,24 @@ const index: React.FunctionComponent<Props> = ({
   pageNum,
   getPdfImage,
   renderingState,
-}) => {
+}: Props) => {
   const [dataUrl, setDataUrl] = useState('');
 
-  const getDataUrl = async () => {
-    const _dataUrl = await getPdfImage(pageNum);
-    setDataUrl(_dataUrl);
-  }
+  const getDataUrl = async (): Promise<any> => {
+    const imageDataUrl = await getPdfImage(pageNum);
+    setDataUrl(imageDataUrl);
+  };
 
-  const onClick = () => {
-    const ele : HTMLElement = document.getElementById(`page_${pageNum}`)!;
-    scrollIntoView(ele);
-  }
+  const onClick = (): void => {
+    const ele: HTMLElement | null = document.getElementById(`page_${pageNum}`);
+
+    if (ele) {
+      scrollIntoView(ele);
+    }
+  };
 
   useEffect(() => {
-    if(renderingState === 'RENDERING') {
+    if (renderingState === 'RENDERING') {
       getDataUrl();
     }
   }, [renderingState]);

+ 24 - 17
components/ThumbnailViewer/index.tsx

@@ -3,11 +3,12 @@ import React, { useEffect, useState, useRef } from 'react';
 import Icon from '../Icon';
 import Drawer from '../Drawer';
 import Thumbnail from '../Thumbnail';
-import { Wrapper, Head, Body, IconWrapper } from '../../global/sidebarStyled'
 import { ScrollStateType } from '../../constants/type';
-
 import { watchScroll, scrollIntoView } from '../../helpers/utility';
 
+import {
+  Wrapper, Head, Body, IconWrapper,
+} from '../../global/sidebarStyled';
 import { ThumbnailsWrapper } from './styled';
 
 type Props = {
@@ -18,45 +19,51 @@ type Props = {
   getPdfImage: (page: number) => Promise<string>;
 };
 
-const Thumbnails : React.FunctionComponent<Props> = ({
+const Thumbnails: React.FunctionComponent<Props> = ({
   isActive = false,
   close,
   currentPage,
   totalPage,
   getPdfImage,
-}) => {
+}: Props) => {
   const containerRef = useRef<HTMLDivElement>(null);
   const [scrollIndex, setScrollIndex] = useState(currentPage);
   const [elements, setElement] = useState<React.ReactNode[]>([]);
-  
-  const scrollUpdate = (state: ScrollStateType) => {
+
+  const scrollUpdate = (state: ScrollStateType): void => {
     const height = 220;
     const index = Math.round((state.lastY + height) / height);
     setScrollIndex(index);
   };
 
-  const createThumbnails = () => {
+  const createThumbnails = (): void => {
     const eleContent: React.ReactNode[] = [];
-    for(let i = 1; i <= totalPage; i++) {
+    for (let i = 1; i <= totalPage; i += 1) {
       const component = (
         <Thumbnail
           key={`thumbnail_${i}`}
           pageNum={i}
           getPdfImage={getPdfImage}
-          renderingState={[1,2,3,4,5].includes(i) ? 'RENDERING' : 'LOADING'}
+          renderingState={[1, 2, 3, 4, 5].includes(i) ? 'RENDERING' : 'LOADING'}
         />
       );
       eleContent.push(component);
     }
     setElement(eleContent);
-  }
-  
-  const updateThumbnails = () => {
-    const renderingIndexQueue = [scrollIndex - 1 ,scrollIndex, scrollIndex + 1, scrollIndex + 2, scrollIndex + 3];
+  };
+
+  const updateThumbnails = (): void => {
+    const renderingIndexQueue = [
+      scrollIndex - 1,
+      scrollIndex,
+      scrollIndex + 1,
+      scrollIndex + 2,
+      scrollIndex + 3,
+    ];
     let index = scrollIndex - 5;
     const end = scrollIndex + 5;
 
-    while (true) {
+    while (index >= 0) {
       if (elements[index]) {
         const pageNum = index + 1;
 
@@ -67,7 +74,7 @@ const Thumbnails : React.FunctionComponent<Props> = ({
             getPdfImage={getPdfImage}
             renderingState={renderingIndexQueue.includes(pageNum) ? 'RENDERING' : 'LOADING'}
           />
-        )
+        );
       }
 
       index += 1;
@@ -84,7 +91,7 @@ const Thumbnails : React.FunctionComponent<Props> = ({
       watchScroll(containerRef.current, scrollUpdate);
     }
   }, [containerRef]);
-  
+
   useEffect(() => {
     if (isActive && !elements.length) {
       createThumbnails();
@@ -97,7 +104,7 @@ const Thumbnails : React.FunctionComponent<Props> = ({
 
   useEffect(() => {
     if (isActive && elements.length) {
-      const ele : HTMLElement = document.getElementById(`thumbnail_${currentPage}`)!;
+      const ele: HTMLElement = document.getElementById(`thumbnail_${currentPage}`) as HTMLElement;
       scrollIntoView(ele);
     }
   }, [currentPage, isActive]);

+ 1 - 1
components/ThumbnailViewer/styled.ts

@@ -3,4 +3,4 @@ import styled from 'styled-components';
 export const ThumbnailsWrapper = styled.div`
   display: inline-flex;
   flex-direction: column;
-`;
+`;

+ 7 - 9
components/Toasts/index.tsx

@@ -8,17 +8,15 @@ type Props = {
   action?: React.ReactNode;
 };
 
-const Toasts : React.FunctionComponent<Props> = ({
+const Toasts: React.FunctionComponent<Props> = ({
   message,
   appearance = 'default',
   action,
-}) => {
-  return (
-    <Wrapper appearance={appearance}>
-      <Message>{message}</Message>
-      {action ? <Action>{action}</Action> : null}
-    </Wrapper>
-  );
-};
+}: Props) => (
+  <Wrapper appearance={appearance}>
+    <Message>{message}</Message>
+    {action ? <Action>{action}</Action> : null}
+  </Wrapper>
+);
 
 export default Toasts;

+ 2 - 2
components/Toasts/styled.ts

@@ -19,7 +19,7 @@ const staticStyles = css`
   box-shadow: 0px 3px 5px -1px rgba(0,0,0,0.2), 0px 4px 12px 0px rgba(0,0,0,0.14), 0px 1px 8px 0px rgba(0,0,0,0.12);
 `;
 
-const theme: {[index: string]:any} = {
+const theme: {[index: string]: any} = {
   default: css`
     color: ${color.black87};
     background-color: white;
@@ -43,7 +43,7 @@ export const Wrapper = styled('div')<{appearance: string}>`
   ${props => theme[props.appearance]}
 `;
 
-export const Message =styled.div`
+export const Message = styled.div`
   padding: 8px 0;
 `;
 

+ 34 - 32
components/Toolbar/data.ts

@@ -1,32 +1,34 @@
-export const scaleOptions = [
-  {
-    key: 'fit',
-    content: 'Fit',
-    value: 'fit',
-  },
-  {
-    key: '50',
-    content: '50 %',
-    value: 50,
-  },
-  {
-    key: '100',
-    content: '100 %',
-    value: 100,
-  },
-  {
-    key: '150',
-    content: '150 %',
-    value: 150,
-  },
-  {
-    key: '200',
-    content: '200 %',
-    value: 200,
-  },
-  {
-    key: '250',
-    content: '250 %',
-    value: 250,
-  },
-];
+export default {
+  scaleOptions: [
+    {
+      key: 'fit',
+      content: 'Fit',
+      value: 'fit',
+    },
+    {
+      key: '50',
+      content: '50 %',
+      value: 50,
+    },
+    {
+      key: '100',
+      content: '100 %',
+      value: 100,
+    },
+    {
+      key: '150',
+      content: '150 %',
+      value: 150,
+    },
+    {
+      key: '200',
+      content: '200 %',
+      value: 200,
+    },
+    {
+      key: '250',
+      content: '250 %',
+      value: 250,
+    },
+  ],
+};

+ 15 - 15
components/Toolbar/index.tsx

@@ -8,7 +8,7 @@ import { SelectOptionType, ViewportType } from '../../constants/type';
 import { scaleCheck } from '../../helpers/utility';
 
 import { Wrapper } from './styled';
-import { scaleOptions } from './data';
+import data from './data';
 
 type Props = {
   totalPage: number;
@@ -30,18 +30,18 @@ const Toolbar: React.FunctionComponent<Props> = ({
   scale,
   rotation,
   viewport,
-}) => {
-  const handleClockwiseRotation = () => {
+}: Props) => {
+  const handleClockwiseRotation = (): void => {
     const r = rotation + 90;
     changeRotate(r);
   };
 
-  const handleCounterclockwiseRotation = () => {
+  const handleCounterclockwiseRotation = (): void => {
     const r = rotation - 90;
     changeRotate(r);
-  }
+  };
 
-  const handleScaleSelect = async (selected: SelectOptionType) => {
+  const handleScaleSelect = async (selected: SelectOptionType): Promise<any> => {
     if (selected.value === 'fit') {
       const screenHeight = window.screen.height - 200;
       const originPdfHeight = viewport.height / scale;
@@ -50,13 +50,13 @@ const Toolbar: React.FunctionComponent<Props> = ({
     } else {
       changeScale(scaleCheck(selected.value as number));
     }
-  }
+  };
 
-  const handleZoomIn = () => {
+  const handleZoomIn = (): void => {
     changeScale(scaleCheck(scale * 100 + 10));
   };
 
-  const handleZoomOut = () => {
+  const handleZoomOut = (): void => {
     changeScale(scaleCheck(scale * 100 - 10));
   };
 
@@ -64,13 +64,13 @@ const Toolbar: React.FunctionComponent<Props> = ({
     <Wrapper>
       <Pagination totalPage={totalPage} currentPage={currentPage} onChange={setCurrentPage} />
       <Divider />
-      <Icon glyph="hand" style={{width: '30px'}} />
-      <Icon glyph="zoom-in" style={{width: '30px'}} onClick={handleZoomIn} />
-      <Icon glyph="zoom-out" style={{width: '30px'}} onClick={handleZoomOut} />
-      <SelectBox options={scaleOptions} width="94px" useInput isDivide onChange={handleScaleSelect} defaultValue={`${Math.round(scale * 100)} %`} />
+      <Icon glyph="hand" style={{ width: '30px' }} />
+      <Icon glyph="zoom-in" style={{ width: '30px' }} onClick={handleZoomIn} />
+      <Icon glyph="zoom-out" style={{ width: '30px' }} onClick={handleZoomOut} />
+      <SelectBox options={data.scaleOptions} width="94px" useInput isDivide onChange={handleScaleSelect} defaultValue={`${Math.round(scale * 100)} %`} />
       <Divider />
-      <Icon glyph="rotate-left" style={{width: '30px'}} onClick={handleCounterclockwiseRotation} />
-      <Icon glyph="rotate-right" style={{width: '30px'}} onClick={handleClockwiseRotation} />
+      <Icon glyph="rotate-left" style={{ width: '30px' }} onClick={handleCounterclockwiseRotation} />
+      <Icon glyph="rotate-right" style={{ width: '30px' }} onClick={handleClockwiseRotation} />
     </Wrapper>
   );
 };

+ 6 - 4
components/Tooltip/index.tsx

@@ -10,14 +10,14 @@ type Props = {
   content: React.ReactNode;
 };
 
-const Tooltip : React.FunctionComponent<Props> = ({
+const Tooltip: React.FunctionComponent<Props> = ({
   anchor = 'left',
   children,
   content,
-}) => (
+}: Props) => (
   <Manager>
     <Reference>
-      {({ ref }) => (
+      {({ ref }): React.ReactElement => (
         <TargetContainer ref={ref}>
           {children}
         </TargetContainer>
@@ -25,7 +25,9 @@ const Tooltip : React.FunctionComponent<Props> = ({
     </Reference>
     <Portal>
       <Popper placement={anchor}>
-        {({ ref, style, placement, arrowProps }) => (
+        {({
+          ref, style, placement, arrowProps,
+        }): React.ReactElement => (
           <TooltipContainer ref={ref} style={style} data-placement={placement}>
             {content}
             <Arrow data-placement={placement} ref={arrowProps.ref} style={arrowProps.style} />

+ 1 - 1
components/Tooltip/styled.ts

@@ -6,7 +6,7 @@ export const TargetContainer = styled.div`
   margin-left: 100px;
 `;
 
-export const TooltipContainer = styled('div')<{}>`
+export const TooltipContainer = styled.div`
   z-index: 1000;
   color: #fff;
   border-radius: 2px;

+ 6 - 7
components/Typography/index.tsx

@@ -11,14 +11,14 @@ type Props = {
 
 const Typography: React.FunctionComponent<Props> = ({
   variant = 'title',
-  light = false,
   children,
-  style = {},
-}) => {
-  const getComponent = () => {
+  ...rest
+}: Props) => {
+  const getComponent = (): React.FunctionComponent => {
     if (variant === 'title') {
       return Title;
-    } else if (variant === 'subtitle') {
+    }
+    if (variant === 'subtitle') {
       return Subtitle;
     }
     return Body;
@@ -27,8 +27,7 @@ const Typography: React.FunctionComponent<Props> = ({
 
   return (
     <Component
-      light={light}
-      style={style}
+      {...rest}
     >
       {children}
     </Component>

+ 5 - 4
components/Typography/styled.ts

@@ -4,20 +4,21 @@ import { color } from '../../constants/style';
 
 export const Title = styled('p')<{light: boolean}>`
   font-size: 16px;
-  color: ${props => props.light ? color.black38 : '#000000' };
+  color: ${props => (props.light ? color.black38 : '#000000')};
   margin: 5px;
   white-space: nowrap;
 `;
 
 export const Subtitle = styled('p')<{light: boolean}>`
   font-size: 14px;
-  color: ${props => props.light ? color.black38 : '#000000' };
+  color: ${props => (props.light ? color.black38 : '#000000')};
   margin: 5px;
   white-space: nowrap;
+  text-align: left;
 `;
 
 export const Body = styled('p')<{light: boolean}>`
   font-size: 14px;
-  color: ${props => props.light ? color.black38 : '#000000' };
+  color: ${props => (props.light ? color.black38 : '#000000')};
   margin: 5px;
-`;
+`;

+ 15 - 15
components/Viewer/index.tsx

@@ -21,25 +21,25 @@ const Viewer = forwardRef<Ref, Props>(({
   viewport,
   pdf,
   rotation,
-}, ref) => {
+}: Props, ref) => {
   const [elements, setElement] = useState<React.ReactNode[]>([]);
 
-  const getPdfPage = async (pageNum: number) => {
+  const getPdfPage = async (pageNum: number): Promise<any> => {
     const page = await pdf.getPage(pageNum);
     return page;
   };
 
-  const createPages = () => {
+  const createPages = (): void => {
     const pagesContent: React.ReactNode[] = [];
 
-    for(let i = 1; i <= totalPage; i++) {
+    for (let i = 1; i <= totalPage; i += 1) {
       const component = (
         <PageView
           key={`page-${i}`}
           pageNum={i}
           renderingState={[1, 2, 3].includes(i) ? 'RENDERING' : 'LOADING'}
           viewport={viewport}
-          getPage={() => getPdfPage(i) }
+          getPage={(): Promise<any> => getPdfPage(i)}
           rotation={rotation}
         />
       );
@@ -49,12 +49,12 @@ const Viewer = forwardRef<Ref, Props>(({
     setElement(pagesContent);
   };
 
-  const updatePages = () => {
-    const renderingIndexQueue = [currentPage - 1 ,currentPage, currentPage + 1];
+  const updatePages = (): void => {
+    const renderingIndexQueue = [currentPage - 1, currentPage, currentPage + 1];
     let index = currentPage - 2;
     const end = currentPage + 2;
 
-    while (true) {
+    while (index >= 0) {
       if (elements[index]) {
         const pageNum = index + 1;
 
@@ -64,10 +64,10 @@ const Viewer = forwardRef<Ref, Props>(({
             pageNum={pageNum}
             renderingState={renderingIndexQueue.includes(pageNum) ? 'RENDERING' : 'LOADING'}
             viewport={viewport}
-            getPage={() => getPdfPage(pageNum)}
+            getPage={(): Promise<any> => getPdfPage(pageNum)}
             rotation={rotation}
           />
-        )
+        );
       }
 
       index += 1;
@@ -79,11 +79,11 @@ const Viewer = forwardRef<Ref, Props>(({
     }
   };
 
-  const changePdfContainerScale = () => {
+  const changePdfContainerScale = (): void => {
     if (elements.length) {
-      for(let i = 1; i <= totalPage; i++) {
+      for (let i = 1; i <= totalPage; i += 1) {
         const ele: HTMLDivElement = document.getElementById(`page_${i}`) as HTMLDivElement;
-        ele.style.width =  `${viewport.width}px`;
+        ele.style.width = `${viewport.width}px`;
         ele.style.height = `${viewport.height}px`;
 
         if (i === currentPage) {
@@ -92,7 +92,7 @@ const Viewer = forwardRef<Ref, Props>(({
         }
       }
     }
-  }
+  };
 
   useEffect(() => {
     createPages();
@@ -108,7 +108,7 @@ const Viewer = forwardRef<Ref, Props>(({
 
   return (
     <Container ref={ref}>
-      <Wrapper width={rotation / 90 % 2 === 1 ? viewport.height : viewport.width}>
+      <Wrapper width={(rotation / 90) % 2 === 1 ? viewport.height : viewport.width}>
         {elements}
       </Wrapper>
     </Container>

+ 71 - 75
components/Watermark/index.tsx

@@ -11,7 +11,9 @@ import ColorSelect from '../ColorSelect';
 import TextField from '../TextField';
 
 import { BtnWrapper, ContentWrapper } from './styled';
-import { Wrapper, Head, Body, Footer, IconWrapper } from '../../global/sidebarStyled';
+import {
+  Wrapper, Head, Body, Footer, IconWrapper,
+} from '../../global/sidebarStyled';
 import { Group, SliderWrapper } from '../../global/toolStyled';
 
 type Props = {
@@ -19,85 +21,79 @@ type Props = {
   isActive: boolean;
 };
 
-const TextContent = () => {
-  return (
-    <>
-      <ContentWrapper>
-        <Typography variant="subtitle">Content</Typography>
-      </ContentWrapper>
-      <TextField variant="multiline" shouldFitContainer />
-    </>
-  );
-}
-
-const ImageContent = () => {
-  return (
+const TextContent = (): React.ReactElement => (
+  <>
     <ContentWrapper>
-      <Icon glyph="add-image" />
-      <Button appearance="link" style={{marginLeft: '10px'}}>Select Image</Button>
+      <Typography variant="subtitle">Content</Typography>
     </ContentWrapper>
-  );
-}
+    <TextField variant="multiline" shouldFitContainer />
+  </>
+);
+
+const ImageContent = (): React.ReactElement => (
+  <ContentWrapper>
+    <Icon glyph="add-image" />
+    <Button appearance="link" style={{ marginLeft: '10px' }}>Select Image</Button>
+  </ContentWrapper>
+);
 
 const Watermark: React.FunctionComponent<Props> = ({
   onClick,
   isActive,
-}) => {
-  return (
-    <>
-      <BtnWrapper>
-        <Button shouldFitContainer align="left" onClick={onClick}>
-          <Icon glyph="watermark" style={{marginRight: '10px'}} />
-          Watermark
-        </Button>
-      </BtnWrapper>
-      <Drawer open={isActive} anchor="left">
-        <Wrapper>
-          <Head>
-            <IconWrapper>
-              <Icon glyph="left-back" onClick={onClick} />
-            </IconWrapper>
-            <Typography light>Watermark</Typography>
-          </Head>
-          <Body>
-            <Typography variant="subtitle">Type</Typography>
-            <Tabs
-              options={[
-                {
-                  key: 'text',
-                  content: 'Text',
-                  child: <TextContent />,
-                },
-                {
-                  key: 'image',
-                  content: 'Image',
-                  child: <ImageContent />,
-                }
-              ]}
-            />
-            <Divider orientation="horizontal" style={{ margin: '20px 0' }} />
-            <ColorSelect />
-            <Typography variant="subtitle">Opacity</Typography>
-            <Group>
-              <SliderWrapper>
-                <Sliders />
-              </SliderWrapper>
-              40%
-            </Group>
-            <Divider orientation="horizontal" style={{ margin: '20px 0' }} />
-            <Group>
-              <Typography variant="subtitle">Page Range</Typography>
-              <Button appearance="primary-hollow" style={{width: '50%'}}>All Pages</Button>
-            </Group>
-          </Body>
-          <Footer>
-            <Button appearance="primary">Save</Button>
-            <Button appearance="danger-link">Remove watermark</Button>
-          </Footer>
-        </Wrapper>
-      </Drawer>
-    </>
-  );
-};
+}: Props) => (
+  <>
+    <BtnWrapper>
+      <Button shouldFitContainer align="left" onClick={onClick}>
+        <Icon glyph="watermark" style={{ marginRight: '10px' }} />
+        Watermark
+      </Button>
+    </BtnWrapper>
+    <Drawer open={isActive} anchor="left">
+      <Wrapper>
+        <Head>
+          <IconWrapper>
+            <Icon glyph="left-back" onClick={onClick} />
+          </IconWrapper>
+          <Typography light>Watermark</Typography>
+        </Head>
+        <Body>
+          <Typography variant="subtitle">Type</Typography>
+          <Tabs
+            options={[
+              {
+                key: 'text',
+                content: 'Text',
+                child: <TextContent />,
+              },
+              {
+                key: 'image',
+                content: 'Image',
+                child: <ImageContent />,
+              },
+            ]}
+          />
+          <Divider orientation="horizontal" style={{ margin: '20px 0' }} />
+          <ColorSelect />
+          <Typography variant="subtitle">Opacity</Typography>
+          <Group>
+            <SliderWrapper>
+              <Sliders />
+            </SliderWrapper>
+            40%
+          </Group>
+          <Divider orientation="horizontal" style={{ margin: '20px 0' }} />
+          <Group>
+            <Typography variant="subtitle">Page Range</Typography>
+            <Button appearance="primary-hollow" style={{ width: '50%' }}>All Pages</Button>
+          </Group>
+        </Body>
+        <Footer>
+          <Button appearance="primary">Save</Button>
+          <Button appearance="danger-link">Remove watermark</Button>
+        </Footer>
+      </Wrapper>
+    </Drawer>
+  </>
+);
 
 export default Watermark;

+ 1 - 1
components/Watermark/styled.ts

@@ -7,4 +7,4 @@ export const BtnWrapper = styled.div`
 export const ContentWrapper = styled.div`
   margin-top: 20px;
   display: flex;
-`;
+`;

+ 4 - 4
config/index.js

@@ -1,17 +1,17 @@
-let HOST = 'http://localhost:3000';
+let API_HOST = 'http://localhost:3000';
 
 switch (process.env.NODE_ENV) {
   case 'production':
-    HOST = 'http://localhost:3000';
+    API_HOST = '';
     break;
   case 'preparing':
   case 'test':
-    HOST = 'http://localhost:3000';
+    API_HOST = 'http://localhost:3000';
     break;
   default:
     break;
 }
 
 module.exports = {
-  HOST,
+  API_HOST,
 };

+ 1 - 1
constants/style.ts

@@ -7,7 +7,7 @@ export const mediaRule = {
   desktop: '1440px',
 };
 
-export const color: {[index: string]:any} = {
+export const color: {[index: string]: any} = {
   primary: '#586af2',
   'light-primary': 'rgba(88, 106, 242, 0.6)',
   secondary: '#2d3e4e',

+ 5 - 5
containers/Navbar.tsx

@@ -8,21 +8,21 @@ import Search from '../components/Search';
 import Annotations from '../components/Annotations';
 import Thumbnails from './Thumbnails';
 
-const Navbar = () => {
+const Navbar: React.FunctionComponent = () => {
   const [{ navbarState }, dispatch] = useStore();
   const { switchNavbar } = useActions(dispatch);
 
-  const onClick = (state: string) => {
+  const onClick = (state: string): void => {
     if (state === navbarState) {
-      switchNavbar('');  
+      switchNavbar('');
     } else {
       switchNavbar(state);
     }
   };
 
-  const transferProps = (role: string) => ({
+  const transferProps = (role: string): any => ({
     isActive: navbarState === role,
-    close: () => { onClick(''); },
+    close: (): void => { onClick(''); },
   });
 
   return (

+ 2 - 2
containers/Placeholder.tsx

@@ -6,7 +6,7 @@ import useStore from '../store';
 import { delay } from '../helpers/time';
 
 const Placeholder: React.FunctionComponent = () => {
-  const [{progress}] = useStore();
+  const [{ progress }] = useStore();
   const [done, setDone] = useState(false);
 
   useEffect(() => {
@@ -16,7 +16,7 @@ const Placeholder: React.FunctionComponent = () => {
   }, []);
 
   return (
-    progress.loaded <= progress.total || !done ? (
+    progress.loaded < progress.total || !done ? (
       <PdfSkeleton />
     ) : (
       null

+ 8 - 8
containers/Sidebar.tsx

@@ -5,19 +5,19 @@ import Typography from '../components/Typography';
 import Icon from '../components/Icon';
 import MarkupTools from '../components/MarkupTools';
 import CreateForm from '../components/CreateForm';
-import Watermark from '../containers/Watermark';
+import Watermark from './Watermark';
 
 import useActions from '../actions';
 import useStore from '../store';
 
 import { BtnWrapper } from '../global/toolStyled';
 import { SidebarWrapper } from '../global/otherStyled';
- 
-const Sidebar = () => {
+
+const Sidebar: React.FunctionComponent = () => {
   const [{ sidebarState }, dispatch] = useStore();
   const { switchSidebar } = useActions(dispatch);
 
-  const onClick = (state: string) => {
+  const onClick = (state: string): void => {
     if (state === sidebarState) {
       switchSidebar('');
     } else {
@@ -28,16 +28,16 @@ const Sidebar = () => {
   const transferProps = {
     onClick,
     sidebarState,
-  }
+  };
 
   return (
     <SidebarWrapper>
-      <Typography light style={{marginLeft: '30px', marginTop: '46px'}}>Main Menu</Typography>
+      <Typography light style={{ marginLeft: '30px', marginTop: '46px' }}>Main Menu</Typography>
       <MarkupTools {...transferProps} />
       <CreateForm {...transferProps} />
       <BtnWrapper>
-        <Button shouldFitContainer align="left" onClick={() => { onClick('add-image'); }}>
-          <Icon glyph="add-image" style={{marginRight: '10px'}}/>
+        <Button shouldFitContainer align="left" onClick={(): void => { onClick('add-image'); }}>
+          <Icon glyph="add-image" style={{ marginRight: '10px' }} />
           Add Image
         </Button>
       </BtnWrapper>

+ 8 - 6
containers/Thumbnails.tsx

@@ -5,16 +5,18 @@ import ThumbnailsComponent from '../components/ThumbnailViewer';
 import useActions from '../actions';
 import useStore from '../store';
 
-const Thumbnails = () => {
-  const [{pdf, totalPage, currentPage, navbarState, viewport}, dispatch] = useStore();
+const Thumbnails: React.FunctionComponent = () => {
+  const [{
+    pdf, totalPage, currentPage, navbarState, viewport,
+  }, dispatch] = useStore();
   const { switchNavbar } = useActions(dispatch);
 
-  const getPdfImage = async (pageNum: number) => {
+  const getPdfImage = async (pageNum: number): Promise<any> => {
     let dataUrl = '';
 
     const page = await pdf.getPage(pageNum);
     const canvas = document.createElement('canvas');
-    const context: CanvasRenderingContext2D = canvas.getContext('2d')!;
+    const context: CanvasRenderingContext2D = canvas.getContext('2d') as CanvasRenderingContext2D;
     canvas.height = viewport.height;
     canvas.width = viewport.width;
 
@@ -26,7 +28,7 @@ const Thumbnails = () => {
 
     await renderTask.promise;
     dataUrl = canvas.toDataURL();
-    canvas.remove;
+    canvas.remove();
 
     return dataUrl;
   };
@@ -38,7 +40,7 @@ const Thumbnails = () => {
         totalPage={totalPage}
         currentPage={currentPage}
         isActive={navbarState === 'thumbnails'}
-        close={() => { switchNavbar(''); }}
+        close={(): void => { switchNavbar(''); }}
       />
     )
   );

+ 10 - 8
containers/Toolbar.tsx

@@ -7,23 +7,25 @@ import useStore from '../store';
 
 import { scrollIntoView } from '../helpers/utility';
 
-const Toolbar = () => {
-  const [{totalPage, currentPage, scale, rotation, viewport}, dispatch] = useStore();
-  const { setCurrentPage, changeScale, changeRotate } = useActions(dispatch);
+const Toolbar: React.FunctionComponent = () => {
+  const [{
+    totalPage, currentPage, scale, rotation, viewport,
+  }, dispatch] = useStore();
+  const { setCurrentPage: setCurrentPageAction, changeScale, changeRotate } = useActions(dispatch);
 
-  const _setCurrentPage = (num: number) => {
+  const setCurrentPage = (num: number): void => {
     if (num > 0) {
-      const ele: HTMLElement = document.getElementById(`page_${num}`)!;
+      const ele: HTMLElement = document.getElementById(`page_${num}`) as HTMLElement;
       scrollIntoView(ele);
     }
-    setCurrentPage(num);
-  }
+    setCurrentPageAction(num);
+  };
 
   return (
     <ToolbarComponent
       totalPage={totalPage}
       currentPage={currentPage}
-      setCurrentPage={_setCurrentPage}
+      setCurrentPage={setCurrentPage}
       changeScale={changeScale}
       changeRotate={changeRotate}
       scale={scale}

+ 6 - 6
containers/Watermark.tsx

@@ -2,19 +2,19 @@ import React, { useState } from 'react';
 
 import WatermarkComponent from '../components/Watermark';
 
-import useActions from '../actions'
+import useActions from '../actions';
 import useStore from '../store';
 
-const Watermark = () => {
+const Watermark: React.FunctionComponent = () => {
   const [isActive, setActive] = useState(false);
-  const [{}, dispatch] = useStore();
+  const [, dispatch] = useStore();
   const { switchSidebar } = useActions(dispatch);
 
-  const handleClick = () => {
+  const handleClick = (): void => {
     setActive(!isActive);
     switchSidebar(!isActive ? 'watermark' : '');
-  }
-  
+  };
+
   return (
     <WatermarkComponent
       isActive={isActive}

+ 2 - 2
global/toolStyled.ts

@@ -18,8 +18,8 @@ export const Group = styled.div`
 `;
 
 export const Item = styled('div')<{size?: string}>`
-  width: ${props => props.size === 'small' ? '30px' : '40px'};
-  height: ${props => props.size === 'small' ? '30px' : '40px'};
+  width: ${props => (props.size === 'small' ? '30px' : '40px')};
+  height: ${props => (props.size === 'small' ? '30px' : '40px')};
   border-radius: 4px;
   display: flex;
   justify-content: center;

+ 2 - 2
helpers/dom.ts

@@ -1,5 +1,5 @@
-export const canUseDOM = () : boolean => (
-  typeof window !== 'undefined' && window.document ? true : false
+export const canUseDOM = (): boolean => (
+  !!(typeof window !== 'undefined' && window.document)
 );
 
 export default canUseDOM;

+ 4 - 4
helpers/pdf.ts

@@ -10,7 +10,7 @@ const CMAP_PACKED = true;
 
 pdfjs.GlobalWorkerOptions.workerSrc = pdfjsWorker;
 
-export const fetchPdf = async (src: string, cb: (progress: ProgressType) => void) => {
+export const fetchPdf = async (src: string, cb: (progress: ProgressType) => void): Promise<any> => {
   const loadingTask = pdfjs.getDocument({
     url: src,
     cMapUrl: CMAP_URL,
@@ -18,7 +18,7 @@ export const fetchPdf = async (src: string, cb: (progress: ProgressType) => void
   });
 
   if (cb) {
-    loadingTask.onProgress = (progress: ProgressType) => {
+    loadingTask.onProgress = (progress: ProgressType): void => {
       cb(progress);
     };
   }
@@ -35,12 +35,12 @@ export const renderPdfPage = async ({
   rootEle: HTMLDivElement;
   page: any;
   viewport: ViewportType;
-}) => {
+}): Promise<any> => {
   if (rootEle) {
     const canvas: HTMLCanvasElement = rootEle.querySelectorAll('canvas')[0] as HTMLCanvasElement;
 
     if (canvas) {
-      const context: CanvasRenderingContext2D = canvas.getContext('2d')!;
+      const context: CanvasRenderingContext2D = canvas.getContext('2d') as CanvasRenderingContext2D;
       canvas.height = viewport.height;
       canvas.width = viewport.width;
 

+ 5 - 3
helpers/time.ts

@@ -1,5 +1,7 @@
-export const delay = (ms: number) => (
-  new Promise((resolve) =>{
-    setTimeout(() => { resolve() }, ms)
+export const delay = (ms: number): Promise<any> => (
+  new Promise((resolve) => {
+    setTimeout(() => { resolve(); }, ms);
   })
 );
+
+export default {};

+ 28 - 23
helpers/utility.ts

@@ -1,3 +1,4 @@
+/* eslint-disable no-underscore-dangle */
 import { fromEvent } from 'rxjs';
 import {
   auditTime,
@@ -6,10 +7,20 @@ import {
 
 import { ScrollStateType } from '../constants/type';
 
-export const objIsEmpty = (obj: Object) => !Object.keys(obj).length;
+export const objIsEmpty = (obj: Record<string, any>): boolean => !Object.keys(obj).length;
 
-export const watchScroll = (viewAreaElement: HTMLElement, cb: (state: ScrollStateType) => void) => {
-  const debounceScroll = () => {
+export const watchScroll = (
+  viewAreaElement: HTMLElement, cb: (state: ScrollStateType) => void,
+): ScrollStateType => {
+  let rAF: number | null = null;
+  const state = {
+    right: true,
+    down: true,
+    lastX: viewAreaElement.scrollLeft,
+    lastY: viewAreaElement.scrollTop,
+  };
+
+  const debounceScroll = (): void => {
     if (rAF) {
       return;
     }
@@ -17,14 +28,14 @@ export const watchScroll = (viewAreaElement: HTMLElement, cb: (state: ScrollStat
     rAF = window.requestAnimationFrame(() => {
       rAF = null;
 
-      let currentX = viewAreaElement.scrollLeft;
-      let lastX = state.lastX;
+      const currentX = viewAreaElement.scrollLeft;
+      const { lastX } = state;
       if (currentX !== lastX) {
         state.right = currentX > lastX;
       }
       state.lastX = currentX;
-      let currentY = viewAreaElement.scrollTop;
-      let lastY = state.lastY;
+      const currentY = viewAreaElement.scrollTop;
+      const { lastY } = state;
       if (currentY !== lastY) {
         state.down = currentY > lastY;
       }
@@ -33,14 +44,6 @@ export const watchScroll = (viewAreaElement: HTMLElement, cb: (state: ScrollStat
     });
   };
 
-  let state = {
-    right: true,
-    down: true,
-    lastX: viewAreaElement.scrollLeft,
-    lastY: viewAreaElement.scrollTop,
-  };
-  let rAF: number | null = null;
-
   fromEvent(viewAreaElement, 'scroll').pipe(
     auditTime(300),
     throttleTime(200),
@@ -49,22 +52,24 @@ export const watchScroll = (viewAreaElement: HTMLElement, cb: (state: ScrollStat
   return state;
 };
 
-export const scrollIntoView = (element: HTMLElement, spot?: {top: number}, skipOverflowHiddenElements: boolean = false) => {
-  let parent: HTMLElement = <HTMLElement>element.offsetParent;
+export const scrollIntoView = (
+  element: HTMLElement, spot?: {top: number}, skipOverflowHiddenElements = false,
+): void => {
+  let parent: HTMLElement = element.offsetParent as HTMLElement;
   let offsetY = element.offsetTop + element.clientTop;
 
   if (!parent) {
     return; // no need to scroll
   }
-  while ((parent.clientHeight === parent.scrollHeight &&
-          parent.clientWidth === parent.scrollWidth) ||
-          (skipOverflowHiddenElements &&
-          getComputedStyle(parent).overflow === 'hidden')) {
+  while (
+    (parent.clientHeight === parent.scrollHeight && parent.clientWidth === parent.scrollWidth)
+    || (skipOverflowHiddenElements && getComputedStyle(parent).overflow === 'hidden')
+  ) {
     if (parent.dataset._scaleY) {
-      offsetY /= parseInt(parent.dataset._scaleY);
+      offsetY /= parseInt(parent.dataset._scaleY, 10);
     }
     offsetY += parent.offsetTop;
-    parent = <HTMLElement>parent.offsetParent;
+    parent = parent.offsetParent as HTMLElement;
     if (!parent) {
       return; // no need to scroll
     }

+ 3 - 1
middleware/index.ts

@@ -2,7 +2,9 @@ import { Dispatch } from 'react';
 
 // import { SET_CURRENT_PAGE } from '../constants/actionTypes';
 
-const applyMiddleware = (dispatch: Dispatch<any>) => (action: { type: string, payload?: any }) => {
+const applyMiddleware = (dispatch: Dispatch<any>) => (
+  action: { type: string; payload?: any },
+): void => {
   dispatch(action);
 
   // if (action.type === SET_CURRENT_PAGE) {

+ 2 - 1
package.json

@@ -2,7 +2,7 @@
   "name": "create-next-example-app",
   "version": "1.0.0",
   "scripts": {
-    "dev": "next",
+    "dev": "next -p 8080",
     "build": "next build",
     "start": "next start",
     "export": "npm run build && next export",
@@ -25,6 +25,7 @@
     "notistack": "^0.9.6",
     "pdfjs-dist": "^2.2.228",
     "prop-types": "^15.6.2",
+    "query-string": "^6.9.0",
     "react": "16.10.0",
     "react-dom": "16.10.0",
     "react-popper": "^1.3.6",

+ 0 - 17
pages/demo.tsx

@@ -1,17 +0,0 @@
-import React from 'react';
-
-import Navbar from '../components/Navbar';
-import Sidebar from '../components/Sidebar';
-import Toolbar from '../components/Toolbar';
-
-const demo: React.FunctionComponent = () => {
-  return (
-    <>
-      <Sidebar />
-      <Navbar />
-      <Toolbar />
-    </>
-  );
-};
-
-export default demo;

+ 10 - 12
pages/index.tsx

@@ -7,19 +7,17 @@ import Toolbar from '../containers/Toolbar';
 import Placeholder from '../containers/Placeholder';
 import PdfViewer from '../containers/PdfViewer';
 
-const index: NextPage = () => {
-  return (
-    <>
-      <Sidebar />
-      <Navbar />
-      <Toolbar />
-      <Placeholder />
-      <PdfViewer />
-    </>
-  );
-};
+const index: NextPage = () => (
+  <>
+    <Sidebar />
+    <Navbar />
+    <Toolbar />
+    <Placeholder />
+    <PdfViewer />
+  </>
+);
 
-index.getInitialProps = async () => ({
+index.getInitialProps = async (): Promise<any> => ({
   namespacesRequired: ['common'],
 });
 

+ 8 - 8
pages/toasts.tsx

@@ -6,17 +6,17 @@ import Icon from '../components/Icon';
 const toasts: React.FunctionComponent = () => {
   const { enqueueSnackbar, closeSnackbar } = useSnackbar();
 
-  const handleClick = () => {
-    enqueueSnackbar('asd111', { 
-        variant: 'success',
-        action: (key) => (
-          <Icon glyph="close" onClick={() => {closeSnackbar(key)}}/>
-        ),
+  const handleClick = (): void => {
+    enqueueSnackbar('asd111', {
+      variant: 'success',
+      action: key => (
+        <Icon glyph="close" onClick={(): void => { closeSnackbar(key); }} />
+      ),
     });
-  }
+  };
 
   return (
-    <button onClick={handleClick}>click</button>
+    <button type="button" onClick={handleClick}>click</button>
   );
 };
 

+ 5 - 2
reducers/index.ts

@@ -2,8 +2,11 @@ import * as mainActions from './main';
 import * as pdfActions from './pdf';
 import * as types from '../constants/actionTypes';
 
-const createReducer = (handlers: {[key: string]: any}) => (state: Object, action: { type: string }) => {
-  if(!handlers.hasOwnProperty(action.type)) {
+const createReducer = (handlers: {[key: string]: any}) => (
+  state: Record<string, any>,
+  action: { type: string },
+): any => {
+  if (!Object.prototype.hasOwnProperty.call(handlers, action.type)) {
     return state;
   }
 

+ 2 - 2
reducers/main.ts

@@ -1,11 +1,11 @@
 import { PayloadType } from '../constants/type';
 
-export const setNavbarState = (state: Object, { payload }: PayloadType) => ({
+export const setNavbarState = (state: Record<string, any>, { payload }: PayloadType): any => ({
   ...state,
   navbarState: payload.state,
 });
 
-export const setSidebarState = (state: Object, { payload }: PayloadType) => ({
+export const setSidebarState = (state: Record<string, any>, { payload }: PayloadType): any => ({
   ...state,
   sidebarState: payload.state,
 });

+ 7 - 7
reducers/pdf.ts

@@ -1,36 +1,36 @@
 import { PayloadType } from '../constants/type';
 
-export const setCurrentPage = (state: Object, { payload }: PayloadType) => ({
+export const setCurrentPage = (state: Record<string, any>, { payload }: PayloadType): any => ({
   ...state,
   currentPage: payload,
 });
 
-export const setTotalPage = (state: Object, { payload }: PayloadType) => ({
+export const setTotalPage = (state: Record<string, any>, { payload }: PayloadType): any => ({
   ...state,
   totalPage: payload,
 });
 
-export const setPdf = (state: Object, { payload }: PayloadType) => ({
+export const setPdf = (state: Record<string, any>, { payload }: PayloadType): any => ({
   ...state,
   pdf: payload,
 });
 
-export const setProgress = (state: Object, { payload }: PayloadType) => ({
+export const setProgress = (state: Record<string, any>, { payload }: PayloadType): any => ({
   ...state,
   progress: payload,
 });
 
-export const setViewport = (state: Object, { payload }: PayloadType) => ({
+export const setViewport = (state: Record<string, any>, { payload }: PayloadType): any => ({
   ...state,
   viewport: payload,
 });
 
-export const changeScale = (state: Object, { payload }: PayloadType) => ({
+export const changeScale = (state: Record<string, any>, { payload }: PayloadType): any => ({
   ...state,
   scale: payload,
 });
 
-export const changeRotate = (state: Object, { payload }: PayloadType) => ({
+export const changeRotate = (state: Record<string, any>, { payload }: PayloadType): any => ({
   ...state,
   rotation: payload,
 });

+ 9 - 8
store/index.tsx

@@ -3,37 +3,38 @@ import React, { createContext, useContext, useReducer } from 'react';
 import initialMainState, { StateType as MainStateType } from './initialMainState';
 import initialPdfState, { StateType as PdfStateType } from './initialPdfState';
 
-import reducers from '../reducers'
+import reducers from '../reducers';
 import applyMiddleware from '../middleware';
 
 type StateType = MainStateType & PdfStateType
 
 type IContextProps = [
   StateType,
-  ({type}:{type:string}) => void,
+  ({ type }: { type: string }) => void,
 ]
 
 export const initialState = {
   ...initialMainState,
-  ...initialPdfState
+  ...initialPdfState,
 };
 
 export const StateContext = createContext({} as IContextProps);
 
 export const StoreProvider = ({
   children,
-} : {
+}: {
   children: React.ReactNode;
-}) => {
+}): React.ReactElement => {
   const [state, dispatch] = useReducer(reducers, initialState);
   const enhancedDispatch = applyMiddleware(dispatch);
 
   return (
     <StateContext.Provider
       value={[state, enhancedDispatch]}
-      children={children}
-    />
+    >
+      {children}
+    </StateContext.Provider>
   );
 };
 
-export default () => useContext(StateContext);
+export default (): any => useContext(StateContext);

+ 2 - 2
store/initialPdfState.ts

@@ -1,11 +1,11 @@
-import { ProgressType, ViewportType  } from '../constants/type';
+import { ProgressType, ViewportType } from '../constants/type';
 
 export type StateType = {
   totalPage: number;
   currentPage: number;
   pdf: any;
   progress: ProgressType;
-  viewport: ViewportType,
+  viewport: ViewportType;
   scale: number;
   rotation: number;
 };

+ 19 - 0
yarn.lock

@@ -7445,6 +7445,15 @@ query-string@^4.1.0:
     object-assign "^4.1.0"
     strict-uri-encode "^1.0.0"
 
+query-string@^6.9.0:
+  version "6.9.0"
+  resolved "https://registry.yarnpkg.com/query-string/-/query-string-6.9.0.tgz#1c3b727c370cf00f177c99f328fda2108f8fa3dd"
+  integrity sha512-KG4bhCFYapExLsUHrFt+kQVEegF2agm4cpF/VNc6pZVthIfCc/GK8t8VyNIE3nyXG9DK3Tf2EGkxjR6/uRdYsA==
+  dependencies:
+    decode-uri-component "^0.2.0"
+    split-on-first "^1.0.0"
+    strict-uri-encode "^2.0.0"
+
 querystring-es3@^0.2.0:
   version "0.2.1"
   resolved "https://registry.yarnpkg.com/querystring-es3/-/querystring-es3-0.2.1.tgz#9ec61f79049875707d69414596fd907a4d711e73"
@@ -8261,6 +8270,11 @@ spdx-license-ids@^3.0.0:
   resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz#3694b5804567a458d3c8045842a6358632f62654"
   integrity sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==
 
+split-on-first@^1.0.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/split-on-first/-/split-on-first-1.1.0.tgz#f610afeee3b12bce1d0c30425e76398b78249a5f"
+  integrity sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw==
+
 split-string@^3.0.1, split-string@^3.0.2:
   version "3.1.0"
   resolved "https://registry.yarnpkg.com/split-string/-/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2"
@@ -8355,6 +8369,11 @@ strict-uri-encode@^1.0.0:
   resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz#279b225df1d582b1f54e65addd4352e18faa0713"
   integrity sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=
 
+strict-uri-encode@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz#b9c7330c7042862f6b142dc274bbcc5866ce3546"
+  integrity sha1-ucczDHBChi9rFC3CdLvMWGbONUY=
+
 string-hash@1.1.3:
   version "1.1.3"
   resolved "https://registry.yarnpkg.com/string-hash/-/string-hash-1.1.3.tgz#e8aafc0ac1855b4666929ed7dd1275df5d6c811b"