diff --git a/package-lock.json b/package-lock.json index 937a670..a95836c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1216,6 +1216,11 @@ "loader-utils": "^1.1.0" } }, + "@types/classnames": { + "version": "2.2.7", + "resolved": "https://registry.npmjs.org/@types/classnames/-/classnames-2.2.7.tgz", + "integrity": "sha512-rzOhiQ55WzAiFgXRtitP/ZUT8iVNyllEpylJ5zHzR4vArUvMB39GTk+Zon/uAM0JxEFAWnwsxC2gH8s+tZ3Myg==" + }, "@types/events": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/@types/events/-/events-3.0.0.tgz", @@ -1233,6 +1238,19 @@ "@types/node": "*" } }, + "@types/jest": { + "version": "24.0.12", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-24.0.12.tgz", + "integrity": "sha512-60sjqMhat7i7XntZckcSGV8iREJyXXI6yFHZkSZvCPUeOnEJ/VP1rU/WpEWQ56mvoh8NhC+sfKAuJRTyGtCOow==", + "requires": { + "@types/jest-diff": "*" + } + }, + "@types/jest-diff": { + "version": "20.0.1", + "resolved": "https://registry.npmjs.org/@types/jest-diff/-/jest-diff-20.0.1.tgz", + "integrity": "sha512-yALhelO3i0hqZwhjtcr6dYyaLoCHbAMshwtj6cGxTvHZAKXHsYGdff6E8EPw3xLKY0ELUTQ69Q1rQiJENnccMA==" + }, "@types/json5": { "version": "0.0.29", "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", @@ -1246,10 +1264,14 @@ "dev": true }, "@types/node": { - "version": "11.13.5", - "resolved": "https://registry.npmjs.org/@types/node/-/node-11.13.5.tgz", - "integrity": "sha512-/OMMBnjVtDuwX1tg2pkYVSqRIDSmNTnvVvmvP/2xiMAAWf4a5+JozrApCrO4WCAILmXVxfNoQ3E+0HJbNpFVGg==", - "dev": true + "version": "11.13.8", + "resolved": "https://registry.npmjs.org/@types/node/-/node-11.13.8.tgz", + "integrity": "sha512-szA3x/3miL90ZJxUCzx9haNbK5/zmPieGraZEe4WI+3srN0eGLiT22NXeMHmyhNEopn+IrxqMc7wdVwvPl8meg==" + }, + "@types/prop-types": { + "version": "15.7.1", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.1.tgz", + "integrity": "sha512-CFzn9idOEpHrgdw8JsoTkaDDyRWk1jrzIV8djzcgpq0y9tG4B4lFT+Nxh52DVpDXV+n4+NPNv7M1Dj5uMp6XFg==" }, "@types/q": { "version": "1.5.2", @@ -1257,6 +1279,23 @@ "integrity": "sha512-ce5d3q03Ex0sy4R14722Rmt6MT07Ua+k4FwDfdcToYJcMKNtRVQvJ6JCAPdAmAnbRb6CsX6aYb9m96NGod9uTw==", "dev": true }, + "@types/react": { + "version": "16.8.15", + "resolved": "https://registry.npmjs.org/@types/react/-/react-16.8.15.tgz", + "integrity": "sha512-dMhzw1rWK+wwJWvPp5Pk12ksSrm/z/C/+lOQbMZ7YfDQYnJ02bc0wtg4EJD9qrFhuxFrf/ywNgwTboucobJqQg==", + "requires": { + "@types/prop-types": "*", + "csstype": "^2.2.0" + } + }, + "@types/react-dom": { + "version": "16.8.4", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-16.8.4.tgz", + "integrity": "sha512-eIRpEW73DCzPIMaNBDP5pPIpK1KXyZwNgfxiVagb5iGiz6da+9A5hslSX6GAQKdO7SayVCS/Fr2kjqprgAvkfA==", + "requires": { + "@types/react": "*" + } + }, "@types/tapable": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/@types/tapable/-/tapable-1.0.2.tgz", @@ -4085,6 +4124,11 @@ } } }, + "classnames": { + "version": "2.2.6", + "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.2.6.tgz", + "integrity": "sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q==" + }, "clean-css": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.1.tgz", @@ -4890,6 +4934,11 @@ "cssom": "0.3.x" } }, + "csstype": { + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.4.tgz", + "integrity": "sha512-lAJUJP3M6HxFXbqtGRc0iZrdyeN+WzOWeY0q/VnFzI+kqVrYIzC7bWlKqCW7oCIdzoPkvfp82EVvrTlQ8zsWQg==" + }, "currently-unhandled": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", @@ -16699,8 +16748,7 @@ "typescript": { "version": "3.3.4000", "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.3.4000.tgz", - "integrity": "sha512-jjOcCZvpkl2+z7JFn0yBOoLQyLoIkNZAs/fYJkUG6VKy6zLPHJGfQJYFHzibB6GJaF/8QrcECtlQ5cpvRHSMEA==", - "dev": true + "integrity": "sha512-jjOcCZvpkl2+z7JFn0yBOoLQyLoIkNZAs/fYJkUG6VKy6zLPHJGfQJYFHzibB6GJaF/8QrcECtlQ5cpvRHSMEA==" }, "uglify-js": { "version": "3.4.10", diff --git a/package.json b/package.json index 9ede333..e114765 100644 --- a/package.json +++ b/package.json @@ -9,8 +9,15 @@ "not op_mini all" ], "dependencies": { + "@types/jest": "24.0.12", + "@types/node": "11.13.8", + "@types/react": "16.8.15", + "@types/react-dom": "16.8.4", + "@types/classnames": "2.2.7", "react": "16.8.6", - "react-dom": "16.8.6" + "react-dom": "16.8.6", + "typescript": "3.3.4000", + "classnames": "2.2.6" }, "devDependencies": { "@hellroot/eslint-config": "1.8.0", diff --git a/public/index.html b/public/index.html index 9a8ef8f..5d57a79 100644 --- a/public/index.html +++ b/public/index.html @@ -8,7 +8,7 @@ content="width=device-width, initial-scale=1, shrink-to-fit=no" /> - React App + Яндекс.Почта diff --git a/src/app/LetterSmall/index.js b/src/app/LetterSmall/index.js new file mode 100644 index 0000000..98d2e58 --- /dev/null +++ b/src/app/LetterSmall/index.js @@ -0,0 +1 @@ +export * from './letterSmall'; diff --git a/src/app/LetterSmall/letterSmall.module.css b/src/app/LetterSmall/letterSmall.module.css new file mode 100644 index 0000000..d6ba3a5 --- /dev/null +++ b/src/app/LetterSmall/letterSmall.module.css @@ -0,0 +1,202 @@ +.letter { + width: 100%; + height: 37px; + + border-right: solid 1px #e2e2e2; + border-bottom: solid 1px #e2e2e2; +} + +.letter__animatedAddLetter { + animation-duration: 2s; + animation-name: add-new-letter; +} + +.letter__animatedDeleteLetter { + animation-duration: 1s; + animation-name: delete-letter; +} + +.letter__checkbox { + display: inline-block; + width: 16px; + height: 16px; + padding: 2px; + margin-top: 11px; + margin-left: 20px; + + border: solid 1px rgba(0, 0, 0, 0.15); + -webkit-appearance: none; + background-color: #ffffff; + border-radius: 3px; + outline: none; + vertical-align: top; +} + +.letter__checkbox:checked { + display: inline-block; + background: #e2e2e2; + background-clip: content-box; +} + +.letter__checkbox_dark { + display: inline-block; + width: 16px; + height: 16px; + padding: 2px; + margin-top: 11px; + margin-left: 20px; + + border: solid 1px #ffffff; + -webkit-appearance: none; + background-color: rgba(0, 0, 0, 0.15); + border-radius: 3px; + outline: none; + vertical-align: top; +} + +.letter__checkbox_dark:checked { + display: inline-block; + background: #e2e2e2; + background-clip: content-box; +} + +.letter__textSenderLetter_dark { + display: inline-block; + overflow: hidden; + width: 40%; + height: 15px; + margin-top: 12px; + margin-left: 10px; + color: #cccccc; + font-family: HelveticaNeue; + font-size: 13px; + text-overflow: ellipsis; + vertical-align: top; + white-space: nowrap; +} + +.letter__textLetter_dark { + display: inline-block; + overflow: hidden; + width: 10%; + height: 15px; + margin-top: 12px; + margin-left: 10px; + color: #cccccc; + font-family: HelveticaNeue; + font-size: 13px; + text-overflow: ellipsis; + vertical-align: top; + white-space: nowrap; +} + +.letter__data_dark { + width: 4%; + height: 15px; + margin-top: 11px; + margin-right: 20px; + color: #cccccc; + float: right; + font-family: HelveticaNeue; + font-size: 13px; + text-align: right; +} + +.letter__delLine { + text-decoration: none; +} + +.letter__yLogo { + display: inline-block; + width: 22px; + height: 22px; + margin-top: 7px; + margin-left: 7px; + background-color: red; + border-radius: 50%; + color: white; + text-align: center; +} + +.letter__yLogoText { + margin-top: 4px; + font-family: HelveticaNeueLight; + font-size: 20px; +} + +.letter_isBold { + font-weight: bold; +} + +.letter__textSenderLetter { + display: inline-block; + overflow: hidden; + width: 40%; + height: 15px; + margin-top: 12px; + margin-left: 10px; + color: #000000; + font-family: HelveticaNeue; + font-size: 13px; + text-overflow: ellipsis; + vertical-align: top; + white-space: nowrap; +} + +.letter__textLetter { + display: inline-block; + overflow: hidden; + width: 10%; + height: 15px; + margin-top: 12px; + margin-left: 10px; + color: #000000; + font-family: HelveticaNeue; + font-size: 13px; + text-overflow: ellipsis; + vertical-align: top; + white-space: nowrap; +} + +.letter__markNewLetter { + display: inline-block; + width: 10px; + height: 10px; + margin-top: 14px; + margin-left: 7px; + background-color: #6287bd; + border-radius: 50%; + vertical-align: top; +} + +.letter__data { + width: 8%; + height: 15px; + margin-top: 7px; + margin-right: 10px; + color: #9b9b9b; + float: right; + font-family: HelveticaNeue; + font-size: 13px; + text-align: right; +} + +@keyframes delete-letter { + from { + opacity: 100%; + } + + to { + opacity: 0; + } +} + +@keyframes add-new-letter { + from { + opacity: 0; + } + + to { + opacity: 100%; + } +} diff --git a/src/app/LetterSmall/letterSmall.tsx b/src/app/LetterSmall/letterSmall.tsx new file mode 100644 index 0000000..6c1cd29 --- /dev/null +++ b/src/app/LetterSmall/letterSmall.tsx @@ -0,0 +1,66 @@ +import *as React from 'react'; + +import styles from './letterSmall.module.css'; +import classnames from 'classnames'; + +interface IProps { + isDark: boolean; + isSelected: boolean; + changeAnimation: boolean; + id: number; + deleteChosenLetter: (id :number) => void; + switchLetterCheckbox: (id: number) => void; + openLetter: (text: string[]) => void; + text: string[]; + author: string; + subject: string; + date: string; +} + +export class LetterSmall extends React.Component { + constructor(props: IProps) { + super(props); + this.props = props; + this.changeAnimation = this.changeAnimation.bind(this); + } + + public readonly props: IProps; + + changeAnimation() { + if (this.props.changeAnimation) { + this.props.deleteChosenLetter(this.props.id); + } + } + + render() { + return ( +
+ this.props.switchLetterCheckbox(this.props.id)} + /> + this.props.openLetter(this.props.text)} + > +
+
Я
+
+ {this.props.author} + {this.props.subject} + {this.props.date} +
+
+ ); + } +} diff --git a/src/app/allLetters/allLetters.module.css b/src/app/allLetters/allLetters.module.css new file mode 100644 index 0000000..b1edb05 --- /dev/null +++ b/src/app/allLetters/allLetters.module.css @@ -0,0 +1,4 @@ +.allLetters { + display: inline-block; + width: 100%; +} diff --git a/src/app/allLetters/allLetters.tsx b/src/app/allLetters/allLetters.tsx new file mode 100644 index 0000000..b882527 --- /dev/null +++ b/src/app/allLetters/allLetters.tsx @@ -0,0 +1,48 @@ +import *as React from 'react'; + +import styles from './allLetters.module.css'; +import { Letter } from '../letter'; +import {ILetter} from '../letterTypes/letterTypes'; + +interface IProps { + create: boolean; + visibleLetters: ILetter[]; + markedLetters: {[id: string]: boolean}; + switchLetterCheckbox: (id: number) => void; + openLetter: (text: string[]) => void; + deleteChosenLetter: (id: number) => void; + isDark: boolean; +} + +export class AllLetters extends React.Component { + constructor(props: IProps) { + super(props); + this.props = props; + } + public readonly props: IProps; + + render() { + return ( +
+ {this.props.visibleLetters.map(letter => { + return ( + + ); + })} +
+ ); + } +} diff --git a/src/app/allLetters/index.js b/src/app/allLetters/index.js new file mode 100644 index 0000000..7e2dfac --- /dev/null +++ b/src/app/allLetters/index.js @@ -0,0 +1 @@ +export * from './allLetters'; diff --git a/src/app/app.css b/src/app/app.css deleted file mode 100644 index 1c4d511..0000000 --- a/src/app/app.css +++ /dev/null @@ -1,27 +0,0 @@ -.app { - text-align: center; -} - -.app-header { - display: flex; - min-height: 100vh; - flex-direction: column; - align-items: center; - justify-content: center; - background-color: #282c34; - color: #fff; - font-size: calc(10px + 2vmin); -} - -.app-link { - color: #61dafb; -} - -@keyframes app-logo-spin { - from { - transform: rotate(0deg); - } - to { - transform: rotate(360deg); - } -} diff --git a/src/app/app.jsx b/src/app/app.jsx deleted file mode 100644 index f759eed..0000000 --- a/src/app/app.jsx +++ /dev/null @@ -1,25 +0,0 @@ -import React, { Component } from 'react'; - -import './app.css'; - -export class App extends Component { - render() { - return ( -
-
-

- Edit src/app/app.jsx and save to reload. -

- - Learn React - -
-
- ); - } -} diff --git a/src/app/app.module.css b/src/app/app.module.css new file mode 100644 index 0000000..5e68794 --- /dev/null +++ b/src/app/app.module.css @@ -0,0 +1,13 @@ +.app { + padding: 25px 3% 2%; +} + +@font-face { + font-family: HelveticaNeue; + src: url(./txtStyle/HelveticaNeueCyr-Medium.otf); +} + +@font-face { + font-family: HelveticaNeueLight; + src: url(./txtStyle/HelveticaNeueCyr-Light.otf); +} diff --git a/src/app/app.tsx b/src/app/app.tsx new file mode 100644 index 0000000..c14e412 --- /dev/null +++ b/src/app/app.tsx @@ -0,0 +1,36 @@ +import *as React from 'react'; + +import styles from './app.module.css'; +import { Header } from './header'; +import { MailInnerContent } from './mailInnerContent'; + +interface IState { + isDark: boolean; +} + +export class App extends React.Component { + public readonly state: IState; + + constructor(props: {}) { + super(props); + this.state = { + isDark: false, + }; + this.changeTheme = this.changeTheme.bind(this); + } + + private changeTheme() { + this.setState((state: IState) => { + document.body.style.background = state.isDark ? '#e5eaf0' : 'black'; + return { isDark: !state.isDark }; + }); + } + + render() { + return ( +
+ +
+ ); + } +} diff --git a/src/app/button/button.module.css b/src/app/button/button.module.css new file mode 100644 index 0000000..59c9060 --- /dev/null +++ b/src/app/button/button.module.css @@ -0,0 +1,29 @@ +.button__textMenu { + width: 137px; + height: 13px; + padding-top: 4px; + padding-bottom: 4px; + padding-left: 10px; + margin-bottom: 8px; + margin-left: -10px; + color: #707070; + font-family: HelveticaNeue; + font-size: 11px; + line-height: 16px; + list-style-type: none; +} + +.button__textMenu:hover { + background-color: #cdd6e4; + border-radius: 3px; + color: #555555; + font-weight: bold; +} + +.button_unhighlight { + color: inherit; +} + +.button__delLine { + text-decoration: none; +} diff --git a/src/app/button/button.tsx b/src/app/button/button.tsx new file mode 100644 index 0000000..a4eaa17 --- /dev/null +++ b/src/app/button/button.tsx @@ -0,0 +1,26 @@ +import *as React from 'react'; + +import styles from './button.module.css'; +import classnames from 'classnames'; + +interface IProps { + name: string; +} + +export class Button extends React.Component { + constructor(props: IProps) { + super(props); + this.props = props; + } + public readonly props: IProps; + + render() { + return ( +
  • + + {this.props.name} + +
  • + ); + } +} diff --git a/src/app/button/index.js b/src/app/button/index.js new file mode 100644 index 0000000..eaf5eea --- /dev/null +++ b/src/app/button/index.js @@ -0,0 +1 @@ +export * from './button'; diff --git a/src/app/content/content.module.css b/src/app/content/content.module.css new file mode 100644 index 0000000..091935e --- /dev/null +++ b/src/app/content/content.module.css @@ -0,0 +1,22 @@ +.content { + display: inline-block; + width: 78%; + min-height: 600px; + margin-left: 3%; + background-color: #ffffff; + border-radius: 3px; + box-shadow: 0 2px 6px 0 rgba(0, 0, 0, 0.34); + vertical-align: top; +} + +.content_dark { + display: inline-block; + width: 78%; + min-height: 600px; + margin-left: 3%; + background-color: #101010; + border-radius: 3px; + box-shadow: 0 2px 6px 0 rgba(0, 0, 0, 0.34); + color: inherit; + vertical-align: top; +} diff --git a/src/app/content/content.tsx b/src/app/content/content.tsx new file mode 100644 index 0000000..f007e86 --- /dev/null +++ b/src/app/content/content.tsx @@ -0,0 +1,51 @@ +import *as React from 'react'; + +import styles from './content.module.css'; +import { LettersMenu } from '../lettersMenu'; +import { LetterState } from '../lettersState'; +import { Footer } from '../footer'; +import { ILetter } from '../letterTypes/letterTypes'; + +interface IProps { + create: boolean; + selectAll: boolean; + chooseAllLetters: () => void; + markLettersToDelete: () => void; + deleteChosenLetter: (id: number) => void; + visibleLetters: ILetter[]; + markedLetters: {[id: string]: boolean}; + switchLetterCheckbox: (id: number) => void; + isDark: boolean; + createNewLetter: () => void; +} + +export class Content extends React.Component { + constructor(props: IProps) { + super(props); + this.props = props; + } + + public readonly props: IProps; + render() { + return ( +
    + + +
    + ); + } +} diff --git a/src/app/content/index.js b/src/app/content/index.js new file mode 100644 index 0000000..7b367d1 --- /dev/null +++ b/src/app/content/index.js @@ -0,0 +1 @@ +export * from './content'; diff --git a/src/app/footer/footer.module.css b/src/app/footer/footer.module.css new file mode 100644 index 0000000..0484ee2 --- /dev/null +++ b/src/app/footer/footer.module.css @@ -0,0 +1,24 @@ +.footer { + width: 100%; + height: 37px; + + border-top: solid 1px #e2e2e2; +} + +.footerText__textEndline { + height: 12px; + margin-right: 45px; + color: #9b9b9b; + float: right; + font-family: HelveticaNeueLight; + font-size: 11px; + line-height: 40px; +} + +.footerText_unhighlight { + color: inherit; +} + +.footerText__delLine { + text-decoration: none; +} diff --git a/src/app/footer/footer.tsx b/src/app/footer/footer.tsx new file mode 100644 index 0000000..535fd5a --- /dev/null +++ b/src/app/footer/footer.tsx @@ -0,0 +1,16 @@ +import *as React from 'react'; + +import styles from './footer.module.css'; +import classnames from 'classnames'; + +export class Footer extends React.Component { + render() { + return ( +
    + © 2001 - 2018, Яндекс + Реклама + Помощь и обратная связь +
    + ); + } +} diff --git a/src/app/footer/index.js b/src/app/footer/index.js new file mode 100644 index 0000000..a058eae --- /dev/null +++ b/src/app/footer/index.js @@ -0,0 +1 @@ +export * from './footer'; diff --git a/src/app/header/header.module.css b/src/app/header/header.module.css new file mode 100644 index 0000000..18bdefe --- /dev/null +++ b/src/app/header/header.module.css @@ -0,0 +1,58 @@ +.header { + display: inline-block; + width: 100%; + min-width: 800px; + height: 5%; + margin-bottom: 12px; +} + +.header__ypLogo { + display: inline-block; + width: 200px; + margin-left: 11px; + font-size: 170%; + vertical-align: text-bottom; +} + +.header__burgerMenu { + display: inline-block; + margin-top: 7px; +} + +.header__line { + width: 20px; + height: 3px; + margin-top: 5px; + margin-bottom: 5px; + background-color: #000000; +} + +.header__line_dark { + width: 20px; + height: 3px; + margin-top: 5px; + margin-bottom: 5px; + background-color: #ffffff; +} +.header__button { + width: 80px; + height: 35px; + margin-bottom: 8px; + + border: #6287bd; + background-color: #6287bd; + border-radius: 3px; + float: right; +} + +.header__textWrite { + display: inline-block; + width: 56px; + height: 15px; + margin-top: 7px; + margin-bottom: 10px; + color: #ffffff; + font-family: HelveticaNeue; + font-size: 12px; + vertical-align: center; +} diff --git a/src/app/header/header.tsx b/src/app/header/header.tsx new file mode 100644 index 0000000..f0517ec --- /dev/null +++ b/src/app/header/header.tsx @@ -0,0 +1,38 @@ +import *as React from 'react'; + +import styles from './header.module.css'; +import { Search } from '../search'; +import logo from '../images/header-logo.svg'; +import darkLogo from '../images/header-logo-dark.png'; + +interface IProps { + isClearInput: boolean; + search: (text: string) => void; + changeTheme: () => void; + isDark: boolean; +} + +export class Header extends React.Component { + constructor(props: IProps) { + super(props); + this.props = props; + } + public readonly props: IProps; + + render() { + return ( +
    +
    +
    +
    +
    +
    + logo + + +
    + ); + } +} diff --git a/src/app/header/index.js b/src/app/header/index.js new file mode 100644 index 0000000..677ca79 --- /dev/null +++ b/src/app/header/index.js @@ -0,0 +1 @@ +export * from './header'; diff --git a/src/app/images/cross.png b/src/app/images/cross.png new file mode 100644 index 0000000..7765268 Binary files /dev/null and b/src/app/images/cross.png differ diff --git a/src/app/images/header-logo-dark.png b/src/app/images/header-logo-dark.png new file mode 100644 index 0000000..d2b1bc7 Binary files /dev/null and b/src/app/images/header-logo-dark.png differ diff --git a/src/app/images/header-logo.svg b/src/app/images/header-logo.svg new file mode 100644 index 0000000..db23b2d --- /dev/null +++ b/src/app/images/header-logo.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/src/app/images/logo.jpg b/src/app/images/logo.jpg new file mode 100644 index 0000000..8743b99 Binary files /dev/null and b/src/app/images/logo.jpg differ diff --git a/src/app/leftMenu/index.js b/src/app/leftMenu/index.js new file mode 100644 index 0000000..45e2691 --- /dev/null +++ b/src/app/leftMenu/index.js @@ -0,0 +1 @@ +export * from './leftMenu'; diff --git a/src/app/leftMenu/leftMenu.module.css b/src/app/leftMenu/leftMenu.module.css new file mode 100644 index 0000000..d8f6caa --- /dev/null +++ b/src/app/leftMenu/leftMenu.module.css @@ -0,0 +1,28 @@ +.leftMenu { + display: inline-block; + width: 147px; + height: 100%; + vertical-align: top; +} + +.leftMenu__button { + width: 147px; + height: 32px; + margin-bottom: 8px; + + border: #6287bd; + background-color: #6287bd; + border-radius: 3px; +} + +.leftMenu__textWrite { + display: inline-block; + width: 56px; + height: 15px; + margin-top: 7px; + margin-bottom: 10px; + color: #ffffff; + font-family: HelveticaNeue; + font-size: 12px; + vertical-align: center; +} diff --git a/src/app/leftMenu/leftMenu.tsx b/src/app/leftMenu/leftMenu.tsx new file mode 100644 index 0000000..f857a2e --- /dev/null +++ b/src/app/leftMenu/leftMenu.tsx @@ -0,0 +1,27 @@ +import *as React from 'react'; + +import styles from './leftMenu.module.css'; +import { MailMenu } from '../mailMenu'; + +interface IProps { + newMail: () => void; +} + +export class LeftMenu extends React.Component { + constructor(props: IProps) { + super(props); + this.props = props; + } + public readonly props: IProps; + + render() { + return ( +
    + + +
    + ); + } +} diff --git a/src/app/letter/index.js b/src/app/letter/index.js new file mode 100644 index 0000000..c37f80d --- /dev/null +++ b/src/app/letter/index.js @@ -0,0 +1 @@ +export * from './letter'; diff --git a/src/app/letter/letter.module.css b/src/app/letter/letter.module.css new file mode 100644 index 0000000..2979b15 --- /dev/null +++ b/src/app/letter/letter.module.css @@ -0,0 +1,201 @@ +.letter { + width: 100%; + height: 37px; + + border-bottom: solid 1px #e2e2e2; +} + +.letter__animatedAddLetter { + animation-duration: 2s; + animation-name: add-new-letter; +} + +.letter__animatedDeleteLetter { + animation-duration: 1s; + animation-name: delete-letter; +} + +.letter__checkbox { + display: inline-block; + width: 16px; + height: 16px; + padding: 2px; + margin-top: 11px; + margin-left: 20px; + + border: solid 1px rgba(0, 0, 0, 0.15); + -webkit-appearance: none; + background-color: #ffffff; + border-radius: 3px; + outline: none; + vertical-align: top; +} + +.letter__checkbox:checked { + display: inline-block; + background: #e2e2e2; + background-clip: content-box; +} + +.letter__checkbox_dark { + display: inline-block; + width: 16px; + height: 16px; + padding: 2px; + margin-top: 11px; + margin-left: 20px; + + border: solid 1px #ffffff; + -webkit-appearance: none; + background-color: rgba(0, 0, 0, 0.15); + border-radius: 3px; + outline: none; + vertical-align: top; +} + +.letter__checkbox_dark:checked { + display: inline-block; + background: #e2e2e2; + background-clip: content-box; +} + +.letter__textSenderLetter_dark { + display: inline-block; + overflow: hidden; + width: 20%; + height: 15px; + margin-top: 12px; + margin-left: 10px; + color: #cccccc; + font-family: HelveticaNeue; + font-size: 13px; + text-overflow: ellipsis; + vertical-align: top; + white-space: nowrap; +} + +.letter__textLetter_dark { + display: inline-block; + overflow: hidden; + width: 40%; + height: 15px; + margin-top: 12px; + margin-left: 10px; + color: #cccccc; + font-family: HelveticaNeue; + font-size: 13px; + text-overflow: ellipsis; + vertical-align: top; + white-space: nowrap; +} + +.letter__data_dark { + width: 8%; + height: 15px; + margin-top: 11px; + margin-right: 20px; + color: #cccccc; + float: right; + font-family: HelveticaNeue; + font-size: 13px; + text-align: right; +} + +.letter__delLine { + text-decoration: none; +} + +.letter__yLogo { + display: inline-block; + width: 22px; + height: 22px; + margin-top: 7px; + margin-left: 20px; + background-color: red; + border-radius: 50%; + color: white; + text-align: center; +} + +.letter__yLogoText { + margin-top: 4px; + font-family: HelveticaNeueLight; + font-size: 20px; +} + +.letter_isBold { + font-weight: bold; +} + +.letter__textSenderLetter { + display: inline-block; + overflow: hidden; + width: 20%; + height: 15px; + margin-top: 12px; + margin-left: 10px; + color: #000000; + font-family: HelveticaNeue; + font-size: 13px; + text-overflow: ellipsis; + vertical-align: top; + white-space: nowrap; +} + +.letter__textLetter { + display: inline-block; + overflow: hidden; + width: 40%; + height: 15px; + margin-top: 12px; + margin-left: 10px; + color: #000000; + font-family: HelveticaNeue; + font-size: 13px; + text-overflow: ellipsis; + vertical-align: top; + white-space: nowrap; +} + +.letter__markNewLetter { + display: inline-block; + width: 10px; + height: 10px; + margin-top: 14px; + margin-left: 20px; + background-color: #6287bd; + border-radius: 50%; + vertical-align: top; +} + +.letter__data { + width: 8%; + height: 15px; + margin-top: 11px; + margin-right: 20px; + color: #9b9b9b; + float: right; + font-family: HelveticaNeue; + font-size: 13px; + text-align: right; +} + +@keyframes delete-letter { + from { + opacity: 100%; + } + + to { + opacity: 0; + } +} + +@keyframes add-new-letter { + from { + opacity: 0; + } + + to { + opacity: 100%; + } +} diff --git a/src/app/letter/letter.tsx b/src/app/letter/letter.tsx new file mode 100644 index 0000000..a5c053e --- /dev/null +++ b/src/app/letter/letter.tsx @@ -0,0 +1,66 @@ +import *as React from 'react'; + +import styles from './letter.module.css'; +import classnames from 'classnames'; + +interface IProps { + isDark: boolean; + isSelected: boolean; + changeAnimation: boolean; + id: number; + deleteChosenLetter: (id :number) => void; + switchLetterCheckbox: (id: number) => void; + openLetter: (text: string[]) => void; + text: string[]; + author: string; + subject: string; + date: string; +} + +export class Letter extends React.Component { + constructor(props: IProps) { + super(props); + this.props = props; + this.changeAnimation = this.changeAnimation.bind(this); + } + + public readonly props: IProps; + + changeAnimation() { + if (this.props.changeAnimation) { + this.props.deleteChosenLetter(this.props.id); + } + } + + render() { + return ( +
    + this.props.switchLetterCheckbox(this.props.id)} + /> + this.props.openLetter(this.props.text)} + > +
    +
    Я
    +
    + {this.props.author} + {this.props.subject} + {this.props.date} +
    +
    + ); + } +} diff --git a/src/app/letterTypes/letterTypes.ts b/src/app/letterTypes/letterTypes.ts new file mode 100644 index 0000000..af8a243 --- /dev/null +++ b/src/app/letterTypes/letterTypes.ts @@ -0,0 +1,9 @@ +export interface ILetter { + id: number; + author: string; + subject: string; + text: string[]; + date: string; + changeAnimation: boolean; + isSelected: boolean; +} diff --git a/src/app/lettersMenu/index.js b/src/app/lettersMenu/index.js new file mode 100644 index 0000000..9dd0de6 --- /dev/null +++ b/src/app/lettersMenu/index.js @@ -0,0 +1 @@ +export * from './lettersMenu'; diff --git a/src/app/lettersMenu/lettersMenu.module.css b/src/app/lettersMenu/lettersMenu.module.css new file mode 100644 index 0000000..0dba425 --- /dev/null +++ b/src/app/lettersMenu/lettersMenu.module.css @@ -0,0 +1,77 @@ +.lettersMenu { + width: 100%; + height: 37px; + padding: 0; + margin: 0; + + border-bottom: solid 1px #e2e2e2; +} + +.lettersMenu__checkbox { + display: inline-block; + width: 16px; + height: 16px; + padding: 2px; + margin-top: 11px; + margin-left: 20px; + + border: solid 1px rgba(0, 0, 0, 0.15); + -webkit-appearance: none; + background-color: #ffffff; + border-radius: 3px; + outline: none; + vertical-align: top; +} + +.lettersMenu__checkbox:checked { + display: inline-block; + background: #e2e2e2; + background-clip: content-box; +} + +.lettersMenu__checkbox_dark { + display: inline-block; + width: 16px; + height: 16px; + padding: 2px; + margin-top: 11px; + margin-left: 20px; + + border: solid 1px #ffffff; + -webkit-appearance: none; + background-color: rgba(0, 0, 0, 0.15); + border-radius: 3px; + outline: none; + vertical-align: top; +} + +.lettersMenu__checkbox_dark:checked { + display: inline-block; + background: #e2e2e2; + background-clip: content-box; +} + +.lettersMenu__horizontalPosition { + display: inline; + list-style-type: none; +} + +.lettersMenu__button__textTitle { + display: inline-block; + height: 16px; + margin-top: 11px; + margin-left: 25px; + + border: none; + background: none; + color: #cccccc; + font-family: HelveticaNeue; + font-size: 13px; + line-height: 20px; + outline: none; + vertical-align: top; +} + +.lettersMenu__button__delLine { + text-decoration: none; +} diff --git a/src/app/lettersMenu/lettersMenu.tsx b/src/app/lettersMenu/lettersMenu.tsx new file mode 100644 index 0000000..23323e8 --- /dev/null +++ b/src/app/lettersMenu/lettersMenu.tsx @@ -0,0 +1,69 @@ +import *as React from 'react'; + +import styles from './lettersMenu.module.css'; +import classnames from 'classnames'; + +interface IProps { + selectAll: boolean; + chooseAllLetters: () => void; + createNewLetter: () => void; + markLettersToDelete: () => void; + isDark: boolean; +} +export class LettersMenu extends React.Component { + constructor(props: IProps) { + super(props); + this.props = props; + } + public readonly props: IProps; + + render() { + return ( + + ); + } +} diff --git a/src/app/lettersState/index.js b/src/app/lettersState/index.js new file mode 100644 index 0000000..32f343b --- /dev/null +++ b/src/app/lettersState/index.js @@ -0,0 +1 @@ +export * from './letterState'; diff --git a/src/app/lettersState/letterState.module.css b/src/app/lettersState/letterState.module.css new file mode 100644 index 0000000..3a0b05b --- /dev/null +++ b/src/app/lettersState/letterState.module.css @@ -0,0 +1,32 @@ +.letterState { + width: 100%; + min-height: 524px; +} + +.letterState_show:target { + display: inline-block; +} + +.search__textSearch { + width: 90%; + height: 100%; + padding-left: 10px; + + border: none; + -webkit-appearance: none; + background: none; + color: #000000; + font-size: 15px; + outline: none; +} + +.search { + display: inline-block; + width: 40%; + height: 32px; + margin-left: 14%; + background-color: #ffffff; + box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.2); + opacity: 0.5; + vertical-align: text-bottom; +} diff --git a/src/app/lettersState/letterState.tsx b/src/app/lettersState/letterState.tsx new file mode 100644 index 0000000..2e84060 --- /dev/null +++ b/src/app/lettersState/letterState.tsx @@ -0,0 +1,88 @@ +import *as React from 'react'; + +import classnames from 'classnames'; +import styles from './letterState.module.css'; +import { OpenLetter } from '../openLetter'; +import { AllLetters } from '../allLetters'; +import { ILetter } from '../letterTypes/letterTypes'; +import cross from '../images/cross.png'; + +interface IProps { + create: boolean; + deleteChosenLetter: (id: number) => void; + visibleLetters: ILetter[]; + markedLetters: { [id: string]: boolean }; + switchLetterCheckbox: (id: number) => void; + isDark: boolean; +} + +interface IState { + openLetter: boolean; + contentLetter: string[]; +} + +export class LetterState extends React.Component { + constructor(props: IProps) { + super(props); + this.props = props; + this.state = { + openLetter: false, + contentLetter: [] + }; + this.openLetter = this.openLetter.bind(this); + this.closeLetter = this.closeLetter.bind(this); + } + + public readonly props: IProps; + public readonly state: IState; + + openLetter(text: string[]) { + this.setState({ + openLetter: true, + contentLetter: text + }); + } + + closeLetter() { + this.setState({ + openLetter: false + }); + } + + render() { + return this.props.create ? ( +
    +
    + +
    +
    + +
    +
    + ) : (this.state.openLetter ? ( +
    + +
    + ) : ( +
    + +
    + )); + } +} diff --git a/src/app/mailInnerContent/index.js b/src/app/mailInnerContent/index.js new file mode 100644 index 0000000..1babe3c --- /dev/null +++ b/src/app/mailInnerContent/index.js @@ -0,0 +1 @@ +export * from './mailInnerContent'; diff --git a/src/app/mailInnerContent/mailInnerContent.module.css b/src/app/mailInnerContent/mailInnerContent.module.css new file mode 100644 index 0000000..156ad4a --- /dev/null +++ b/src/app/mailInnerContent/mailInnerContent.module.css @@ -0,0 +1,7 @@ +.mailInnerContent { + display: inline-block; + width: 100%; + min-width: 800px; + height: 90%; + padding-top: 13px; +} diff --git a/src/app/mailInnerContent/mailInnerContent.tsx b/src/app/mailInnerContent/mailInnerContent.tsx new file mode 100644 index 0000000..8ace356 --- /dev/null +++ b/src/app/mailInnerContent/mailInnerContent.tsx @@ -0,0 +1,246 @@ +import *as React from 'react'; + +import styles from './mailInnerContent.module.css'; +import { LeftMenu } from '../leftMenu'; +import { Content } from '../content'; +import { + generateDate, + generateName, + generateContent, + generateRandomCount +} from './scripts/letterGeneratorUtils'; +import { ILetter } from '../letterTypes/letterTypes'; +import { Header } from '../header/header'; + +interface IState { + create: boolean; + isClearInput: boolean; + counter: number; + letters: ILetter[]; + visibleLetters: ILetter[]; + selectAll: boolean; + markedLetters: { [id: string]: boolean }; + text: string; +} + +interface IProps { + changeTheme: () => void; + isDark: boolean; +} + +const MAX_COUNT = 30; + +export class MailInnerContent extends React.Component { + public readonly state: IState; + public readonly props: IProps; + + static async generateLetter() { + const author = generateName(); + const text = await generateContent(); + const subject = text[0].substr(0, 45); + const date = generateDate(); + return { author, text, subject, date }; + } + + constructor(props: IProps) { + super(props); + this.props = props; + this.state = { + create: false, + isClearInput: false, + text: '', + counter: 0, + letters: [], + visibleLetters: [], + selectAll: false, + markedLetters: {} + }; + this.search = this.search.bind(this); + this.deleteChosenLetter = this.deleteChosenLetter.bind(this); + this.markLettersToDelete = this.markLettersToDelete.bind(this); + this.switchLetterCheckbox = this.switchLetterCheckbox.bind(this); + this.chooseAllLetters = this.chooseAllLetters.bind(this); + this.newMail = this.newMail.bind(this); + this.GenerateNewLetter(); + this.createNewLetter = this.createNewLetter.bind(this); + } + + createNewLetter() { + console.log(this.state.create); + this.setState((state: IState) => { + return { + create: !state.create + }; + }); + } + + search(text: string) { + console.log(this.state.isClearInput); + this.setState(() => { + return { + text: text + } + }); + const tmpLetters: ILetter[] = []; + const tmp = this.state.letters; + for (let i = 0; i < tmp.length; i++) { + if (i < MAX_COUNT) { + tmpLetters.push(tmp[i]); + } + } + if (text == '') { + this.setState(() => { + return { visibleLetters: tmpLetters }; + }); + } else { + let contentVisibleLetters = tmpLetters.filter(letter => letter.text[0].search(text) !== -1); + let authorVisibleLetters = tmpLetters.filter(letter => letter.author.search(text) !== -1); + if (authorVisibleLetters !== this.state.visibleLetters && authorVisibleLetters.length !== 0) { + this.setState(() => { + return { visibleLetters: authorVisibleLetters }; + }); + } else if (contentVisibleLetters !== this.state.visibleLetters) { + this.setState(() => { + return { visibleLetters: contentVisibleLetters }; + }); + } + } + } + + deleteChosenLetter(id: number) { + let count = 0; + const tmpVisibleLetters: ILetter[] = []; + const tmpLetters = this.state.letters.filter(letter => letter.id !== id); + tmpLetters.forEach(letter => { + const tmp = letter; + if (MAX_COUNT > count) { + tmpVisibleLetters.push(tmp); + count++; + } + }); + this.setState((state: IState) => { + return { isClearInput: false, letters: tmpLetters, visibleLetters: tmpVisibleLetters }; + }); + } + + chooseAllLetters() { + const tmpVisibleLetters = this.state.visibleLetters; + const newMarkedLetters = this.state.markedLetters; + for (let i = 0; i < tmpVisibleLetters.length; i++) { + newMarkedLetters[tmpVisibleLetters[i].id] = !this.state.selectAll; + } + this.setState((state: IState) => { + return { + visibleLetters: tmpVisibleLetters, + selectAll: !state.selectAll, + markedLetters: newMarkedLetters + }; + }); + } + + async newMail() { + const { author, text, subject, date } = await MailInnerContent.generateLetter(); + const newMarkedLetters = this.state.markedLetters; + const id: number = this.state.counter; + this.setState((state: IState) => { + return { counter: state.counter + 1 }; + }); + newMarkedLetters[id] = false; + const tmpLetters = this.state.letters; + // const tmpVisibleLetters: ILetter[] = []; + const letter = { + id, + author, + subject, + text, + date, + changeAnimation: false, + isSelected: false + }; + // tmpVisibleLetters.push(letter); + // for (let i = 0; i < tmpLetters.length; i++) { + // if (i < MAX_COUNT - 1) { + // tmpVisibleLetters.push(tmpLetters[i]); + // } + // } + this.setState((state: IState) => { + return { + //visibleLetters: tmpVisibleLetters, + letters: [letter].concat(state.letters), + markedLetters: newMarkedLetters + }; + }); + this.search(this.state.text); + } + + sleep(ms: number) { + return new Promise(resolve => setTimeout(resolve, ms)); + } + + async GenerateNewLetter() { + const fiveMinute = 300000; + const minTime = 10; + const maxTime = 600000; + let previous = 300000; + await this.newMail(); + previous = Math.max(fiveMinute - previous, generateRandomCount(minTime, maxTime)); + await this.sleep(previous); + this.GenerateNewLetter(); + } + + markLettersToDelete() { + const tmpLetters = this.state.letters; + const tmpVisibleLetters = this.state.visibleLetters; + //console.log(tmpVisibleLetters); + //console.log(tmpLetters); + let f = false; + for (let i = 0; i < tmpVisibleLetters.length; i++) { + if (this.state.markedLetters[tmpVisibleLetters[i].id]) { + for (let j = 0; j < tmpLetters.length; j++) { + if (tmpLetters[j] == tmpVisibleLetters[i]){ + f = true; + tmpVisibleLetters[i].changeAnimation = true; + tmpLetters[j].changeAnimation = true; + } + } + } + } + this.setState(() => { + return { + isClearInput: f, + visibleLetters: tmpVisibleLetters, + letters: tmpLetters, + selectAll: false + }; + }); + } + + switchLetterCheckbox(id: number) { + const newMarkedLetters = this.state.markedLetters; + newMarkedLetters[id] = !newMarkedLetters[id]; + this.setState(() => { + return { markedLetters: newMarkedLetters }; + }); + } + + render() { + return ( +
    +
    + + +
    + ); + } +} diff --git a/src/app/mailInnerContent/scripts/letterGeneratorUtils.js b/src/app/mailInnerContent/scripts/letterGeneratorUtils.js new file mode 100644 index 0000000..2d2f0ae --- /dev/null +++ b/src/app/mailInnerContent/scripts/letterGeneratorUtils.js @@ -0,0 +1,95 @@ +const months = ['янв', 'фев', 'мар', 'апр', 'май', 'июн', 'июл', 'авг', 'сен', 'окт', 'ноя', 'дек']; + +const names = [ + 'Фотин', + 'Евтихий', + 'Азарий', + 'Фетис', + 'Полиевкт', + 'Борислав', + 'Кассиан', + 'Юст', + 'Мартьян', + 'Капитон', + 'Никандр', + 'Эрнест', + 'Петроний', + 'Иезекииль', + 'Харитон', + 'Севастиан', + 'Орест', + 'Вит', + 'Василий', + 'Гордей', + 'Максим', + 'Павлин', + 'Захар', + 'Владилен', + 'Наум', + 'Алипий', + 'Меркурий', + 'Феоктист', + 'Овдоким', + 'Феофил' +]; + +const surnames = [ + 'Чашников', + 'Березников', + 'Руликовский', + 'Ляпишев', + 'Оффенберг', + 'Шипов', + 'Арнаутов', + 'Машковцев', + 'Столыпин', + 'Шереметьев', + 'Яворский', + 'Рындин', + 'Лонгинов', + 'Ададуров', + 'Нечаев', + 'Габаев', + 'Маткевич', + 'Маковский', + 'Юрасовский', + 'Ващенко', + 'Кобылин', + 'Карандеев', + 'Золотарёв', + 'Голицын', + 'Игнатьев', + 'Байчуров', + 'Бурдуков', + 'Болтенков', + 'Михеев', + 'Храпов' +]; + +export const generateRandomCount = (from, to) => { + return Math.floor(Math.random() * (to - from) + from); +}; + +const getRandomObj = (array) => { + return array[generateRandomCount(0, array.length)]; +}; + +export const generateName = () => { + const name = getRandomObj(names); + const surname = getRandomObj(surnames); + return `${name} ${surname}`; +}; + +export const generateContent = async () => { + const paragraphsCount = generateRandomCount(1, 2); + + const text = await fetch( + `https://baconipsum.com/api/?type=meat&formaat=json¶s=${paragraphsCount}` + ); + return text.json(); +}; + +export const generateDate = () => { + const date = new Date(); + return `${date.getDate()} ${months[date.getMonth()]}`; +}; diff --git a/src/app/mailMenu/index.js b/src/app/mailMenu/index.js new file mode 100644 index 0000000..7451256 --- /dev/null +++ b/src/app/mailMenu/index.js @@ -0,0 +1 @@ +export * from './mailMenu'; diff --git a/src/app/mailMenu/mailMenu.module.css b/src/app/mailMenu/mailMenu.module.css new file mode 100644 index 0000000..0a08017 --- /dev/null +++ b/src/app/mailMenu/mailMenu.module.css @@ -0,0 +1,5 @@ +.mailMenu__actionsBlock { + width: 100%; + margin-top: 0; + margin-left: -30px; +} diff --git a/src/app/mailMenu/mailMenu.tsx b/src/app/mailMenu/mailMenu.tsx new file mode 100644 index 0000000..a808eb2 --- /dev/null +++ b/src/app/mailMenu/mailMenu.tsx @@ -0,0 +1,19 @@ +import *as React from 'react'; + +import styles from './mailMenu.module.css'; +import {Button} from '../button'; + +export class MailMenu extends React.Component { + render() { + return ( + + ); + } +} diff --git a/src/app/openLetter/index.js b/src/app/openLetter/index.js new file mode 100644 index 0000000..3406e12 --- /dev/null +++ b/src/app/openLetter/index.js @@ -0,0 +1 @@ +export * from './openLetter'; diff --git a/src/app/openLetter/openLetter.module.css b/src/app/openLetter/openLetter.module.css new file mode 100644 index 0000000..75c4932 --- /dev/null +++ b/src/app/openLetter/openLetter.module.css @@ -0,0 +1,48 @@ +.openLetter__close { + margin-top: 10px; + margin-right: 10px; + float: right; +} + +.allLetters { + display: inline-block; + width: 40%; +} + +.width { + width: 60%; + float: right; +} + +.openLetter__delLine { + text-decoration: none; +} + +.openLetter__cross { + width: 15px; + height: 15px; + margin-top: 20px; + margin-right: 10px; + float: right; + opacity: 0.15; +} + +.openLetter__textLetter { + margin: 30px; +} + +.openLetter__cross_dark { + width: 20px; + height: 20px; + margin-top: -8px; + margin-right: 10px; + background-color: #cccccc; + border-radius: 50%; + float: right; + opacity: 0.15; +} + +.openLetter__textLetter_dark { + margin: 30px; + color: #cccccc; +} diff --git a/src/app/openLetter/openLetter.tsx b/src/app/openLetter/openLetter.tsx new file mode 100644 index 0000000..f85385e --- /dev/null +++ b/src/app/openLetter/openLetter.tsx @@ -0,0 +1,64 @@ +import *as React from 'react'; + +import styles from './openLetter.module.css'; +import cross from '../images/cross.png'; +import classnames from 'classnames'; +import { ILetter } from '../letterTypes/letterTypes'; +import { LetterSmall } from '../LetterSmall/letterSmall'; + +interface IProps { + markedLetters: { [id: string]: boolean }; + switchLetterCheckbox: (id: number) => void; + openLetter: (text: string[]) => void; + deleteChosenLetter: (id: number) => void; + visibleLetters: ILetter[]; + contentLetter: string[]; + closeLetter: () => void; + isDark: boolean; +} + +export class OpenLetter extends React.Component { + constructor(props: IProps) { + super(props); + this.props = props; + } + + public readonly props: IProps; + + render() { + return ( +
    +
    + {this.props.visibleLetters.map(letter => { + return ( + + ); + })} +
    +
    + + + +
    {this.props.contentLetter.map((paragraph) => { + return

    {paragraph}

    ; + })}
    +
    +
    + ); + } +} diff --git a/src/app/search/index.js b/src/app/search/index.js new file mode 100644 index 0000000..5a2bdeb --- /dev/null +++ b/src/app/search/index.js @@ -0,0 +1 @@ +export * from './search'; diff --git a/src/app/search/search.module.css b/src/app/search/search.module.css new file mode 100644 index 0000000..7d55b6a --- /dev/null +++ b/src/app/search/search.module.css @@ -0,0 +1,32 @@ +.search { + display: inline-block; + width: 40%; + height: 32px; + margin-left: 14%; + background-color: #ffffff; + box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.2); + opacity: 0.5; + vertical-align: text-bottom; +} + +.search__textSearch { + width: 90%; + height: 100%; + padding-left: 10px; + + border: none; + -webkit-appearance: none; + background: none; + color: #000000; + font-size: 15px; + outline: none; +} + +.search__cross { + width: 9px; + height: 9px; + margin-top: 12px; + margin-right: 10px; + float: right; + opacity: 0.15; +} diff --git a/src/app/search/search.tsx b/src/app/search/search.tsx new file mode 100644 index 0000000..5d59da2 --- /dev/null +++ b/src/app/search/search.tsx @@ -0,0 +1,35 @@ +import *as React from 'react'; + +import styles from './search.module.css'; +import cross from '../images/cross.png'; + +interface IProps { + isClearInput: boolean; + search: (text: string) => void; +} + +export class Search extends React.Component { + public constructor(props: IProps) { + super(props); + this.props = props; + } + + public readonly props: IProps; + + render() { + return this.props.isClearInput ? ( +
    + this.props.search('')}/> + cross +
    + ) : ( +
    + this.props.search(text.target.value)}/> + cross +
    + ); + } +} diff --git a/src/app/txtStyle/HelveticaNeueCyr-Light.otf b/src/app/txtStyle/HelveticaNeueCyr-Light.otf new file mode 100644 index 0000000..7ced49a Binary files /dev/null and b/src/app/txtStyle/HelveticaNeueCyr-Light.otf differ diff --git a/src/app/txtStyle/HelveticaNeueCyr-Medium.otf b/src/app/txtStyle/HelveticaNeueCyr-Medium.otf new file mode 100644 index 0000000..a2cde16 Binary files /dev/null and b/src/app/txtStyle/HelveticaNeueCyr-Medium.otf differ diff --git a/src/app/txtStyle/YandexSansDisplay-Thin.ttf b/src/app/txtStyle/YandexSansDisplay-Thin.ttf new file mode 100644 index 0000000..3b8e196 Binary files /dev/null and b/src/app/txtStyle/YandexSansDisplay-Thin.ttf differ diff --git a/src/index.css b/src/index.css index 2b6e525..74897da 100644 --- a/src/index.css +++ b/src/index.css @@ -1,10 +1,5 @@ body { - padding: 0; - margin: 0; - font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', - 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; + background-color: #e5eaf0; } code { diff --git a/src/index.jsx b/src/index.tsx similarity index 62% rename from src/index.jsx rename to src/index.tsx index ffc72ee..4b7c423 100644 --- a/src/index.jsx +++ b/src/index.tsx @@ -1,5 +1,5 @@ -import React from 'react'; -import ReactDOM from 'react-dom'; +import *as React from 'react'; +import *as ReactDOM from 'react-dom'; import { App } from './app'; diff --git a/src/react-app-env.d.ts b/src/react-app-env.d.ts new file mode 100644 index 0000000..6431bc5 --- /dev/null +++ b/src/react-app-env.d.ts @@ -0,0 +1 @@ +///