├── .dockerignore ├── .editorconfig ├── .gitattributes ├── .gitignore ├── .prettierrc ├── .travis.yml ├── CONTRIBUTING.md ├── Dockerfile ├── LICENSE ├── README.md ├── config └── tslint.js ├── lerna.json ├── package.json ├── packages ├── storybook │ ├── addons.js │ ├── config.js │ ├── package.json │ ├── tsconfig.json │ └── webpack.config.js ├── theme-parser │ ├── .gitignore │ ├── package.json │ ├── src │ │ ├── __tests__ │ │ │ ├── __snapshots__ │ │ │ │ └── index.test.ts.snap │ │ │ └── index.test.ts │ │ ├── color-value.ts │ │ ├── color.ts │ │ ├── index.h.ts │ │ ├── index.ts │ │ ├── map-links.ts │ │ ├── omit-comment.ts │ │ ├── parser.ts │ │ └── split-kv.ts │ └── tsconfig.json └── treact │ ├── .babelrc │ ├── .gitattributes │ ├── .gitignore │ ├── .scripts │ ├── cleanup.sh │ ├── gen-themes.ts │ ├── tsconfig.json │ └── update-themes.ts │ ├── .stylelintrc │ ├── .travis.yml │ ├── CONTRIBUTING.md │ ├── README.md │ ├── build │ └── index.html │ ├── config │ ├── index.html │ ├── main.js │ ├── test │ │ └── karma.conf.js │ ├── types │ │ ├── dev.d.ts │ │ ├── google-react-map.d.ts │ │ ├── normalizr.d.ts │ │ ├── react-autosize-textarea.d.ts │ │ ├── recompose.d.ts │ │ ├── redux-act.d.ts │ │ ├── universal-router-react.d.ts │ │ └── universal-router.d.ts │ └── webpack │ │ ├── dev.js │ │ ├── index.js │ │ ├── prod.js │ │ ├── server.js │ │ ├── test.js │ │ └── vendor.js │ ├── package.json │ ├── postcss.config.js │ ├── src │ ├── __mocks__ │ │ └── fileMock.js │ ├── app │ │ ├── components │ │ │ ├── App │ │ │ │ ├── __snapshots__ │ │ │ │ │ └── index.test.tsx.snap │ │ │ │ ├── index.test.tsx │ │ │ │ ├── index.tsx │ │ │ │ └── style.css │ │ │ ├── AutoSizeTextarea │ │ │ │ └── index.tsx │ │ │ ├── Chat │ │ │ │ ├── index.tsx │ │ │ │ ├── scroll.ts │ │ │ │ └── style.css │ │ │ ├── ChatFooter │ │ │ │ ├── __snapshots__ │ │ │ │ │ └── index.test.tsx.snap │ │ │ │ ├── index.test.tsx │ │ │ │ └── index.tsx │ │ │ ├── ChatList │ │ │ │ ├── __snapshots__ │ │ │ │ │ └── index.test.tsx.snap │ │ │ │ ├── index.test.tsx │ │ │ │ ├── index.tsx │ │ │ │ └── style.css │ │ │ ├── ChatListItem │ │ │ │ ├── index.tsx │ │ │ │ ├── style.ts │ │ │ │ └── usercolor1.png │ │ │ ├── ChatListSearch │ │ │ │ ├── __snapshots__ │ │ │ │ │ └── index.test.tsx.snap │ │ │ │ ├── index.test.tsx │ │ │ │ ├── index.tsx │ │ │ │ ├── pencil.png │ │ │ │ ├── search.png │ │ │ │ └── style.css │ │ │ ├── ChatMessage │ │ │ │ ├── index.tsx │ │ │ │ └── style.css │ │ │ ├── Header │ │ │ │ ├── index.tsx │ │ │ │ ├── style.css │ │ │ │ └── title-logo.png │ │ │ ├── InfiniteScroll │ │ │ │ └── index.tsx │ │ │ ├── InstantMessages │ │ │ │ ├── index.tsx │ │ │ │ └── style.css │ │ │ ├── LocationMap │ │ │ │ ├── index.h.ts │ │ │ │ └── index.tsx │ │ │ ├── Login │ │ │ │ ├── index.tsx │ │ │ │ ├── steps │ │ │ │ │ ├── AuthCode.tsx │ │ │ │ │ ├── Intro │ │ │ │ │ │ ├── icon102.png │ │ │ │ │ │ ├── index.tsx │ │ │ │ │ │ └── style.css │ │ │ │ │ ├── Password.tsx │ │ │ │ │ ├── PhoneNumber │ │ │ │ │ │ ├── index.tsx │ │ │ │ │ │ └── style.ts │ │ │ │ │ └── index.ts │ │ │ │ └── style.css │ │ │ ├── Media │ │ │ │ ├── index.tsx │ │ │ │ ├── preview.tsx │ │ │ │ └── types.tsx │ │ │ ├── Message │ │ │ │ ├── index.tsx │ │ │ │ └── style.css │ │ │ ├── MessageGroup │ │ │ │ └── index.tsx │ │ │ ├── PeerPhoto │ │ │ │ ├── __snapshots__ │ │ │ │ │ └── index.test.tsx.snap │ │ │ │ ├── index.test.tsx │ │ │ │ ├── index.tsx │ │ │ │ └── usercolor1.png │ │ │ ├── RichText │ │ │ │ ├── __snapshots__ │ │ │ │ │ └── index.test.tsx.snap │ │ │ │ ├── index.test.tsx │ │ │ │ ├── index.tsx │ │ │ │ └── parser.ts │ │ │ ├── Time │ │ │ │ └── index.tsx │ │ │ ├── components.stories.tsx │ │ │ └── index.tsx │ │ ├── containers │ │ │ ├── App │ │ │ │ └── index.tsx │ │ │ ├── Chat │ │ │ │ └── index.tsx │ │ │ ├── ChatFooter │ │ │ │ └── index.tsx │ │ │ ├── ChatList │ │ │ │ └── index.tsx │ │ │ ├── ChatListItem │ │ │ │ └── index.tsx │ │ │ ├── Header │ │ │ │ └── index.tsx │ │ │ ├── Home │ │ │ │ └── index.tsx │ │ │ ├── InstantMessages │ │ │ │ ├── downloadAssistant.tsx │ │ │ │ └── index.tsx │ │ │ ├── Login │ │ │ │ ├── index.tsx │ │ │ │ └── steps │ │ │ │ │ ├── AuthCode │ │ │ │ │ └── index.tsx │ │ │ │ │ ├── Password │ │ │ │ │ └── index.tsx │ │ │ │ │ ├── PhoneNumber │ │ │ │ │ └── index.tsx │ │ │ │ │ ├── Success │ │ │ │ │ └── index.tsx │ │ │ │ │ └── index.ts │ │ │ ├── Media │ │ │ │ ├── index.h.ts │ │ │ │ ├── index.tsx │ │ │ │ ├── photoSizesAssistant.tsx │ │ │ │ ├── selector.test.ts │ │ │ │ └── selector.ts │ │ │ ├── PeerName │ │ │ │ └── index.tsx │ │ │ ├── PeerPhoto │ │ │ │ └── index.tsx │ │ │ └── index.tsx │ │ ├── helpers │ │ │ ├── FileManager │ │ │ │ ├── IdbFileStorage.ts │ │ │ │ ├── MemoryFileStorage.ts │ │ │ │ ├── TmpfsFileStorage.ts │ │ │ │ ├── __mocks__ │ │ │ │ │ └── picStore.ts │ │ │ │ ├── index.ts │ │ │ │ ├── picStore.ts │ │ │ │ └── usercolor1.png │ │ │ ├── Telegram │ │ │ │ ├── Chats │ │ │ │ │ └── index.ts │ │ │ │ ├── Files │ │ │ │ │ └── index.ts │ │ │ │ ├── Messages │ │ │ │ │ └── index.ts │ │ │ │ ├── Peers │ │ │ │ │ └── index.ts │ │ │ │ ├── Updates │ │ │ │ │ ├── HttpLoopEmitter.ts │ │ │ │ │ └── index.ts │ │ │ │ ├── api-tlschema-57.json │ │ │ │ ├── config.ts │ │ │ │ ├── connection.ts │ │ │ │ ├── constants.ts │ │ │ │ ├── helpers.ts │ │ │ │ ├── index.ts │ │ │ │ ├── pool.ts │ │ │ │ └── publickeys.ts │ │ │ ├── reselector.h.ts │ │ │ ├── reselector.ts │ │ │ └── state.ts │ │ ├── routes │ │ │ └── index.tsx │ │ ├── store │ │ │ ├── actions.ts │ │ │ ├── api │ │ │ │ ├── auth.ts │ │ │ │ ├── chatList.ts │ │ │ │ ├── messages.ts │ │ │ │ └── theme.ts │ │ │ ├── batchUpdate.ts │ │ │ ├── domain.ts │ │ │ ├── effector-redux.ts │ │ │ ├── events.ts │ │ │ ├── modules │ │ │ │ ├── auth │ │ │ │ │ └── index.ts │ │ │ │ ├── authKey │ │ │ │ │ └── index.ts │ │ │ │ ├── avatars │ │ │ │ │ ├── index.ts │ │ │ │ │ └── reducer.ts │ │ │ │ ├── chats │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── reducer.ts │ │ │ │ │ └── shape.ts │ │ │ │ ├── currentDc │ │ │ │ │ └── index.ts │ │ │ │ ├── currentUser │ │ │ │ │ └── index.ts │ │ │ │ ├── dialogs │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── reducer.ts │ │ │ │ │ └── shape.ts │ │ │ │ ├── documents │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── preprocess.ts │ │ │ │ │ ├── reducer.ts │ │ │ │ │ └── shape.ts │ │ │ │ ├── files │ │ │ │ │ ├── entities.ts │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── locations.ts │ │ │ │ │ ├── reducer.ts │ │ │ │ │ ├── shape.ts │ │ │ │ │ └── status.ts │ │ │ │ ├── histories │ │ │ │ │ ├── index.ts │ │ │ │ │ └── reducer.ts │ │ │ │ ├── loadings │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── reducer.ts │ │ │ │ │ └── shape.ts │ │ │ │ ├── media │ │ │ │ │ ├── entities.ts │ │ │ │ │ └── index.ts │ │ │ │ ├── messages │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── reducer.ts │ │ │ │ │ └── shape.ts │ │ │ │ ├── peers │ │ │ │ │ ├── index.ts │ │ │ │ │ └── reducer.ts │ │ │ │ ├── photos │ │ │ │ │ ├── cachedSizes.ts │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── preprocess.ts │ │ │ │ │ └── sizes.ts │ │ │ │ ├── selected │ │ │ │ │ ├── index.ts │ │ │ │ │ └── reducer.ts │ │ │ │ ├── settings │ │ │ │ │ ├── index.ts │ │ │ │ │ └── shape.ts │ │ │ │ ├── theme │ │ │ │ │ ├── actions.ts │ │ │ │ │ ├── domain.ts │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── reducer.ts │ │ │ │ │ └── shape.ts │ │ │ │ └── users │ │ │ │ │ ├── index.ts │ │ │ │ │ └── reducer.ts │ │ │ ├── mtproto.h.ts │ │ │ ├── mtproto.ts │ │ │ ├── reducers.ts │ │ │ ├── store.h.ts │ │ │ └── store.ts │ │ └── themes │ │ │ ├── UserSelectedTheme.tsx │ │ │ ├── default │ │ │ ├── background.jpg │ │ │ └── index.ts │ │ │ ├── night │ │ │ ├── index.ts │ │ │ └── tiled.jpg │ │ │ └── theme.h.ts │ ├── client.tsx │ ├── history.ts │ └── vendor │ │ ├── app.css │ │ ├── containers │ │ └── Link.tsx │ │ ├── font.css │ │ └── main.ts │ ├── tsconfig.json │ └── webpack.config.js ├── screenshot.png ├── tslint.json ├── types └── ramda.d.ts └── yarn.lock /.dockerignore: -------------------------------------------------------------------------------- 1 | # Build Folder 2 | build 3 | 4 | # Logs 5 | logs 6 | *.log 7 | npm-debug.log* 8 | 9 | # Runtime data 10 | pids 11 | *.pid 12 | *.seed 13 | 14 | # Directory for instrumented libs generated by jscoverage/JSCover 15 | lib-cov 16 | 17 | # Coverage directory used by tools like istanbul 18 | coverage 19 | 20 | # node-waf configuration 21 | .lock-wscript 22 | 23 | # Compiled binary addons (http://nodejs.org/api/addons.html) 24 | build/Release 25 | 26 | # Dependency directory 27 | node_modules 28 | 29 | # Optional npm cache directory 30 | .npm 31 | 32 | # Optional REPL history 33 | .node_repl_history 34 | 35 | # OS X 36 | .DS_STORE 37 | 38 | # TypeScript 39 | typings 40 | 41 | # Git 42 | .git -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig helps developers define and maintain consistent 2 | # coding styles between different editors and IDEs 3 | # editorconfig.org 4 | 5 | root = true 6 | 7 | [*] 8 | 9 | # Change these settings to your own preference 10 | indent_style = space 11 | indent_size = 2 12 | 13 | # We recommend you to keep these unchanged 14 | end_of_line = lf 15 | charset = utf-8 16 | trim_trailing_whitespace = true 17 | insert_final_newline = true 18 | 19 | [*.md] 20 | trim_trailing_whitespace = false 21 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # 2 | ## These files are binary and should be left untouched 3 | # 4 | 5 | # (binary is a macro for -text -diff) 6 | *.png binary 7 | *.jpg binary 8 | *.jpeg binary 9 | *.gif binary 10 | *.ico binary 11 | *.mov binary 12 | *.mp4 binary 13 | *.mp3 binary 14 | *.flv binary 15 | *.fla binary 16 | *.swf binary 17 | *.gz binary 18 | *.zip binary 19 | *.7z binary 20 | *.ttf binary 21 | *.eot binary 22 | *.woff binary 23 | *.pyc binary 24 | *.pdf binary 25 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Build Folder 2 | build/* 3 | !build/index.html 4 | gh-pages 5 | 6 | # Logs 7 | logs 8 | *.log 9 | npm-debug.log* 10 | 11 | # Runtime data 12 | pids 13 | *.pid 14 | *.seed 15 | 16 | # Directory for instrumented libs generated by jscoverage/JSCover 17 | lib-cov 18 | 19 | # Coverage directory used by tools like istanbul 20 | coverage 21 | 22 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 23 | .grunt 24 | 25 | # node-waf configuration 26 | .lock-wscript 27 | 28 | # Compiled binary addons (http://nodejs.org/api/addons.html) 29 | build/Release 30 | 31 | # Dependency directory 32 | node_modules 33 | 34 | # Optional npm cache directory 35 | .npm 36 | 37 | # Optional REPL history 38 | .node_repl_history 39 | 40 | # OS X 41 | .DS_STORE 42 | 43 | # TypeScript 44 | typings 45 | typings.json 46 | 47 | # JetBrains 48 | .idea 49 | 50 | # Visual Studio Code 51 | .vscode 52 | .history 53 | 54 | packages/TreactNative 55 | packages/test-comp 56 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "semi": false, 3 | "singleQuote": true, 4 | "trailingComma": "all" 5 | } -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "7" 4 | - "node" 5 | env: 6 | - NODE_ENV=ci 7 | cache: 8 | directories: 9 | - node_modules 10 | install: 11 | - lerna bootstrap --hoist 12 | before_script: 13 | - "export DISPLAY=:99.0" 14 | - "sh -e /etc/init.d/xvfb start" 15 | script: 16 | - lerna run --scope treact build:vendor 17 | - lerna run build 18 | - lerna run test 19 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM mhart/alpine-node:latest 2 | 3 | MAINTAINER goodmind andwebar@gmail.com 4 | 5 | WORKDIR /app 6 | ADD . . 7 | 8 | RUN npm install 9 | 10 | EXPOSE 8889 11 | 12 | CMD ["npm", "run", "start:prod"] 13 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | Copyright (c) 2016 Barbar Startup Factory 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Telegram React 2 | [![Build Status](https://travis-ci.org/barbar/vortigern.svg?branch=master)](https://travis-ci.org/barbar/vortigern) 3 | [![Dependency Status](https://david-dm.org/barbar/vortigern.svg)]() 4 | [![devDependency Status](https://david-dm.org/barbar/vortigern/dev-status.svg)]() 5 | [![Code Climate](https://codeclimate.com/github/barbar/vortigern/badges/gpa.svg)](https://codeclimate.com/github/barbar/vortigern) 6 | [![GitHub issues](https://img.shields.io/github/issues/barbar/vortigern.svg)](https://github.com/barbar/vortigern/issues) 7 | [![GitHub license](https://img.shields.io/badge/license-MIT-blue.svg)](https://raw.githubusercontent.com/barbar/vortigern/develop/LICENSE) 8 | ___ 9 | 10 | **Work in progress** 11 | 12 | Contact me in telegram [@goodmind](https://telegram.me/goodmind) 13 | 14 | ![treact](screenshot.png) 15 | 16 | [![TypeScript](https://barbaruploads.s3.amazonaws.com/bicoz/typescript.png)](https://www.typescriptlang.org/) 17 | [![React](https://barbaruploads.s3.amazonaws.com/bicoz/react.png)](https://github.com/facebook/react) 18 | [![Redux](https://barbaruploads.s3.amazonaws.com/bicoz/redux.png)](https://github.com/reactjs/redux) 19 | 20 | ## Installation 21 | 22 | You can clone from this repository 23 | 24 | ```bash 25 | $ git clone https://github.com/goodmind/treact 26 | $ cd treact 27 | $ cd packages/theme-parser && yarn build 28 | $ cd packages/treact && yarn start:dev 29 | ``` 30 | 31 | ## Usage 32 | 33 | All commands defaults to development environment. You can set `NODE_ENV` to `production` or use the shortcuts below. 34 | 35 | ```bash 36 | # Running 37 | 38 | $ yarn start # This starts the app in development mode 39 | 40 | # Starting it with the production build 41 | $ NODE_ENV=production yarn start # or 42 | $ yarn start:prod 43 | 44 | # Building 45 | 46 | $ yarn build # This builds the app in development mode 47 | 48 | # Commands below builds the production build 49 | $ NODE_ENV=production yarn build # or 50 | $ yarn build:prod 51 | 52 | # Testing 53 | $ yarn test 54 | ``` 55 | 56 | ## Credits 57 | 58 | TReact is released under the [MIT license](LICENSE). 59 | -------------------------------------------------------------------------------- /config/tslint.js: -------------------------------------------------------------------------------- 1 | const tsRules = { 2 | 'interface-name': [ 3 | true, 4 | 'never-prefix', 5 | ], 6 | 'no-non-null-assertion': true, 7 | 'no-any': true, 8 | //'no-unsafe-any': true, 9 | //'no-inferred-empty-object-type': true, 10 | 'no-var-requires': true, 11 | } 12 | 13 | const jsRules = { 14 | 'indent': [ 15 | true, 16 | 'spaces', 17 | 2, 18 | ], 19 | 'quotemark': [ 20 | true, 21 | 'single', 22 | 'jsx-double', 23 | ], 24 | 'semicolon': [ 25 | true, 26 | 'never', 27 | ], 28 | 'ordered-imports': [], 29 | 'member-ordering': [ 30 | false, 31 | ], 32 | 'no-console': [ 33 | false, 34 | ], 35 | 'jsx-alignment': [ 36 | false, 37 | ], 38 | 'no-empty-interface': [ 39 | false, 40 | ], 41 | 'space-before-function-paren': [ 42 | false, 43 | ], 44 | 'no-consecutive-blank-lines': [ 45 | false, , 46 | ], 47 | 'max-classes-per-file': [ 48 | false, , 49 | ], 50 | 'comment-format': [ 51 | false, , 52 | ], 53 | /*'no-submodule-imports': [ 54 | true, 55 | 'containers', 56 | 'components', 57 | 'redux', 58 | 'helpers', 59 | 'api', 60 | 'themes', 61 | 'modules', 62 | ],*/ 63 | 'no-submodule-imports': false, 64 | 'arrow-parens': false, 65 | 'object-literal-sort-keys': false, 66 | 'object-literal-key-quotes': [false], 67 | 'no-shadowed-variable': false, 68 | 'interface-over-type-literal': false, 69 | 'prefer-const': true, 70 | 'curly': false, 71 | 'no-bitwise': false, 72 | 'jsx-no-multiline-js': false, 73 | 'jsx-boolean-value': false, 74 | 'jsx-wrap-multiline': false, 75 | 'prefer-object-spread': false, 76 | 'no-implicit-dependencies': false, 77 | } 78 | 79 | module.exports = { 80 | extends: [ 81 | 'tslint:latest', 82 | 'tslint-react', 83 | ], 84 | lintOptions: { 85 | typeCheck: true, 86 | }, 87 | rules: Object.assign({}, tsRules, jsRules), 88 | jsRules, 89 | } 90 | -------------------------------------------------------------------------------- /lerna.json: -------------------------------------------------------------------------------- 1 | { 2 | "lerna": "2.9.0", 3 | "packages": [ 4 | "packages/*" 5 | ], 6 | "version": "independent" 7 | } 8 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "name": "treact", 4 | "version": "0.1.0", 5 | "devDependencies": { 6 | "lerna": "^2.9.0" 7 | }, 8 | "_________": { 9 | "nohoist": [ 10 | "**/react-native", 11 | "**/react-native/**", 12 | "**/treact", 13 | "**/@treact/web", 14 | "**/@treact/theme-parser", 15 | "TreactNative/react-native-*", 16 | "TreactNative/react-native-*/**", 17 | "TreactNative/vm-browserify", 18 | "TreactNative/vm-browserify/**" 19 | ] 20 | }, 21 | "workspaces": { 22 | "packages": [ 23 | "packages/theme-parser", 24 | "packages/treact", 25 | "packages/storybook" 26 | ] 27 | }, 28 | "resolutions": { 29 | "**/worker-loader": "2.0.0" 30 | }, 31 | "dependencies": { 32 | "ramda": "^0.25.0" 33 | }, 34 | "scripts": { 35 | "reset-modules": "rm -rf node_modules/ yarn.lock packages/*/node_modules", 36 | "reset-yarn": "yarn cache clean", 37 | "reset-rn": "watchman watch-del-all; rm -fr $TMPDIR/react-*; rm -rf $TMPDIR/haste-map-react-native-packager-*", 38 | "reset-cache": "yarn reset-yarn && yarn reset-rn", 39 | "reset": "yarn reset-modules && yarn reset-cache" 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /packages/storybook/addons.js: -------------------------------------------------------------------------------- 1 | import '@storybook/addon-knobs/register' 2 | -------------------------------------------------------------------------------- /packages/storybook/config.js: -------------------------------------------------------------------------------- 1 | import { configure } from '@storybook/react' 2 | 3 | function importAll(r) { 4 | r.keys().forEach(r) 5 | } 6 | 7 | function loadStories() { 8 | importAll(require.context('app', true, /\.stories\.tsx$/)) 9 | } 10 | 11 | configure(loadStories, module) 12 | -------------------------------------------------------------------------------- /packages/storybook/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@treact/storybook", 3 | "version": "0.1.0", 4 | "scripts": { 5 | "storybook": "start-storybook -p 6006 -c ." 6 | }, 7 | "devDependencies": { 8 | "@storybook/addon-knobs": "^3.4.8", 9 | "@storybook/addons": "^3.4.8", 10 | "@storybook/react": "^3.4.8", 11 | "@types/storybook__addon-knobs": "^3.3.1", 12 | "@types/storybook__react": "^3.0.7", 13 | "css-loader": "^0.28.7", 14 | "file-loader": "^1.1.5", 15 | "fork-ts-checker-webpack-plugin": "^0.4.3", 16 | "hard-source-webpack-plugin": "^0.11.2", 17 | "postcss-loader": "^2.0.6", 18 | "source-map-loader": "^0.2.1", 19 | "style-loader": "^0.18.2", 20 | "ts-loader": "^3.5.0", 21 | "tsconfig-paths-webpack-plugin": "2.0.0", 22 | "tslint": "^5.9.1", 23 | "typescript": "^2.6.2", 24 | "url-loader": "^0.6.2", 25 | "webpack": "^3.11.0" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /packages/storybook/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "baseUrl": ".", 4 | "paths": { 5 | "*": ["../treact/src/app/*", "../treact/src/app/store/*"] 6 | }, 7 | "declaration": true, 8 | "module": "esnext", 9 | "target": "es2015", 10 | "pretty": true, 11 | "sourceMap": true, 12 | "inlineSourceMap": false, 13 | "inlineSources": false, 14 | "experimentalDecorators": true, 15 | "noUnusedParameters": true, 16 | "noUnusedLocals": true, 17 | "strict": true, 18 | "jsx": "react", 19 | "moduleResolution": "node", 20 | "lib": ["es2015", "dom"] 21 | }, 22 | "include": ["../../types/ramda.d.ts", "src"], 23 | "exclude": ["node_modules"] 24 | } 25 | -------------------------------------------------------------------------------- /packages/theme-parser/.gitignore: -------------------------------------------------------------------------------- 1 | lib 2 | node_modules 3 | -------------------------------------------------------------------------------- /packages/theme-parser/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@treact/theme-parser", 3 | "version": "0.1.0", 4 | "description": "Telegram Desktop theme parser", 5 | "typings": "lib/index.d.ts", 6 | "main": "lib/index.js", 7 | "publishConfig": { 8 | "access": "public" 9 | }, 10 | "files": [ 11 | "lib" 12 | ], 13 | "jest": { 14 | "globals": { 15 | "ts-jest": { 16 | "skipBabel": false 17 | } 18 | }, 19 | "transform": { 20 | "^.+\\.tsx?$": "/node_modules/ts-jest/preprocessor.js" 21 | }, 22 | "testRegex": "(/__tests__/.*|\\.(test|spec))\\.(ts|tsx|js)$", 23 | "moduleDirectories": [ 24 | "node_modules", 25 | "/src" 26 | ], 27 | "moduleFileExtensions": [ 28 | "ts", 29 | "tsx", 30 | "js", 31 | "json" 32 | ] 33 | }, 34 | "scripts": { 35 | "test": "jest", 36 | "build": "tsc", 37 | "prepublishOnly": "npm run build" 38 | }, 39 | "author": "goodmind ", 40 | "contributors": [ 41 | { 42 | "name": "goodmind", 43 | "email": "andwebar@gmail.com" 44 | }, 45 | { 46 | "name": "Zero Bias", 47 | "email": "ribkatt@gmail.com" 48 | } 49 | ], 50 | "homepage": "https://github.com/goodmind/treact.git", 51 | "repository": { 52 | "type": "git", 53 | "url": "https://github.com/goodmind/treact.git" 54 | }, 55 | "bugs": { 56 | "url": "https://github.com/goodmind/treact/issues" 57 | }, 58 | "license": "MIT", 59 | "dependencies": { 60 | "ramda": "^0.25.0" 61 | }, 62 | "devDependencies": {} 63 | } 64 | -------------------------------------------------------------------------------- /packages/theme-parser/src/color-value.ts: -------------------------------------------------------------------------------- 1 | 2 | import { map, pipe, splitEvery } from 'ramda' 3 | 4 | export default class Color { 5 | private data: Uint8ClampedArray 6 | get r(): number { 7 | return this.data[0] 8 | } 9 | get g(): number { 10 | return this.data[1] 11 | } 12 | get b(): number { 13 | return this.data[2] 14 | } 15 | get a(): number { 16 | return this.data[3] 17 | } 18 | constructor(data: number[]) { 19 | if (data.length !== 4) { 20 | throw new TypeError(`Color data error: ${data} should have length 4`) 21 | } 22 | this.data = Uint8ClampedArray.from(data) 23 | } 24 | 25 | public toString() { 26 | return `rgba(${this.r}, ${this.g}, ${this.b}, ${+(this.a / 255).toFixed(2)})` 27 | } 28 | public inspect() { 29 | return `Color ${this.toString()}` 30 | } 31 | 32 | public static of(color: string) { 33 | return new Color(fromString(color)) 34 | } 35 | } 36 | 37 | const fromString: (str: string) => number[] = pipe( 38 | splitEvery(2), 39 | map(color => parseInt(color, 16)), 40 | ) 41 | -------------------------------------------------------------------------------- /packages/theme-parser/src/color.ts: -------------------------------------------------------------------------------- 1 | import { 2 | contains, 3 | equals, 4 | head, 5 | map, 6 | pipe, 7 | split, 8 | tail, 9 | trim, 10 | when, 11 | } from 'ramda' 12 | import { 13 | Splitter, 14 | StringPred, 15 | } from './index.h' 16 | 17 | import Color from './color-value' 18 | 19 | // TODO: make better types 20 | const onSecond = (fn: (a: T) => S) => 21 | // tslint:disable-next-line 22 | ([l, t, ...rest]: any[]): (L|T|S) & any => [l, fn(t), ...rest]; 23 | const isPair: StringPred = contains('|') 24 | const splitPair: Splitter = pipe(split('|'), map(trim)) 25 | const isColor: StringPred = pipe(head, equals('#')) 26 | 27 | const getColorObj: (str: string) => Color = 28 | pipe(tail, (str: string) => { 29 | switch (str.length) { 30 | case 6: { 31 | return Color.of(str + 'ff') 32 | } 33 | case 8: { 34 | return Color.of(str) 35 | } 36 | default: { 37 | throw new TypeError(`Unexpected color value ${str}`) 38 | } 39 | } 40 | }) 41 | 42 | 43 | const arrify = (str: string) => isPair(str) 44 | ? splitPair(str) 45 | : [str] 46 | 47 | const transformColors: (str: string) => string | Color = when(isColor, getColorObj) 48 | 49 | const processing = pipe( 50 | map(onSecond(arrify)), 51 | map<[string, string[]], [string, Array]>( 52 | onSecond>(map(transformColors))), 53 | ) 54 | 55 | export default processing 56 | -------------------------------------------------------------------------------- /packages/theme-parser/src/index.h.ts: -------------------------------------------------------------------------------- 1 | export type StringPred = (str: string) => boolean 2 | export type Splitter = (str: string) => string[] 3 | export type StringChange = (str: string) => string 4 | export type ListChange = (list: string[]) => string[] 5 | export type TokenHandler = { 6 | isOnly: StringPred, 7 | apply: StringChange, 8 | } 9 | -------------------------------------------------------------------------------- /packages/theme-parser/src/index.ts: -------------------------------------------------------------------------------- 1 | 2 | export { parseWithDefaults, processingToObject } from './map-links' 3 | export { parser } from './parser' 4 | export { default as Color } from './color-value' 5 | export { InputPair } from './map-links' 6 | 7 | import resolver from './map-links' 8 | 9 | export default resolver 10 | -------------------------------------------------------------------------------- /packages/theme-parser/src/omit-comment.ts: -------------------------------------------------------------------------------- 1 | 2 | import { 3 | append, 4 | contains, 5 | equals, 6 | head, 7 | last, 8 | map, 9 | pipe, 10 | reduce, 11 | split, 12 | take, 13 | takeLast, 14 | } from 'ramda' 15 | import { 16 | ListChange, 17 | StringChange, 18 | StringPred, 19 | TokenHandler, 20 | } from './index.h' 21 | 22 | const isBeginWith: (word: string) => StringPred = word => pipe( 23 | take(word.length), 24 | equals(word), 25 | ) 26 | 27 | const callHandler: (handler: TokenHandler) => StringChange = 28 | handler => str => 29 | handler.isOnly(str) 30 | ? '' 31 | : handler.apply(str) 32 | 33 | const lineComment: StringChange = callHandler({ 34 | isOnly: isBeginWith('//'), 35 | apply : pipe(split('//'), head), 36 | }) 37 | 38 | const mlCommentL: StringChange = callHandler({ 39 | isOnly: isBeginWith('/*'), 40 | apply : pipe(split('/*'), head), 41 | }) 42 | 43 | const mlCommentR: StringChange = callHandler({ 44 | isOnly: pipe(takeLast(2), equals('*/')), 45 | apply : pipe(split('*/'), t => last(t)), 46 | }) 47 | 48 | const semi: StringChange = callHandler({ 49 | isOnly: isBeginWith(';'), 50 | apply : pipe(split(';'), head), 51 | }) 52 | 53 | type OmitMLAcc = { list: string[], comment: boolean } 54 | const omitMLComments: (list: string[]) => string[] = pipe( 55 | reduce(({ list, comment }: OmitMLAcc, str: string) => { 56 | if (comment) { 57 | if (contains('*/', str)) 58 | return { 59 | list: append(mlCommentR(str), list), 60 | comment: false, 61 | } 62 | return { list, comment } 63 | } 64 | if (contains('/*', str)) 65 | return { 66 | list: append(mlCommentL(str), list), 67 | comment: true, 68 | } 69 | return { 70 | list: append(str, list), 71 | comment, 72 | } 73 | }, { list: [], comment: false }), 74 | x => x.list, 75 | ) 76 | 77 | 78 | const omitComment: ListChange = pipe( 79 | map(lineComment), 80 | omitMLComments, 81 | map(semi), 82 | ) 83 | 84 | export default omitComment 85 | -------------------------------------------------------------------------------- /packages/theme-parser/src/parser.ts: -------------------------------------------------------------------------------- 1 | import { isEmpty, pipe, reject, split } from 'ramda' 2 | import color from './color' 3 | import Color from './color-value' 4 | import omitComment from './omit-comment' 5 | import splitKV from './split-kv' 6 | 7 | export type Parser = (text: string) => Array<[string, Array]> 8 | 9 | export const parser: Parser = pipe( 10 | split(`\n`), 11 | omitComment, 12 | reject(isEmpty), 13 | splitKV, 14 | color, 15 | ) 16 | 17 | export default parser 18 | -------------------------------------------------------------------------------- /packages/theme-parser/src/split-kv.ts: -------------------------------------------------------------------------------- 1 | import { 2 | all, 3 | both, 4 | contains, 5 | filter, 6 | is, 7 | map, 8 | pipe, 9 | split, 10 | trim, 11 | } from 'ramda' 12 | import { 13 | StringPred, 14 | } from './index.h' 15 | 16 | const checkString: StringPred = both( 17 | is(String), 18 | str => str.length > 0, 19 | ) 20 | 21 | const process: (x: string[]) => string[][] = pipe( 22 | filter(contains(':')), 23 | map(split(':')), 24 | map(map(trim)), 25 | filter(all(checkString)), 26 | ) 27 | 28 | export default process 29 | -------------------------------------------------------------------------------- /packages/theme-parser/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "baseUrl": ".", 4 | "outDir": "lib", 5 | "declaration": true, 6 | "module": "esnext", 7 | "target": "es2015", 8 | "pretty": true, 9 | "sourceMap": true, 10 | "inlineSourceMap": false, 11 | "inlineSources": false, 12 | "experimentalDecorators": true, 13 | "noUnusedParameters": true, 14 | "noUnusedLocals": true, 15 | "strict": true, 16 | "moduleResolution": "node", 17 | "lib": [ 18 | "es2015", 19 | "dom" 20 | ] 21 | }, 22 | "include": [ 23 | "../../types/ramda.d.ts", 24 | "src" 25 | ], 26 | "exclude": [ 27 | "node_modules", 28 | "src/__tests__", 29 | "lib" 30 | ] 31 | } 32 | -------------------------------------------------------------------------------- /packages/treact/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | //["es2015", {"modules": false}] 4 | ], 5 | "plugins": [ 6 | // "react-hot-loader/babel", 7 | "dynamic-import-webpack", 8 | "transform-async-to-generator" 9 | ], 10 | "env": { 11 | "development": { 12 | "plugins": [ 13 | "glamorous-displayname" 14 | ] 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /packages/treact/.gitattributes: -------------------------------------------------------------------------------- 1 | # 2 | ## These files are binary and should be left untouched 3 | # 4 | 5 | # (binary is a macro for -text -diff) 6 | *.png binary 7 | *.jpg binary 8 | *.jpeg binary 9 | *.gif binary 10 | *.ico binary 11 | *.mov binary 12 | *.mp4 binary 13 | *.mp3 binary 14 | *.flv binary 15 | *.fla binary 16 | *.swf binary 17 | *.gz binary 18 | *.zip binary 19 | *.7z binary 20 | *.ttf binary 21 | *.eot binary 22 | *.woff binary 23 | *.pyc binary 24 | *.pdf binary 25 | -------------------------------------------------------------------------------- /packages/treact/.gitignore: -------------------------------------------------------------------------------- 1 | # Build Folder 2 | build/* 3 | !build/index.html 4 | gh-pages 5 | 6 | # Logs 7 | logs 8 | *.log 9 | npm-debug.log* 10 | 11 | # Runtime data 12 | pids 13 | *.pid 14 | *.seed 15 | 16 | # Directory for instrumented libs generated by jscoverage/JSCover 17 | lib-cov 18 | 19 | # Coverage directory used by tools like istanbul 20 | coverage 21 | 22 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 23 | .grunt 24 | 25 | # node-waf configuration 26 | .lock-wscript 27 | 28 | # Compiled binary addons (http://nodejs.org/api/addons.html) 29 | build/Release 30 | 31 | # Dependency directory 32 | node_modules 33 | 34 | # Optional npm cache directory 35 | .npm 36 | 37 | # Optional REPL history 38 | .node_repl_history 39 | 40 | # OS X 41 | .DS_STORE 42 | 43 | # TypeScript 44 | typings 45 | typings.json 46 | 47 | # JetBrains 48 | .idea 49 | 50 | # Visual Studio Code 51 | .vscode 52 | .history 53 | -------------------------------------------------------------------------------- /packages/treact/.scripts/cleanup.sh: -------------------------------------------------------------------------------- 1 | echo "--- Clean install ---" 2 | 3 | echo "Remove old modules" 4 | 5 | rimraf ./package-lock.json 6 | rimraf ./node_modules 7 | 8 | echo "Install dependencies" 9 | 10 | npm i 11 | 12 | echo "Clean install finished" 13 | -------------------------------------------------------------------------------- /packages/treact/.scripts/gen-themes.ts: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ./node_modules/.bin/ts-node --project .scripts 2 | 3 | import { Color, InputPair, parser } from '@treact/theme-parser' 4 | import { map, pipe } from 'ramda' 5 | 6 | import generate from 'babel-generator' 7 | import * as template from 'babel-template' 8 | import * as t from 'babel-types' 9 | import * as getStdin from 'get-stdin' 10 | import * as recast from 'recast' 11 | 12 | const createThemePairs = pipe( 13 | parser, 14 | map((v: InputPair) => t.arrayExpression([ 15 | t.stringLiteral(v[0]), 16 | t.arrayExpression(v[1].map(c => c instanceof Color 17 | ? t.newExpression( 18 | t.identifier('Color'), 19 | [t.arrayExpression( 20 | Array 21 | // tslint:disable-next-line 22 | .from((c as any).data) 23 | .map((x: number) => t.numericLiteral(x)), 24 | )]) 25 | : t.stringLiteral(c))), 26 | ])), 27 | t.arrayExpression, 28 | ) 29 | 30 | export const parse = (code: string, meta, background: string = './background.jpg') => { 31 | const build = template(` 32 | import { Color, InputPair } from '@treact/theme-parser'; 33 | const pairs: InputPair[] = THEME; 34 | export default { 35 | meta: META, 36 | pairs, 37 | } 38 | `, { 39 | sourceType: 'module', 40 | plugins: ['flow'], 41 | }) 42 | 43 | const sourceFile = t.program(build({ 44 | THEME: createThemePairs(code), 45 | IMAGE: t.stringLiteral(background), 46 | META: t.objectExpression([ 47 | t.objectProperty( 48 | t.identifier('backgroundImage'), 49 | t.callExpression(t.identifier('require'), [t.stringLiteral(background)]), 50 | ), 51 | ...meta, 52 | ]), 53 | })) 54 | 55 | const file = recast.prettyPrint(sourceFile, { 56 | tabWidth: 2, 57 | quote: 'single', 58 | trailingComma: true, 59 | }) 60 | 61 | return `${file.code}\n` 62 | } 63 | 64 | if (require.main === module) { 65 | getStdin().then(str => { 66 | console.log(parse(str, [])) 67 | }) 68 | } 69 | -------------------------------------------------------------------------------- /packages/treact/.scripts/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "baseUrl": "..", 4 | "moduleResolution": "node", 5 | "target": "es5", 6 | "lib": ["es2015", "es5", "dom"], 7 | "allowJs": true, 8 | "noStrictGenericChecks": true 9 | }, 10 | "exclude": [ 11 | "node_modules", 12 | "gh-pages", 13 | "build", 14 | "typings/main", 15 | "typings/main.d.ts" 16 | ] 17 | } 18 | -------------------------------------------------------------------------------- /packages/treact/.scripts/update-themes.ts: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ./node_modules/.bin/ts-node --project .scripts 2 | import axios from 'axios'; 3 | import * as t from 'babel-types'; 4 | import * as fs from 'fs'; 5 | import * as JSZip from 'jszip'; 6 | import * as path from 'path'; 7 | import { promisify } from 'util'; 8 | import { parse } from './gen-themes'; 9 | 10 | const jszip = new JSZip(); 11 | const themesDir = path.join(__dirname, '..', 'src/app/themes'); 12 | 13 | const writeFile = promisify(fs.writeFile); 14 | const download = (theme: string, name: string, meta) => axios({ 15 | method: 'get', 16 | url: theme, 17 | responseType: 'arraybuffer', 18 | }).then(response => { 19 | const type = response.headers['content-type']; 20 | if (type.includes('text/plain')) { 21 | return response.data.toString(); 22 | } else if (type.includes('application/octet-stream')) { 23 | return jszip.loadAsync(response.data); 24 | } else { 25 | return Promise.reject('unknown type'); 26 | } 27 | }).then(async file => { 28 | const dest = path.join(themesDir, name); 29 | const save = (file, content) => writeFile(path.join(dest, file), content); 30 | const saveTheme = (theme, meta, bg?) => save('index.ts', parse(theme, meta, bg)); 31 | 32 | if (file instanceof JSZip) { 33 | const zip = file; 34 | const background = zip.file(/.jpg/)[0]; 35 | const theme = await zip.file('colors.tdesktop-theme').async('string'); 36 | 37 | await save( 38 | background.name, 39 | await background.async('nodebuffer')); 40 | await saveTheme(theme, meta, `./${background.name}`); 41 | } else { 42 | // console.log(typeof file); 43 | await saveTheme(file, meta); 44 | } 45 | }); 46 | 47 | const defaultThemeFile = 48 | 'https://raw.githubusercontent.com/telegramdesktop/tdesktop/dev/Telegram/Resources/colors.palette'; 49 | const nightThemeBundle = 50 | 'https://github.com/telegramdesktop/tdesktop/raw/dev/Telegram/Resources/night.tdesktop-theme'; 51 | 52 | const themes = [ 53 | download(defaultThemeFile, 'default', [ 54 | t.objectProperty(t.identifier('builtin'), t.booleanLiteral(true)), 55 | ]), 56 | download(nightThemeBundle, 'night', [ 57 | t.objectProperty(t.identifier('builtin'), t.booleanLiteral(true)), 58 | t.objectProperty(t.identifier('nightMode'), t.booleanLiteral(true)), 59 | ]), 60 | ]; 61 | 62 | Promise 63 | .all(themes) 64 | .catch(err => console.error(err)); 65 | 66 | 67 | -------------------------------------------------------------------------------- /packages/treact/.stylelintrc: -------------------------------------------------------------------------------- 1 | { 2 | "rules": { 3 | "block-no-empty": null, 4 | "color-no-invalid-hex": true, 5 | "declaration-colon-space-after": "always", 6 | "indentation": [2, { 7 | "except": ["value"] 8 | }], 9 | "max-empty-lines": 2, 10 | "unit-whitelist": ["px", "em", "rem", "%", "s"] 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /packages/treact/.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "7" 4 | - "node" 5 | env: 6 | - NODE_ENV=ci 7 | cache: 8 | directories: 9 | - node_modules 10 | install: 11 | - npm install 12 | before_script: 13 | - "export DISPLAY=:99.0" 14 | - "sh -e /etc/init.d/xvfb start" 15 | script: 16 | - npm run lint || true 17 | - npm run build:vendor 18 | - npm run build 19 | - npm test 20 | -------------------------------------------------------------------------------- /packages/treact/README.md: -------------------------------------------------------------------------------- 1 | # Telegram React 2 | [![Build Status](https://travis-ci.org/barbar/vortigern.svg?branch=master)](https://travis-ci.org/barbar/vortigern) 3 | [![Dependency Status](https://david-dm.org/barbar/vortigern.svg)]() 4 | [![devDependency Status](https://david-dm.org/barbar/vortigern/dev-status.svg)]() 5 | [![Code Climate](https://codeclimate.com/github/barbar/vortigern/badges/gpa.svg)](https://codeclimate.com/github/barbar/vortigern) 6 | [![GitHub issues](https://img.shields.io/github/issues/barbar/vortigern.svg)](https://github.com/barbar/vortigern/issues) 7 | [![GitHub license](https://img.shields.io/badge/license-MIT-blue.svg)](https://raw.githubusercontent.com/barbar/vortigern/develop/LICENSE) 8 | ___ 9 | 10 | Contact me in telegram [@goodmind](https://telegram.me/goodmind) 11 | 12 | [![TypeScript](https://barbaruploads.s3.amazonaws.com/bicoz/typescript.png)](https://www.typescriptlang.org/) 13 | [![React](https://barbaruploads.s3.amazonaws.com/bicoz/react.png)](https://github.com/facebook/react) 14 | [![Redux](https://barbaruploads.s3.amazonaws.com/bicoz/redux.png)](https://github.com/reactjs/redux) 15 | 16 | ## Installation 17 | 18 | You can clone from this repository 19 | 20 | ```bash 21 | $ git clone https://github.com/goodmind/treact 22 | $ cd treact 23 | $ npm install 24 | ``` 25 | 26 | ## Usage 27 | 28 | All commands defaults to development environment. You can set `NODE_ENV` to `production` or use the shortcuts below. 29 | 30 | ```bash 31 | # Running 32 | 33 | $ npm start # This starts the app in development mode 34 | 35 | # Starting it with the production build 36 | $ NODE_ENV=production npm start # or 37 | $ npm run start:prod 38 | 39 | # Building 40 | 41 | $ npm build # This builds the app in development mode 42 | 43 | # Commands below builds the production build 44 | $ NODE_ENV=production npm build # or 45 | $ npm run build:prod 46 | 47 | # Testing 48 | $ npm test 49 | ``` 50 | 51 | ## Credits 52 | 53 | TReact is released under the [MIT license](LICENSE). 54 | -------------------------------------------------------------------------------- /packages/treact/build/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | TREACT ✒️ 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /packages/treact/config/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | <%= htmlWebpackPlugin.options.title %> 5 | 6 | 7 | 8 |
9 | 10 | 11 | -------------------------------------------------------------------------------- /packages/treact/config/main.js: -------------------------------------------------------------------------------- 1 | /** General Configurations Like PORT, HOST names and etc... */ 2 | 3 | var config = { 4 | env: process.env.NODE_ENV || 'development', 5 | host: process.env.HOST || 'localhost', 6 | port: process.env.PORT || 8889, 7 | karmaPort: 9876, 8 | 9 | // This part goes to React-Helmet for Head of our HTML 10 | app: { 11 | head: { 12 | title: 'barbar-vortigern', 13 | titleTemplate: 'TREACT ✒️: %s', 14 | meta: [ 15 | { charset: 'utf-8' }, 16 | { 'http-equiv': 'x-ua-compatible', content: 'ie=edge' }, 17 | { name: 'viewport', content: 'width=device-width, initial-scale=1' }, 18 | { name: 'description', content: 'React Redux Typescript' }, 19 | ], 20 | }, 21 | }, 22 | } 23 | 24 | module.exports = config 25 | -------------------------------------------------------------------------------- /packages/treact/config/types/dev.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Type declerations for global development variables 3 | */ 4 | 5 | declare module '' {} 6 | 7 | type mixed = {} 8 | 9 | /// 10 | /// 11 | /// 12 | /// 13 | /// 14 | /// 15 | 16 | // TODO: move to reduce wrapper 17 | interface Array { 18 | reduce(callbackfn: (previousValue: U | V, currentValue: T, currentIndex: number, array: T[]) => U | V, initialValue: V): U; 19 | } 20 | 21 | declare module '*.png' { 22 | const image: any; 23 | export = image; 24 | } 25 | 26 | declare module '*.css' { 27 | const classes: { [className: string]: string }; 28 | export = classes; 29 | } 30 | 31 | declare module '@goodmind/*' { 32 | const module: any; 33 | export = module; 34 | } 35 | 36 | declare module 'telegram-mtproto/lib/plugins/math-help' { 37 | export function getRandomId(): [number, number]; 38 | } 39 | 40 | declare module 'telegram-mtproto/lib/bin' { 41 | export function bufferConcat(b1: ArrayBuffer | Uint8Array | string, b2: ArrayBuffer | Uint8Array | string): ArrayBuffer; 42 | export function sha256HashSync(b: ArrayBuffer): string; 43 | export function bigint(i: number): any; 44 | export function nextRandomInt(i: number): number; 45 | } 46 | 47 | declare module 'telegram-mtproto/lib/service/time-manager' { 48 | export function tsNow(bool: boolean): number; 49 | } 50 | 51 | interface Window { 52 | // A hack for the Redux DevTools Chrome extension. 53 | __REDUX_DEVTOOLS_EXTENSION_COMPOSE__?: (...f: F[]) => F; 54 | __INITIAL_STATE__?: any; 55 | webkitURL?: any; 56 | BlobBuilder?: any; 57 | WebKitBlobBuilder?: any; 58 | MozBlobBuilder?: any; 59 | chrome?: any; 60 | api?: any; 61 | } 62 | -------------------------------------------------------------------------------- /packages/treact/config/types/google-react-map.d.ts: -------------------------------------------------------------------------------- 1 | // Type definitions for google-map-react 0.24.0 2 | // Project: https://github.com/istarkov/google-map-react 3 | // Definitions by: goodmind 4 | // Definitions: https://github.com/goodmind/treact 5 | 6 | /// 7 | 8 | declare module 'google-map-react' { 9 | import * as React from 'react'; 10 | 11 | export type BootstrapURLKeys = { [key: string]: string }; 12 | 13 | export type Options = google.maps.MapOptions; 14 | 15 | export type Maps = typeof google.maps; 16 | 17 | export interface Bounds { 18 | nw: number; 19 | ne: number; 20 | sw: number; 21 | se: number; 22 | } 23 | 24 | export interface Point { 25 | x: number; 26 | y: number; 27 | } 28 | 29 | export interface Coords { 30 | lat: number; 31 | lng: number; 32 | } 33 | 34 | export interface ClickEventValue extends Point, Coords { 35 | event: any; 36 | } 37 | 38 | export interface ChangeEventValue { 39 | center: Coords; 40 | zoom: number; 41 | bounds: Bounds; 42 | marginBounds: Bounds; 43 | } 44 | 45 | export interface Props { 46 | bootstrapURLKeys?: BootstrapURLKeys; 47 | defaultCenter?: Coords; 48 | center?: Coords; 49 | defaultZoom?: number; 50 | zoom?: number; 51 | hoverDistance?: number; 52 | options?: Options | ((maps: Maps) => Options); 53 | margin?: any[]; 54 | debounced?: boolean; 55 | layerTypes?: string[]; 56 | onClick?(value: ClickEventValue): any; 57 | onChange?(value: ChangeEventValue): any; 58 | resetBoundsOnResize?: boolean; 59 | onChildClick?(hoverKey: any, childProps: any): void; 60 | onChildMouseEnter?(hoverKey: any, childProps: any): void; 61 | onChildMouseLeave?(hoverKey: any, childProps: any): void; 62 | onZoomAnimationStart?(args: any): void; 63 | onZoomAnimationEnd?(args: any): void; 64 | onMapTypeIdChange?(args: any): void; 65 | distanceToMouse?(pt: Point, mousePos: Point): void; 66 | googleMapLoader?(bootstrapURLKeys: any): void; 67 | onGoogleApiLoaded?(maps: { map: any, maps: any }): void; 68 | yesIWantToUseGoogleMapApiInternals?: boolean; 69 | } 70 | 71 | export default class GoogleMapReact extends React.Component {} 72 | 73 | export interface ChildComponentProps extends Coords { 74 | $hover?: boolean; 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /packages/treact/config/types/normalizr.d.ts: -------------------------------------------------------------------------------- 1 | // Type definitions for normalizr 3.2.3 2 | // Project: https://github.com/paularmstrong/normalizr 3 | // Definitions by: goodmind 4 | // Definitions: https://github.com/goodmind/treact 5 | 6 | declare module 'normalizr' { 7 | export namespace schema { 8 | export type StrategyFunction = (value: any, parent: any, key: string) => any; 9 | export type SchemaFunction = (value: any, parent: any, key: string) => string | number; 10 | export type MergeFunction = (entityA: any, entityB: any) => any; 11 | 12 | export class Array { 13 | constructor(definition: Schema, schemaAttribute?: string | SchemaFunction) 14 | define(definition: Schema): void 15 | } 16 | 17 | export interface EntityOptions { 18 | idAttribute?: string | SchemaFunction 19 | mergeStrategy?: MergeFunction 20 | processStrategy?: StrategyFunction 21 | } 22 | 23 | export class Entity { 24 | constructor(key: string, definition?: Schema, options?: EntityOptions) 25 | define(definition: Schema): void 26 | key: string 27 | } 28 | 29 | export class Object { 30 | constructor(definition: {[key: string]: Schema}) 31 | define(definition: Schema): void 32 | } 33 | 34 | export class Union { 35 | constructor(definition: Schema, schemaAttribute?: string | SchemaFunction) 36 | define(definition: Schema): void 37 | } 38 | 39 | export class Values { 40 | constructor(definition: Schema, schemaAttribute?: string | SchemaFunction) 41 | define(definition: Schema): void 42 | } 43 | } 44 | 45 | export type Schema = 46 | schema.Array | 47 | schema.Entity | 48 | schema.Object | 49 | schema.Union | 50 | schema.Values | 51 | schema.Array[] | 52 | schema.Entity[] | 53 | schema.Object[] | 54 | schema.Union[] | 55 | schema.Values[] | 56 | {[key: string]: Schema}; 57 | 58 | export function normalize( 59 | data: any, 60 | schema: Schema 61 | ): { 62 | entities: any, 63 | result: any 64 | }; 65 | 66 | export function denormalize( 67 | input: any, 68 | schema: Schema, 69 | entities: any 70 | ): any; 71 | } 72 | -------------------------------------------------------------------------------- /packages/treact/config/types/react-autosize-textarea.d.ts: -------------------------------------------------------------------------------- 1 | // Type definitions for react-autosize-textarea 0.4.8 2 | // Project: https://github.com/andreypopp/react-textarea-autosize 3 | // Definitions by: goodmind 4 | // Definitions: https://github.com/goodmind/treact 5 | 6 | declare module 'react-autosize-textarea' { 7 | import { Component, DetailedHTMLProps, TextareaHTMLAttributes } from 'react'; 8 | 9 | type IProps = DetailedHTMLProps, HTMLTextAreaElement> 10 | export default class AutoSizeTextarea extends Component { 11 | 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /packages/treact/config/types/universal-router-react.d.ts: -------------------------------------------------------------------------------- 1 | // Type definitions for universal-router 2 | // Project: https://github.com/kriasoft/universal-router 3 | // Definitions by: goodmind 4 | // Definitions: https://github.com/goodmind/treact 5 | 6 | import { ComponentType } from 'react' 7 | 8 | declare module 'universal-router' { 9 | export interface ActionResult { 10 | type: ComponentType; 11 | } 12 | 13 | export interface NextFunction { 14 | type: JSX.Element; 15 | } 16 | 17 | export interface Route { 18 | guard?: boolean; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /packages/treact/config/webpack/dev.js: -------------------------------------------------------------------------------- 1 | const { resolve, join } = require('path') 2 | const webpack = require('webpack') 3 | const source = resolve(process.cwd(), 'src') 4 | const build = resolve(process.cwd(), 'build') 5 | 6 | const reactDll = require(join(build, 'React.json')) 7 | const vendorDll = require(join(build, 'Vendor.json')) 8 | const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin') 9 | // const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer'); 10 | 11 | const config = { 12 | devtool: 'source-map', 13 | cache: true, 14 | devServer: { 15 | hot: true, 16 | historyApiFallback: true, 17 | contentBase: build, 18 | publicPath: '/', 19 | port: 8889, 20 | }, 21 | entry: [ 22 | 'babel-polyfill', 23 | 'webpack-dev-server/client?http://localhost:8889', 24 | 'webpack/hot/only-dev-server', 25 | 'react-hot-loader/patch', 26 | './client.tsx', 27 | './vendor/main.ts', 28 | ], 29 | 30 | plugins: [ 31 | // new ManifestPlugin({ 32 | // fileName: '../manifest.json' 33 | // }), 34 | new webpack.DllReferencePlugin({ 35 | context: source, 36 | manifest: reactDll, 37 | }), 38 | new webpack.DllReferencePlugin({ 39 | context: source, 40 | manifest: vendorDll, 41 | }), 42 | new webpack.LoaderOptionsPlugin({ 43 | debug: true, 44 | }), 45 | new webpack.DefinePlugin({ 46 | 'process.env': { 47 | BROWSER: JSON.stringify(true), 48 | NODE_ENV: JSON.stringify('development'), 49 | DC_SERVER: JSON.stringify(process.env.DC_SERVER), 50 | }, 51 | }), 52 | new ForkTsCheckerWebpackPlugin({ 53 | tsconfig: resolve(process.cwd(), 'tsconfig.json'), 54 | memoryLimit: 4096, 55 | }), 56 | // new BundleAnalyzerPlugin(), 57 | // new webpack.optimize.CommonsChunkPlugin({ 58 | // name: 'vendor', 59 | // filename: 'vendor.bundle.js' 60 | // }), 61 | // new webpack.optimize.ModuleConcatenationPlugin(), 62 | new webpack.NamedModulesPlugin(), 63 | new webpack.HotModuleReplacementPlugin(), 64 | // new webpack.NoEmitOnErrorsPlugin() 65 | // new webpack.ProgressPlugin((percentage, msg) => 66 | // console.log((percentage * 100).toFixed(), msg)) 67 | // new HtmlWebpackPlugin({ 68 | // template: resolve('./config/index.html'), 69 | // inject: 'body', 70 | // }), 71 | ], 72 | } 73 | 74 | module.exports = config 75 | -------------------------------------------------------------------------------- /packages/treact/config/webpack/index.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const { resolve, join } = require('path') 3 | 4 | const source = resolve(process.cwd(), 'src') 5 | const app = resolve(source, 'app') 6 | const build = resolve(process.cwd(), 'build') 7 | 8 | const reactDll = require(join(build, 'React.json')) 9 | const vendorDll = require(join(build, 'Vendor.json')) 10 | 11 | const isProd = process.env.NODE_ENV === 'production' 12 | 13 | /* TODO: use options instead of shorthand 14 | notation in webpack */ 15 | 16 | const rules = [ 17 | /*{ 18 | test: /\.tsx?$/, 19 | enforce: "pre", 20 | loader: 'tslint-loader', 21 | options: { 22 | failOnHint: false 23 | } 24 | }, */{ 25 | enforce: 'pre', 26 | test: /\.js$/, 27 | loader: 'source-map-loader', 28 | }, { 29 | enforce: 'pre', 30 | test: /\.tsx?$/, 31 | loader: 'source-map-loader', 32 | }, { 33 | test: /\.tsx?$/, 34 | // loader: 'react-hot-loader!ts' 35 | exclude: /node_modules/, 36 | use: [ 37 | 'babel-loader', 38 | { loader: 'ts-loader', options: { transpileOnly: true } }, 39 | ], 40 | }, { 41 | test: /\.css$/, 42 | include: app, 43 | use: [ 44 | 'style-loader', 45 | { 46 | loader: 'css-loader', 47 | options: { 48 | modules: true, 49 | importLoaders: 2, 50 | localIdentName: '[local]___[hash:base64:5]', 51 | }, 52 | }, 53 | 'postcss-loader', 54 | ], 55 | }, { 56 | test: /\.css$/, 57 | exclude: app, 58 | loaders: [ 59 | 'style-loader', 60 | 'css-loader', 61 | ], 62 | }, 63 | { 64 | test: /\.eot(\?.*)?$/, 65 | loader: 'file-loader?name=fonts/[hash].[ext]', 66 | }, { 67 | test: /\.(woff|woff2)(\?.*)?$/, 68 | loader: 'file-loader?name=fonts/[hash].[ext]', 69 | }, { 70 | test: /\.ttf(\?.*)?$/, 71 | loader: 'url-loader?limit=10000&mimetype=application/octet-stream&name=fonts/[hash].[ext]', 72 | }, { 73 | test: /\.svg(\?.*)?$/, 74 | loader: 'url-loader?limit=10000&mimetype=image/svg+xml&name=fonts/[hash].[ext]', 75 | }, { 76 | test: /\.(jpe?g|png|gif)$/i, 77 | loader: 'url-loader?limit=1000&name=images/[hash].[ext]', 78 | }, 79 | ] 80 | 81 | const unifiedConfig = { 82 | mode: isProd ? 'production' : 'development', 83 | node: { 84 | fs: 'empty', 85 | net: 'empty', 86 | }, 87 | context: source, 88 | resolve: { 89 | extensions: ['.ts', '.tsx', '.js', '.jsx'], 90 | modules: [ 91 | source, 92 | 'app', 93 | 'store', 94 | 'node_modules', 95 | ], 96 | }, 97 | 98 | output: { 99 | path: build, 100 | publicPath: '/', 101 | filename: 'bundle.js', 102 | pathinfo: true, 103 | globalObject: 'self', 104 | }, 105 | 106 | module: { 107 | rules, 108 | }, 109 | } 110 | 111 | const getConfig = () => isProd ? require('./prod') : require('./dev') 112 | 113 | module.exports = Object.assign(unifiedConfig, getConfig()) 114 | -------------------------------------------------------------------------------- /packages/treact/config/webpack/prod.js: -------------------------------------------------------------------------------- 1 | const { resolve, join } = require('path') 2 | const webpack = require('webpack') 3 | // var ExtractTextPlugin = require('extract-text-webpack-plugin'); 4 | // var HtmlWebpackPlugin = require('html-webpack-plugin'); 5 | 6 | const source = resolve(process.cwd(), 'src') 7 | const build = resolve(process.cwd(), 'build') 8 | 9 | const ManifestPlugin = require('webpack-manifest-plugin') 10 | const BabiliPlugin = require('babili-webpack-plugin') 11 | const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin') 12 | // const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer'); 13 | 14 | // const reactDll = require(join(build, 'React.json')); 15 | // const vendorDll = require(join(build, 'Vendor.json')); 16 | 17 | const config = { 18 | bail: true, 19 | cache: false, 20 | entry: [ 21 | 'babel-polyfill', 22 | './client.tsx', 23 | './vendor/main.ts', 24 | ], 25 | 26 | plugins: [ 27 | new ManifestPlugin({ 28 | fileName: './manifest.json', 29 | }), 30 | /*new webpack.DllReferencePlugin({ 31 | context: source, 32 | manifest: reactDll 33 | }), 34 | new webpack.DllReferencePlugin({ 35 | context: source, 36 | manifest: vendorDll 37 | }),*/ 38 | new webpack.DefinePlugin({ 39 | 'process.env': { 40 | BROWSER: JSON.stringify(true), 41 | NODE_ENV: JSON.stringify('production'), 42 | DC_SERVER: JSON.stringify(process.env.DC_SERVER), 43 | }, 44 | }), 45 | new webpack.optimize.ModuleConcatenationPlugin(), 46 | new webpack.NoEmitOnErrorsPlugin(), 47 | new ForkTsCheckerWebpackPlugin({ 48 | tsconfig: resolve(process.cwd(), 'tsconfig.json'), 49 | }), 50 | // new BundleAnalyzerPlugin(), 51 | new BabiliPlugin({}, { 52 | comments: false, 53 | }), 54 | ], 55 | } 56 | 57 | module.exports = config 58 | -------------------------------------------------------------------------------- /packages/treact/config/webpack/server.js: -------------------------------------------------------------------------------- 1 | var path = require('path') 2 | var fs = require('fs') 3 | 4 | var nodeModules = {} 5 | fs.readdirSync('node_modules') 6 | .filter(function(x) { 7 | return ['.bin'].indexOf(x) === -1 8 | }) 9 | .forEach(function(mod) { 10 | nodeModules[mod] = 'commonjs ' + mod 11 | }) 12 | 13 | var config = { 14 | externals: nodeModules, 15 | target: 'node', 16 | 17 | resolve: { 18 | extensions: ['', '.ts', '.tsx', '.js', '.jsx'], 19 | modulesDirectories: ['node_modules', 'app', 'app/redux'], 20 | }, 21 | 22 | entry: './src/server.tsx', 23 | 24 | output: { 25 | path: path.resolve('./build/public'), 26 | filename: '../server.js', 27 | publicPath: '/public/', 28 | libraryTarget: 'commonjs2', 29 | }, 30 | 31 | module: { 32 | loaders: [ 33 | { 34 | test: /\.(jpe?g|png|gif)$/i, 35 | loader: 'url?limit=1000&name=images/[hash].[ext]', 36 | }, 37 | { 38 | test: /\.json$/, 39 | loader: 'json-loader', 40 | }, 41 | { 42 | test: /\.jsx$/, 43 | loader: 'babel?presets[]=es2015', 44 | }, 45 | { 46 | test: /\.tsx?$/, 47 | loader: 'ts-loader', 48 | exclude: /node_modules/, 49 | }, 50 | { 51 | test: /\.css$/, 52 | loaders: [ 53 | 'isomorphic-style-loader', 54 | 'css-loader?modules&importLoaders=2&sourceMap&localIdentName=[local]___[hash:base64:5]', 55 | ], 56 | }, 57 | ], 58 | }, 59 | 60 | plugins: [], 61 | 62 | node: { 63 | console: false, 64 | global: false, 65 | process: false, 66 | Buffer: false, 67 | __filename: false, 68 | __dirname: false, 69 | }, 70 | } 71 | 72 | module.exports = config 73 | -------------------------------------------------------------------------------- /packages/treact/config/webpack/test.js: -------------------------------------------------------------------------------- 1 | require('es6-promise').polyfill() 2 | require('isomorphic-fetch') 3 | 4 | var context = require.context('../../src', true, /.test\.tsx?$/) 5 | context.keys().forEach(context) 6 | -------------------------------------------------------------------------------- /packages/treact/config/webpack/vendor.js: -------------------------------------------------------------------------------- 1 | const { resolve, join } = require('path') 2 | const webpack = require('webpack') 3 | const source = resolve(process.cwd(), 'src') 4 | const build = resolve(process.cwd(), 'build') 5 | 6 | const BabiliPlugin = require('babili-webpack-plugin') 7 | 8 | const plugins = [ 9 | new webpack.optimize.ModuleConcatenationPlugin(), 10 | new webpack.DllPlugin({ 11 | name: '[name]', 12 | path: join(build, '[name].json'), 13 | }), 14 | ] 15 | 16 | if (process.env.NODE_ENV === 'production') { 17 | plugins.push( 18 | new BabiliPlugin( 19 | {}, 20 | { 21 | comments: false, 22 | }, 23 | ), 24 | ) 25 | } 26 | 27 | const config = { 28 | context: source, 29 | entry: { 30 | React: [ 31 | 'react', 32 | 'react-dom', 33 | 'universal-router', 34 | 'react-redux', 35 | 'react-helmet', 36 | 'redux', 37 | 'redux-act', 38 | 'redux-persist', 39 | 'redux-thunk', 40 | 'recompose', 41 | 'reselect', 42 | 'reselect-map', 43 | 'normalizr', 44 | ], 45 | Vendor: [ 46 | 'ramda', 47 | 'history', 48 | 'classnames', 49 | 'localforage', 50 | // 'telegram-mtproto', 51 | ], 52 | }, 53 | mode: 'none', 54 | output: { 55 | path: build, 56 | filename: '[name].dll.js', 57 | library: '[name]', 58 | }, 59 | plugins, 60 | } 61 | 62 | module.exports = config 63 | -------------------------------------------------------------------------------- /packages/treact/postcss.config.js: -------------------------------------------------------------------------------- 1 | const postcssAssets = require('postcss-assets') 2 | const postcssNext = require('postcss-cssnext') 3 | const stylelint = require('stylelint') 4 | 5 | module.exports = ({ options }) => Object.assign({}, options, { 6 | plugins: [ 7 | stylelint(), 8 | postcssNext(), 9 | postcssAssets({ relative: true }), 10 | ], 11 | }) 12 | -------------------------------------------------------------------------------- /packages/treact/src/__mocks__/fileMock.js: -------------------------------------------------------------------------------- 1 | module.exports = 'test-file-stub' 2 | -------------------------------------------------------------------------------- /packages/treact/src/app/components/App/__snapshots__/index.test.tsx.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`App renders correctly 1`] = ` 4 |
7 | Hello, world! 8 |
9 | `; 10 | -------------------------------------------------------------------------------- /packages/treact/src/app/components/App/index.test.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react' 2 | import * as renderer from 'react-test-renderer' 3 | import { App } from './' 4 | 5 | it('App renders correctly', () => { 6 | const tree = renderer.create( 7 | Hello, world!, 8 | ).toJSON() 9 | 10 | expect(tree).toMatchSnapshot() 11 | }) 12 | 13 | -------------------------------------------------------------------------------- /packages/treact/src/app/components/App/index.tsx: -------------------------------------------------------------------------------- 1 | import styled from 'glamorous' 2 | 3 | const App = styled.section({ 4 | display: 'flex', 5 | flexDirection: 'column', 6 | padding: 0, 7 | margin: 0, 8 | width: '100%', 9 | height: '100%', 10 | }) 11 | 12 | export { App } 13 | -------------------------------------------------------------------------------- /packages/treact/src/app/components/App/style.css: -------------------------------------------------------------------------------- 1 | .app { 2 | display: flex; 3 | flex-direction: column; 4 | padding: 0; 5 | margin: 0; 6 | width: 100%; 7 | height: 100%; 8 | } 9 | -------------------------------------------------------------------------------- /packages/treact/src/app/components/AutoSizeTextarea/index.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react' 2 | 3 | interface Props { 4 | className?: string 5 | placeholder?: string 6 | value?: string 7 | rows?: number 8 | } 9 | 10 | const AutoSizeTextarea = (props: Props) => { 11 | const { value } = props 12 | return 13 | } 14 | 15 | export { AutoSizeTextarea } 16 | -------------------------------------------------------------------------------- /packages/treact/src/app/components/Chat/scroll.ts: -------------------------------------------------------------------------------- 1 | import { InfiniteScroll } from 'components/InfiniteScroll' 2 | import styled from 'glamorous' 3 | 4 | export default styled(InfiniteScroll)({ 5 | minHeight: 'min-content', 6 | display: 'flex', 7 | flexDirection: 'column', 8 | flex: 1, 9 | }) 10 | -------------------------------------------------------------------------------- /packages/treact/src/app/components/Chat/style.css: -------------------------------------------------------------------------------- 1 | .chat { 2 | background-size: cover; 3 | display: flex; 4 | flex: 65; 5 | height: 100%; 6 | } 7 | 8 | .bubble { 9 | align-self: center; 10 | background-color: #89a0b4; 11 | border-radius: 27px; 12 | color: #fff; 13 | font-size: 14px; 14 | font-weight: 600; 15 | margin: 0 auto; 16 | padding: 3px 12px 4px 12px; 17 | } 18 | 19 | .chatcontainer { 20 | display: flex; 21 | flex-direction: column; 22 | width: 100%; 23 | } 24 | 25 | .chatheader { 26 | background-color: #fff; 27 | border-bottom: 1px solid rgba(0, 0, 0, .1); 28 | display: flex; 29 | height: 54px; 30 | padding-left: 16px; 31 | border-left: 1px solid rgba(0, 0, 0, .1); 32 | } 33 | 34 | .left { 35 | align-self: center; 36 | display: flex; 37 | flex-direction: column; 38 | font-size: 13px; 39 | } 40 | 41 | .top { 42 | flex: 1; 43 | font-weight: 700; 44 | padding: 2px 0; 45 | } 46 | 47 | .bottom { 48 | color: #979797; 49 | flex: 1; 50 | font-weight: 400; 51 | padding: 2px 0; 52 | } 53 | 54 | .right {} 55 | 56 | .chatbody { 57 | align-items: flex-start; 58 | display: flex; 59 | flex: 1; 60 | height: 100%; 61 | overflow: auto; 62 | padding-bottom: 8px; 63 | border-left: 1px solid rgba(0, 0, 0, .1); 64 | } 65 | 66 | .box { 67 | min-height: -webkit-min-content; 68 | display: flex; 69 | flex-direction: column; 70 | flex: 1; 71 | } 72 | 73 | .chatfooter { 74 | background-color: #fff; 75 | border-top: 1px solid rgba(0, 0, 0, .1); 76 | border-left: 1px solid rgba(0, 0, 0, .1); 77 | display: flex; 78 | } 79 | 80 | .editText { 81 | border: none; 82 | flex: 1; 83 | font-size: 13px; 84 | line-height: 18px; 85 | margin: 12px 0px 12px 7px; 86 | max-height: 256px; 87 | min-height: 18px; 88 | outline: none; 89 | padding-left: 5px; 90 | resize: none; 91 | } 92 | 93 | .sendbutton { 94 | -webkit-user-select: none; 95 | align-self: flex-end; 96 | background-color: white; 97 | color: #0080c0; 98 | cursor: pointer; 99 | font-size: 16px; 100 | padding: 12px 16px; 101 | transition: all .2s linear; 102 | } 103 | 104 | .sendbutton:hover { 105 | background-color: #f5f5f5; 106 | color: #0073ad; 107 | } 108 | -------------------------------------------------------------------------------- /packages/treact/src/app/components/ChatFooter/__snapshots__/index.test.tsx.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`Message renders correctly 1`] = ` 4 |
7 |