├── examples ├── src │ ├── resources │ │ ├── less │ │ │ ├── icon.less │ │ │ ├── share.less │ │ │ ├── spinners.less │ │ │ ├── clip-image.less │ │ │ └── animation-items.less │ │ ├── .DS_Store │ │ └── img │ │ │ ├── .DS_Store │ │ │ ├── beach.jpg │ │ │ ├── icon.png │ │ │ ├── lock.jpg │ │ │ ├── monkey.jpg │ │ │ ├── nvshen.jpg │ │ │ ├── mountains.jpg │ │ │ ├── tiankong.jpg │ │ │ ├── fashion-88x88-4.jpg │ │ │ ├── fashion-88x88-5.jpg │ │ │ ├── fashion-88x88-6.jpg │ │ │ ├── people-68x68-1.jpg │ │ │ ├── people-88x88-1.jpg │ │ │ ├── nature-1000x600-3.jpg │ │ │ ├── nature-1000x700-8.jpg │ │ │ ├── nature-500x500-1.jpg │ │ │ ├── nature-500x500-10.jpg │ │ │ ├── nature-500x500-2.jpg │ │ │ ├── nature-500x500-3.jpg │ │ │ ├── nature-500x500-4.jpg │ │ │ ├── nature-500x500-5.jpg │ │ │ ├── nature-500x500-6.jpg │ │ │ ├── nature-500x500-7.jpg │ │ │ ├── nature-500x500-8.jpg │ │ │ ├── people-1000x600-6.jpg │ │ │ ├── people-160x160-1.jpg │ │ │ ├── people-160x160-2.jpg │ │ │ ├── people-160x160-3.jpg │ │ │ ├── people-500x500-1.jpg │ │ │ ├── people-500x500-10.jpg │ │ │ ├── placekitten-1024x1024.jpg │ │ │ ├── header.svg │ │ │ └── image.svg │ ├── history.js │ ├── .DS_Store │ ├── favicon.ico │ ├── temp.html │ ├── components │ │ ├── Page.js │ │ ├── infinite-scroll │ │ │ └── InfiniteScrollNavbar.js │ │ ├── tmp │ │ │ ├── TmpNavbar.js │ │ │ └── TmpPage.js │ │ ├── cards │ │ │ └── CardsNavbar.js │ │ ├── grid │ │ │ └── GridNavbar.js │ │ ├── quill-editor │ │ │ └── EditorNavbar.js │ │ ├── slider │ │ │ ├── SliderNavbar.js │ │ │ └── SliderPage.js │ │ ├── tabs │ │ │ ├── TabsNavbar.js │ │ │ └── TabsPage.js │ │ ├── bars │ │ │ └── BarsNavbar.js │ │ ├── draft-editor │ │ │ ├── EditorNavbar.js │ │ │ └── EditorPage.js │ │ ├── home │ │ │ └── HomeNavBar.js │ │ ├── kind-editor │ │ │ ├── EditorNavbar.js │ │ │ └── EditorPage.js │ │ ├── media-lists │ │ │ └── MediaListsNavbar.js │ │ ├── modals │ │ │ └── ModalsNavBar.js │ │ ├── umeditor │ │ │ ├── EditorNavbar.js │ │ │ └── EditorPage.js │ │ ├── calendar │ │ │ └── CalendarNavbar.js │ │ ├── forms │ │ │ └── FormsNavbar.js │ │ ├── picker │ │ │ └── PickerNavbar.js │ │ ├── accordion │ │ │ └── AccordionNavbar.js │ │ ├── contacts │ │ │ └── ContactsNavbar.js │ │ ├── lazy-load │ │ │ └── LazyLoadNavbar.js │ │ ├── react-quill │ │ │ ├── EditorNavbar.js │ │ │ └── EditorPage.js │ │ ├── list-view │ │ │ └── ListViewNavbar.js │ │ ├── searchbar │ │ │ └── SearchbarNavbar.js │ │ ├── swiper │ │ │ ├── SwiperNavbar.js │ │ │ ├── SwiperPaginationProgressNavbar.js │ │ │ └── SwiperPaginationProgressPage.js │ │ ├── spinners │ │ │ └── SpinnersNavbar.js │ │ ├── clip-image │ │ │ ├── ClipImageNavbar.js │ │ │ └── ClipImagePage.js │ │ ├── preloader │ │ │ └── PreloaderNavbar.js │ │ ├── autocomplete │ │ │ ├── AutocompleteNavbar.js │ │ │ └── AutocompletePage.js │ │ ├── notifications │ │ │ └── NotificationsNavbar.js │ │ ├── swipe-delete │ │ │ └── SwipeDeleteNavbar.js │ │ ├── pull-to-refresh │ │ │ └── PullToRefreshNavbar.js │ │ ├── photo-browser │ │ │ └── PhotoBrowserNavbar.js │ │ ├── react-animation │ │ │ └── AnimationItemsNavbar.js │ │ ├── forms-elements │ │ │ └── FormsElementsNavbar.js │ │ ├── Navbar.js │ │ ├── View.js │ │ ├── panels │ │ │ └── RightPanel.js │ │ ├── Tabbar.js │ │ ├── tabs-static │ │ │ └── TabsStaticNavbar.js │ │ ├── tabs-animated │ │ │ └── TabsAnimatedNavbar.js │ │ ├── popover │ │ │ └── PopoverNavbar.js │ │ └── tabs-swipeable │ │ │ └── TabsSwipeableNavbar.js │ ├── index.html │ ├── template.html │ └── index.js ├── .DS_Store ├── .babelrc ├── webpack.default.js ├── dev-server.js ├── server.js ├── karma.conf.js ├── webpack.prod.js ├── .eslintrc ├── webpack.dev.js ├── webpack.config.js ├── package.json └── webpack.base.js ├── _config.yml ├── index.js ├── .babelrc ├── .DS_Store ├── src ├── draft-editor │ ├── index.js │ └── tools │ │ ├── insert-image.js │ │ ├── font-shape.js │ │ ├── list-item.js │ │ ├── font-size.js │ │ ├── justify.js │ │ ├── link.js │ │ ├── font-color.js │ │ └── back-color.js ├── .DS_Store ├── umeditor │ ├── index.js │ ├── plugins │ │ ├── plugins.js │ │ ├── cleardoc.js │ │ ├── paragraph.js │ │ ├── preview.js │ │ ├── justify.js │ │ ├── selectall.js │ │ ├── print.js │ │ ├── horizontal.js │ │ └── image.js │ ├── um.js │ ├── tools │ │ ├── font-shape.js │ │ ├── list-item.js │ │ ├── insert-image.js │ │ ├── justify.js │ │ ├── font-color.js │ │ ├── link.js │ │ ├── back-color.js │ │ └── headline.js │ └── top-toolbar-editor.js ├── resources │ ├── .DS_Store │ ├── img │ │ ├── .DS_Store │ │ ├── Jcrop.gif │ │ ├── i-f7-ios.png │ │ ├── i-f7-material.png │ │ ├── i-form-comment-material.svg │ │ ├── i-form-email-material.svg │ │ ├── i-form-calendar-material.svg │ │ ├── i-form-tel-material.svg │ │ ├── i-form-name-material.svg │ │ ├── i-form-password-material.svg │ │ ├── i-form-toggle-material.svg │ │ ├── i-form-settings-material.svg │ │ ├── i-form-toggle-ios.svg │ │ ├── i-form-gender-material.svg │ │ ├── i-form-email-ios.svg │ │ ├── i-form-gender-ios.svg │ │ ├── i-form-url-material.svg │ │ ├── i-form-calendar-ios.svg │ │ ├── image.svg │ │ ├── i-form-password-ios.svg │ │ ├── i-form-comment-ios.svg │ │ ├── i-form-settings-ios.svg │ │ ├── i-form-name-ios.svg │ │ └── i-form-tel-ios.svg │ └── less │ │ ├── widget │ │ ├── loading.less │ │ ├── textarea-editor.less │ │ ├── hscroll-container.less │ │ └── textfield.less │ │ ├── disabled.less │ │ ├── _colors-vars.less │ │ ├── views.less │ │ ├── lazy-load.less │ │ ├── editor │ │ ├── top-toolbar.less │ │ ├── rich-editor.less │ │ └── draft-editor.less │ │ ├── login-screen.less │ │ ├── scroll.less │ │ ├── contacts.less │ │ ├── badges.less │ │ ├── statusbar.less │ │ ├── tabs.less │ │ ├── spinners.less │ │ ├── utils.less │ │ ├── react-ui.ios.less │ │ ├── intro.less │ │ ├── messagebar.less │ │ ├── content-block.less │ │ ├── autocomplete.less │ │ ├── pull-to-refresh.less │ │ └── panels.less ├── react-ui.js ├── stack.js ├── index.js ├── preloader.js ├── widget │ ├── loading.js │ ├── hscroll-container.js │ └── textfield.js ├── html.js ├── editor │ ├── edit.js │ ├── editor.js │ ├── tools │ │ ├── insert-image.js │ │ ├── font-size.js │ │ ├── font-color.js │ │ ├── font-shape.js │ │ ├── font-family.js │ │ └── justify.js │ └── tag-map.js ├── sys.js ├── support-events.js ├── lists.js ├── cookie.js ├── array.js ├── history.js ├── plugins.js ├── view.js ├── browser.js ├── message-box.js ├── url.js └── number.js ├── deploy.txt ├── publish.txt ├── package ├── README.md └── package.json ├── reademe2.md ├── .gitignore ├── webpack.config.js ├── .eslintrc ├── npm-scripts └── postinstall.js ├── gulpfile.js └── copy.js /examples/src/resources/less/icon.less: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/src/resources/less/share.less: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | source: ./examples/dist/ 2 | baseurl: /f7-react-ui/ 3 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | module.exports = function(){ 2 | console.log('123') 3 | } -------------------------------------------------------------------------------- /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["es2015", "react", "stage-2"] 3 | 4 | } 5 | -------------------------------------------------------------------------------- /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangzhengquan/f7-react-ui/HEAD/.DS_Store -------------------------------------------------------------------------------- /src/draft-editor/index.js: -------------------------------------------------------------------------------- 1 | import Editor from './editor' 2 | export default Editor -------------------------------------------------------------------------------- /deploy.txt: -------------------------------------------------------------------------------- 1 | # https://github.com/c-w/ghp-import 2 | ghp-import ./examples/dist/ -p -o 3 | -------------------------------------------------------------------------------- /src/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangzhengquan/f7-react-ui/HEAD/src/.DS_Store -------------------------------------------------------------------------------- /src/umeditor/index.js: -------------------------------------------------------------------------------- 1 | import Editor from './top-toolbar-editor' 2 | export default Editor -------------------------------------------------------------------------------- /examples/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangzhengquan/f7-react-ui/HEAD/examples/.DS_Store -------------------------------------------------------------------------------- /examples/src/history.js: -------------------------------------------------------------------------------- 1 | import history from 'react-ui/history' 2 | 3 | 4 | export default history -------------------------------------------------------------------------------- /examples/src/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangzhengquan/f7-react-ui/HEAD/examples/src/.DS_Store -------------------------------------------------------------------------------- /src/resources/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangzhengquan/f7-react-ui/HEAD/src/resources/.DS_Store -------------------------------------------------------------------------------- /examples/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | "es2015", 4 | "react", 5 | "stage-2" 6 | ] 7 | } 8 | -------------------------------------------------------------------------------- /examples/src/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangzhengquan/f7-react-ui/HEAD/examples/src/favicon.ico -------------------------------------------------------------------------------- /src/resources/img/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangzhengquan/f7-react-ui/HEAD/src/resources/img/.DS_Store -------------------------------------------------------------------------------- /src/resources/img/Jcrop.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangzhengquan/f7-react-ui/HEAD/src/resources/img/Jcrop.gif -------------------------------------------------------------------------------- /src/resources/img/i-f7-ios.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangzhengquan/f7-react-ui/HEAD/src/resources/img/i-f7-ios.png -------------------------------------------------------------------------------- /examples/src/resources/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangzhengquan/f7-react-ui/HEAD/examples/src/resources/.DS_Store -------------------------------------------------------------------------------- /examples/src/resources/img/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangzhengquan/f7-react-ui/HEAD/examples/src/resources/img/.DS_Store -------------------------------------------------------------------------------- /examples/src/resources/img/beach.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangzhengquan/f7-react-ui/HEAD/examples/src/resources/img/beach.jpg -------------------------------------------------------------------------------- /examples/src/resources/img/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangzhengquan/f7-react-ui/HEAD/examples/src/resources/img/icon.png -------------------------------------------------------------------------------- /examples/src/resources/img/lock.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangzhengquan/f7-react-ui/HEAD/examples/src/resources/img/lock.jpg -------------------------------------------------------------------------------- /src/resources/img/i-f7-material.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangzhengquan/f7-react-ui/HEAD/src/resources/img/i-f7-material.png -------------------------------------------------------------------------------- /examples/src/resources/img/monkey.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangzhengquan/f7-react-ui/HEAD/examples/src/resources/img/monkey.jpg -------------------------------------------------------------------------------- /examples/src/resources/img/nvshen.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangzhengquan/f7-react-ui/HEAD/examples/src/resources/img/nvshen.jpg -------------------------------------------------------------------------------- /examples/src/resources/img/mountains.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangzhengquan/f7-react-ui/HEAD/examples/src/resources/img/mountains.jpg -------------------------------------------------------------------------------- /examples/src/resources/img/tiankong.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangzhengquan/f7-react-ui/HEAD/examples/src/resources/img/tiankong.jpg -------------------------------------------------------------------------------- /src/umeditor/plugins/plugins.js: -------------------------------------------------------------------------------- 1 | var _plugins = {} 2 | 3 | var Plugins = { 4 | plugins: _plugins 5 | } 6 | 7 | export default Plugins; -------------------------------------------------------------------------------- /src/resources/less/widget/loading.less: -------------------------------------------------------------------------------- 1 | .loading{ 2 | margin-top: 200px; 3 | padding: 15px; 4 | text-align: center; 5 | font-size: 17px; 6 | } -------------------------------------------------------------------------------- /examples/src/resources/img/fashion-88x88-4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangzhengquan/f7-react-ui/HEAD/examples/src/resources/img/fashion-88x88-4.jpg -------------------------------------------------------------------------------- /examples/src/resources/img/fashion-88x88-5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangzhengquan/f7-react-ui/HEAD/examples/src/resources/img/fashion-88x88-5.jpg -------------------------------------------------------------------------------- /examples/src/resources/img/fashion-88x88-6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangzhengquan/f7-react-ui/HEAD/examples/src/resources/img/fashion-88x88-6.jpg -------------------------------------------------------------------------------- /examples/src/resources/img/people-68x68-1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangzhengquan/f7-react-ui/HEAD/examples/src/resources/img/people-68x68-1.jpg -------------------------------------------------------------------------------- /examples/src/resources/img/people-88x88-1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangzhengquan/f7-react-ui/HEAD/examples/src/resources/img/people-88x88-1.jpg -------------------------------------------------------------------------------- /examples/src/resources/img/nature-1000x600-3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangzhengquan/f7-react-ui/HEAD/examples/src/resources/img/nature-1000x600-3.jpg -------------------------------------------------------------------------------- /examples/src/resources/img/nature-1000x700-8.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangzhengquan/f7-react-ui/HEAD/examples/src/resources/img/nature-1000x700-8.jpg -------------------------------------------------------------------------------- /examples/src/resources/img/nature-500x500-1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangzhengquan/f7-react-ui/HEAD/examples/src/resources/img/nature-500x500-1.jpg -------------------------------------------------------------------------------- /examples/src/resources/img/nature-500x500-10.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangzhengquan/f7-react-ui/HEAD/examples/src/resources/img/nature-500x500-10.jpg -------------------------------------------------------------------------------- /examples/src/resources/img/nature-500x500-2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangzhengquan/f7-react-ui/HEAD/examples/src/resources/img/nature-500x500-2.jpg -------------------------------------------------------------------------------- /examples/src/resources/img/nature-500x500-3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangzhengquan/f7-react-ui/HEAD/examples/src/resources/img/nature-500x500-3.jpg -------------------------------------------------------------------------------- /examples/src/resources/img/nature-500x500-4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangzhengquan/f7-react-ui/HEAD/examples/src/resources/img/nature-500x500-4.jpg -------------------------------------------------------------------------------- /examples/src/resources/img/nature-500x500-5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangzhengquan/f7-react-ui/HEAD/examples/src/resources/img/nature-500x500-5.jpg -------------------------------------------------------------------------------- /examples/src/resources/img/nature-500x500-6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangzhengquan/f7-react-ui/HEAD/examples/src/resources/img/nature-500x500-6.jpg -------------------------------------------------------------------------------- /examples/src/resources/img/nature-500x500-7.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangzhengquan/f7-react-ui/HEAD/examples/src/resources/img/nature-500x500-7.jpg -------------------------------------------------------------------------------- /examples/src/resources/img/nature-500x500-8.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangzhengquan/f7-react-ui/HEAD/examples/src/resources/img/nature-500x500-8.jpg -------------------------------------------------------------------------------- /examples/src/resources/img/people-1000x600-6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangzhengquan/f7-react-ui/HEAD/examples/src/resources/img/people-1000x600-6.jpg -------------------------------------------------------------------------------- /examples/src/resources/img/people-160x160-1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangzhengquan/f7-react-ui/HEAD/examples/src/resources/img/people-160x160-1.jpg -------------------------------------------------------------------------------- /examples/src/resources/img/people-160x160-2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangzhengquan/f7-react-ui/HEAD/examples/src/resources/img/people-160x160-2.jpg -------------------------------------------------------------------------------- /examples/src/resources/img/people-160x160-3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangzhengquan/f7-react-ui/HEAD/examples/src/resources/img/people-160x160-3.jpg -------------------------------------------------------------------------------- /examples/src/resources/img/people-500x500-1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangzhengquan/f7-react-ui/HEAD/examples/src/resources/img/people-500x500-1.jpg -------------------------------------------------------------------------------- /examples/src/resources/img/people-500x500-10.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangzhengquan/f7-react-ui/HEAD/examples/src/resources/img/people-500x500-10.jpg -------------------------------------------------------------------------------- /publish.txt: -------------------------------------------------------------------------------- 1 | 编译并发布到npm 2 | 修改package/package.json --- version属性 3 | gulp 4 | cd build/ 5 | npm login 6 | npm publish 7 | 8 | 从npm上获取 9 | npm install f7-react-ui -------------------------------------------------------------------------------- /examples/src/resources/img/placekitten-1024x1024.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangzhengquan/f7-react-ui/HEAD/examples/src/resources/img/placekitten-1024x1024.jpg -------------------------------------------------------------------------------- /examples/src/temp.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /package/README.md: -------------------------------------------------------------------------------- 1 | 参考Framework7,以react实现的一套移动端ui框架 2 | 3 | npm install f7-react-ui 4 | 5 | 实例演示:http://60.205.148.118:8001/ 6 | 7 | git: https://github.com/wangzhengquan/react-ui 8 | -------------------------------------------------------------------------------- /src/react-ui.js: -------------------------------------------------------------------------------- 1 | // DOM Library Utilites 2 | let $ = {} 3 | 4 | let guid = 0 5 | 6 | $.guid = function() { 7 | return '' + guid++ 8 | } 9 | 10 | 11 | export default $; 12 | -------------------------------------------------------------------------------- /src/stack.js: -------------------------------------------------------------------------------- 1 | export default class Stack extends Array{ 2 | constructor(...args){ 3 | super(...args) 4 | } 5 | 6 | peek(n){ 7 | console.log("======"+n) 8 | } 9 | 10 | } -------------------------------------------------------------------------------- /examples/webpack.default.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const srcDir = path.resolve(__dirname, 'src') 3 | const distDir = path.resolve(__dirname, 'dist') 4 | 5 | module.exports = { 6 | srcDir, 7 | distDir 8 | } -------------------------------------------------------------------------------- /src/resources/less/disabled.less: -------------------------------------------------------------------------------- 1 | /* === Disabled elements === */ 2 | .disabled, [disabled] { 3 | opacity: 0.55; 4 | pointer-events: none; 5 | .disabled &, [disabled] & { 6 | opacity: 1; 7 | } 8 | } -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | 2 | import Searchbar from './searchbar'; 3 | export {Searchbar} 4 | 5 | import InfiniteScroll from './infinite-scroll'; 6 | export {InfiniteScroll} 7 | 8 | 9 | import ReactUI from './react-ui' 10 | export default ReactUI -------------------------------------------------------------------------------- /examples/src/resources/less/spinners.less: -------------------------------------------------------------------------------- 1 | .page-spinners{ 2 | p { 3 | text-align: center; 4 | margin-bottom: 40px !important; 5 | } 6 | .spinner svg { 7 | width: 19% !important; 8 | height: 85px !important; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /examples/src/components/Page.js: -------------------------------------------------------------------------------- 1 | import AnimPage from 'react-ui/page' 2 | 3 | export default class Page extends AnimPage{ 4 | constructor(props) { 5 | super(props); 6 | } 7 | 8 | 9 | render(){ 10 | return super.render() 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /src/preloader.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | require('./resources/less/preloader.less'); 4 | let Preloader = (props) => ( 5 |
6 |
7 |
8 | ); 9 | 10 | export default Preloader -------------------------------------------------------------------------------- /src/resources/img/i-form-comment-material.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /reademe2.md: -------------------------------------------------------------------------------- 1 | 参考Framework7,以react实现的一套移动端ui框架 2 | 3 | npm: [f7-react-ui](https://www.npmjs.com/package/f7-react-ui) 4 | 5 | 实例演示:http://wangzhengquan.github.io/f7-react-ui/examples/dist/index.html 6 | 7 | 运行实例: 8 | cd examples 9 | npm install 10 | npm start 11 | 12 | 打包 13 | npm run build 14 | -------------------------------------------------------------------------------- /src/resources/less/_colors-vars.less: -------------------------------------------------------------------------------- 1 | @blue:#007aff; 2 | 3 | @red: #FF5330; /*#ff3b30*/ 4 | @white: #ffffff; 5 | @black: #000000; 6 | @lightblue: #5ac8fa; 7 | @yellow: #ffcc00; 8 | @orange: #ff9500; 9 | @pink: #ff2d55; 10 | @green: #0bb908; /*4cd964 0bb908*/ 11 | @gray: #8e8e93; 12 | 13 | @themeColor: @green; -------------------------------------------------------------------------------- /src/resources/img/i-form-email-material.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /examples/src/components/infinite-scroll/InfiniteScrollNavbar.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import Navbar from '../Navbar' 3 | 4 | 5 | class InfiniteScrollNavBar extends Navbar{ 6 | 7 | } 8 | InfiniteScrollNavBar.defaultProps = { 9 | title: 'Infinite Scroll' 10 | } 11 | 12 | module.exports = InfiniteScrollNavBar -------------------------------------------------------------------------------- /src/widget/loading.js: -------------------------------------------------------------------------------- 1 | require('../resources/less/widget/loading.less') 2 | import React from 'react'; 3 | // import InfiniteScrollPreloader from '../preloader' 4 | 5 | let Loading = (props) => { 6 | 7 | return ( 8 |
9 | 正在加载... 10 |
11 | ) 12 | } 13 | 14 | export default Loading; -------------------------------------------------------------------------------- /src/resources/less/widget/textarea-editor.less: -------------------------------------------------------------------------------- 1 | @import url('../_mixins.less'); 2 | @import url('../_colors-vars.less'); 3 | 4 | .textarea-editor-page{ 5 | .editor-area{ 6 | .scrollable(); 7 | border: 0; 8 | box-sizing: border-box; 9 | width: 100%; 10 | height: 100%; 11 | padding: 5px; 12 | } 13 | 14 | 15 | } 16 | 17 | -------------------------------------------------------------------------------- /src/resources/img/i-form-calendar-material.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /examples/src/components/tmp/TmpNavbar.js: -------------------------------------------------------------------------------- 1 | import Navbar from '../Navbar' 2 | 3 | class TmpNavbar extends Navbar{ 4 | 5 | constructor(props) { 6 | super(props); 7 | } 8 | 9 | render(){ 10 | return super.render(); 11 | } 12 | } 13 | 14 | TmpNavbar.defaultProps = { 15 | title: 'title' 16 | } 17 | 18 | module.exports = TmpNavbar -------------------------------------------------------------------------------- /examples/src/components/cards/CardsNavbar.js: -------------------------------------------------------------------------------- 1 | import Navbar from '../Navbar' 2 | 3 | class CardsNavbar extends Navbar{ 4 | 5 | constructor(props) { 6 | super(props); 7 | } 8 | 9 | render(){ 10 | return super.render(); 11 | } 12 | } 13 | 14 | CardsNavbar.defaultProps = { 15 | title: 'Cards' 16 | } 17 | 18 | module.exports = CardsNavbar -------------------------------------------------------------------------------- /src/resources/less/views.less: -------------------------------------------------------------------------------- 1 | @import url('_mixins.less'); 2 | @import url('_colors-vars.less'); 3 | 4 | /* === Views === */ 5 | .views, .view { 6 | position: relative; 7 | width: 100%; 8 | height: 100%; 9 | z-index: 5000; 10 | } 11 | .views { 12 | .scrollable(); 13 | } 14 | .view { 15 | overflow: hidden; 16 | box-sizing: border-box; 17 | } 18 | -------------------------------------------------------------------------------- /src/umeditor/um.js: -------------------------------------------------------------------------------- 1 | 2 | // window.UMEDITOR_CONFIG = window.UMEDITOR_CONFIG || {}; 3 | import Plugins from './plugins/plugins' 4 | var UM = window.UM = { 5 | plugins : Plugins.plugins, 6 | 7 | commands : {}, 8 | 9 | I18N : {}, 10 | 11 | version : '1.2.2' 12 | }; 13 | 14 | var dom = UM.dom = {}; 15 | export { 16 | UM, 17 | dom 18 | } 19 | export default UM; -------------------------------------------------------------------------------- /examples/src/components/grid/GridNavbar.js: -------------------------------------------------------------------------------- 1 | import Navbar from '../Navbar' 2 | 3 | class GridNavBar extends Navbar{ 4 | 5 | 6 | constructor(props) { 7 | super(props); 8 | } 9 | 10 | 11 | render(){ 12 | return super.render(); 13 | } 14 | } 15 | 16 | GridNavBar.defaultProps = { 17 | title: 'Grid' 18 | } 19 | module.exports = GridNavBar -------------------------------------------------------------------------------- /examples/src/components/quill-editor/EditorNavbar.js: -------------------------------------------------------------------------------- 1 | import Navbar from '../Navbar' 2 | 3 | class TmpNavbar extends Navbar{ 4 | 5 | constructor(props) { 6 | super(props); 7 | } 8 | 9 | render(){ 10 | return super.render(); 11 | } 12 | } 13 | 14 | TmpNavbar.defaultProps = { 15 | title: 'Qill Editor' 16 | } 17 | 18 | module.exports = TmpNavbar -------------------------------------------------------------------------------- /examples/src/components/slider/SliderNavbar.js: -------------------------------------------------------------------------------- 1 | import Navbar from '../Navbar' 2 | 3 | class SliderNavbar extends Navbar{ 4 | 5 | constructor(props) { 6 | super(props); 7 | } 8 | 9 | render(){ 10 | return super.render(); 11 | } 12 | } 13 | 14 | SliderNavbar.defaultProps = { 15 | title: 'Slider' 16 | } 17 | 18 | module.exports = SliderNavbar -------------------------------------------------------------------------------- /examples/src/components/tabs/TabsNavbar.js: -------------------------------------------------------------------------------- 1 | import Navbar from '../Navbar' 2 | 3 | class TabsNavBar extends Navbar{ 4 | 5 | 6 | constructor(props) { 7 | super(props); 8 | } 9 | 10 | 11 | render(){ 12 | return super.render(); 13 | } 14 | } 15 | 16 | TabsNavBar.defaultProps = { 17 | title: 'Tabs' 18 | } 19 | module.exports = TabsNavBar -------------------------------------------------------------------------------- /examples/src/components/bars/BarsNavbar.js: -------------------------------------------------------------------------------- 1 | import Navbar from '../Navbar' 2 | 3 | class BarsNavbar extends Navbar{ 4 | 5 | constructor(props) { 6 | super(props); 7 | } 8 | 9 | render(){ 10 | return super.render(); 11 | } 12 | } 13 | 14 | BarsNavbar.defaultProps = { 15 | title: 'Navbars And Toolbars' 16 | } 17 | 18 | module.exports = BarsNavbar -------------------------------------------------------------------------------- /examples/src/components/draft-editor/EditorNavbar.js: -------------------------------------------------------------------------------- 1 | import Navbar from '../Navbar' 2 | 3 | class EditorNavbar extends Navbar{ 4 | 5 | constructor(props) { 6 | super(props); 7 | } 8 | 9 | render(){ 10 | return super.render(); 11 | } 12 | } 13 | 14 | EditorNavbar.defaultProps = { 15 | title: 'UMEditor' 16 | } 17 | 18 | module.exports = EditorNavbar -------------------------------------------------------------------------------- /examples/src/components/home/HomeNavBar.js: -------------------------------------------------------------------------------- 1 | import Navbar from '../Navbar' 2 | 3 | class HomeNavBar extends Navbar{ 4 | 5 | 6 | constructor(props) { 7 | super(props); 8 | } 9 | 10 | 11 | render(){ 12 | return super.render(); 13 | } 14 | } 15 | 16 | HomeNavBar.defaultProps = { 17 | title: 'ReactUI' 18 | } 19 | module.exports = HomeNavBar -------------------------------------------------------------------------------- /examples/src/components/kind-editor/EditorNavbar.js: -------------------------------------------------------------------------------- 1 | import Navbar from '../Navbar' 2 | 3 | class EditorNavbar extends Navbar{ 4 | 5 | constructor(props) { 6 | super(props); 7 | } 8 | 9 | render(){ 10 | return super.render(); 11 | } 12 | } 13 | 14 | EditorNavbar.defaultProps = { 15 | title: 'Editor' 16 | } 17 | 18 | module.exports = EditorNavbar -------------------------------------------------------------------------------- /examples/src/components/media-lists/MediaListsNavbar.js: -------------------------------------------------------------------------------- 1 | import Navbar from '../Navbar' 2 | 3 | class TmpNavbar extends Navbar{ 4 | 5 | constructor(props) { 6 | super(props); 7 | } 8 | 9 | render(){ 10 | return super.render(); 11 | } 12 | } 13 | 14 | TmpNavbar.defaultProps = { 15 | title: 'Media Lists' 16 | } 17 | 18 | module.exports = TmpNavbar -------------------------------------------------------------------------------- /examples/src/components/modals/ModalsNavBar.js: -------------------------------------------------------------------------------- 1 | import Navbar from '../Navbar' 2 | 3 | class ModalsNavBar extends Navbar{ 4 | 5 | 6 | constructor(props) { 7 | super(props); 8 | } 9 | 10 | render(){ 11 | return super.render(); 12 | } 13 | } 14 | 15 | ModalsNavBar.defaultProps = { 16 | title: 'Modals' 17 | } 18 | module.exports = ModalsNavBar 19 | -------------------------------------------------------------------------------- /examples/src/components/umeditor/EditorNavbar.js: -------------------------------------------------------------------------------- 1 | import Navbar from '../Navbar' 2 | 3 | class UMEditorNavbar extends Navbar{ 4 | 5 | constructor(props) { 6 | super(props); 7 | } 8 | 9 | render(){ 10 | return super.render(); 11 | } 12 | } 13 | 14 | UMEditorNavbar.defaultProps = { 15 | title: 'Editor' 16 | } 17 | 18 | module.exports = UMEditorNavbar -------------------------------------------------------------------------------- /examples/src/components/calendar/CalendarNavbar.js: -------------------------------------------------------------------------------- 1 | import Navbar from '../Navbar' 2 | 3 | class CalendarNavbar extends Navbar{ 4 | 5 | constructor(props) { 6 | super(props); 7 | } 8 | 9 | render(){ 10 | return super.render(); 11 | } 12 | } 13 | 14 | CalendarNavbar.defaultProps = { 15 | title: 'Calendar' 16 | } 17 | 18 | module.exports = CalendarNavbar -------------------------------------------------------------------------------- /examples/src/components/forms/FormsNavbar.js: -------------------------------------------------------------------------------- 1 | import Navbar from '../Navbar' 2 | 3 | class ModalsNavBar extends Navbar{ 4 | 5 | 6 | constructor(props) { 7 | super(props); 8 | } 9 | 10 | 11 | render(){ 12 | return super.render(); 13 | } 14 | } 15 | 16 | ModalsNavBar.defaultProps = { 17 | title: 'Forms' 18 | } 19 | module.exports = ModalsNavBar -------------------------------------------------------------------------------- /examples/src/components/picker/PickerNavbar.js: -------------------------------------------------------------------------------- 1 | import Navbar from '../Navbar' 2 | 3 | class ModalsNavBar extends Navbar{ 4 | 5 | 6 | constructor(props) { 7 | super(props); 8 | } 9 | 10 | 11 | render(){ 12 | return super.render(); 13 | } 14 | } 15 | 16 | ModalsNavBar.defaultProps = { 17 | title: 'Picker' 18 | } 19 | module.exports = ModalsNavBar -------------------------------------------------------------------------------- /src/html.js: -------------------------------------------------------------------------------- 1 | var HtmlHelper = {} 2 | 3 | HtmlHelper.escape = function (val) { 4 | return val.replace(/&/g, '&').replace(//g, '>').replace(/"/g, '"'); 5 | } 6 | 7 | HtmlHelper.unescape = function (val) { 8 | return val.replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"').replace(/&/g, '&'); 9 | } 10 | export default HtmlHelper; -------------------------------------------------------------------------------- /examples/src/components/accordion/AccordionNavbar.js: -------------------------------------------------------------------------------- 1 | import Navbar from '../Navbar' 2 | 3 | class AccordionNavbar extends Navbar{ 4 | 5 | constructor(props) { 6 | super(props); 7 | } 8 | 9 | render(){ 10 | return super.render(); 11 | } 12 | } 13 | 14 | AccordionNavbar.defaultProps = { 15 | title: 'Accordion' 16 | } 17 | 18 | module.exports = AccordionNavbar -------------------------------------------------------------------------------- /examples/src/components/contacts/ContactsNavbar.js: -------------------------------------------------------------------------------- 1 | import Navbar from '../Navbar' 2 | 3 | class ContactsNavbar extends Navbar{ 4 | 5 | constructor(props) { 6 | super(props); 7 | } 8 | 9 | render(){ 10 | return super.render(); 11 | } 12 | } 13 | 14 | ContactsNavbar.defaultProps = { 15 | title: 'Contacts List' 16 | } 17 | 18 | module.exports = ContactsNavbar -------------------------------------------------------------------------------- /examples/src/components/lazy-load/LazyLoadNavbar.js: -------------------------------------------------------------------------------- 1 | import Navbar from '../Navbar' 2 | 3 | class LazyLoadNavbar extends Navbar{ 4 | 5 | constructor(props) { 6 | super(props); 7 | } 8 | 9 | render(){ 10 | return super.render(); 11 | } 12 | } 13 | 14 | LazyLoadNavbar.defaultProps = { 15 | title: 'lazy-load' 16 | } 17 | 18 | module.exports = LazyLoadNavbar -------------------------------------------------------------------------------- /examples/src/components/react-quill/EditorNavbar.js: -------------------------------------------------------------------------------- 1 | import Navbar from '../Navbar' 2 | 3 | class EditorNavbar extends Navbar{ 4 | 5 | constructor(props) { 6 | super(props); 7 | } 8 | 9 | render(){ 10 | return super.render(); 11 | } 12 | } 13 | 14 | EditorNavbar.defaultProps = { 15 | title: 'React Quill Editor' 16 | } 17 | 18 | module.exports = EditorNavbar -------------------------------------------------------------------------------- /examples/src/components/list-view/ListViewNavbar.js: -------------------------------------------------------------------------------- 1 | import Navbar from '../Navbar' 2 | 3 | class ModalsNavBar extends Navbar{ 4 | 5 | 6 | constructor(props) { 7 | super(props); 8 | } 9 | 10 | 11 | render(){ 12 | return super.render(); 13 | } 14 | } 15 | 16 | ModalsNavBar.defaultProps = { 17 | title: 'List View' 18 | } 19 | module.exports = ModalsNavBar -------------------------------------------------------------------------------- /examples/src/components/searchbar/SearchbarNavbar.js: -------------------------------------------------------------------------------- 1 | import Navbar from '../Navbar' 2 | 3 | class ModalsNavBar extends Navbar{ 4 | 5 | 6 | constructor(props) { 7 | super(props); 8 | } 9 | 10 | 11 | render(){ 12 | return super.render(); 13 | } 14 | } 15 | 16 | ModalsNavBar.defaultProps = { 17 | title: 'Search Bar' 18 | } 19 | module.exports = ModalsNavBar -------------------------------------------------------------------------------- /examples/src/components/swiper/SwiperNavbar.js: -------------------------------------------------------------------------------- 1 | import Navbar from '../Navbar' 2 | 3 | class SwiperNavBar extends Navbar{ 4 | 5 | 6 | constructor(props) { 7 | super(props); 8 | } 9 | 10 | 11 | render(){ 12 | return super.render(); 13 | } 14 | } 15 | 16 | SwiperNavBar.defaultProps = { 17 | title: 'Swiper Slider' 18 | } 19 | module.exports = SwiperNavBar -------------------------------------------------------------------------------- /examples/src/components/spinners/SpinnersNavbar.js: -------------------------------------------------------------------------------- 1 | import Navbar from '../Navbar' 2 | 3 | class SpinnersNavbar extends Navbar{ 4 | 5 | 6 | constructor(props) { 7 | super(props); 8 | } 9 | 10 | 11 | render(){ 12 | return super.render(); 13 | } 14 | } 15 | 16 | SpinnersNavbar.defaultProps = { 17 | title: 'Spinners' 18 | } 19 | module.exports = SpinnersNavbar -------------------------------------------------------------------------------- /src/editor/edit.js: -------------------------------------------------------------------------------- 1 | 2 | import React from 'react'; 3 | 4 | class Edit extends React.Component{ 5 | constructor(props) { 6 | super(props); 7 | } 8 | 9 | componentDidMount(){ 10 | } 11 | 12 | render(){ 13 | return ( 14 |
15 | ) 16 | } 17 | } 18 | 19 | module.exports = Edit 20 | -------------------------------------------------------------------------------- /examples/src/components/clip-image/ClipImageNavbar.js: -------------------------------------------------------------------------------- 1 | import Navbar from '../Navbar' 2 | 3 | class ClipImageNavBar extends Navbar{ 4 | 5 | 6 | constructor(props) { 7 | super(props); 8 | } 9 | 10 | 11 | render(){ 12 | return super.render(); 13 | } 14 | } 15 | 16 | ClipImageNavBar.defaultProps = { 17 | title: 'Clip Image' 18 | } 19 | module.exports = ClipImageNavBar -------------------------------------------------------------------------------- /examples/src/components/preloader/PreloaderNavbar.js: -------------------------------------------------------------------------------- 1 | import Navbar from '../Navbar' 2 | 3 | class PreloaderNavBar extends Navbar{ 4 | 5 | 6 | constructor(props) { 7 | super(props); 8 | } 9 | 10 | 11 | render(){ 12 | return super.render(); 13 | } 14 | } 15 | 16 | PreloaderNavBar.defaultProps = { 17 | title: 'Preloader' 18 | } 19 | module.exports = PreloaderNavBar -------------------------------------------------------------------------------- /examples/src/components/autocomplete/AutocompleteNavbar.js: -------------------------------------------------------------------------------- 1 | import Navbar from '../Navbar' 2 | 3 | class AutocompleteNavbar extends Navbar{ 4 | 5 | constructor(props) { 6 | super(props); 7 | } 8 | 9 | render(){ 10 | return super.render(); 11 | } 12 | } 13 | 14 | AutocompleteNavbar.defaultProps = { 15 | title: 'Autocomplete' 16 | } 17 | 18 | module.exports = AutocompleteNavbar -------------------------------------------------------------------------------- /examples/src/components/notifications/NotificationsNavbar.js: -------------------------------------------------------------------------------- 1 | import Navbar from '../Navbar' 2 | 3 | class NotificationsNavBar extends Navbar{ 4 | 5 | constructor(props) { 6 | super(props); 7 | } 8 | 9 | render(){ 10 | return super.render(); 11 | } 12 | } 13 | 14 | NotificationsNavBar.defaultProps = { 15 | title: 'Notifications' 16 | } 17 | module.exports = NotificationsNavBar -------------------------------------------------------------------------------- /examples/src/components/swipe-delete/SwipeDeleteNavbar.js: -------------------------------------------------------------------------------- 1 | import Navbar from '../Navbar' 2 | 3 | class SwipeDeleteNavbar extends Navbar{ 4 | 5 | constructor(props) { 6 | super(props); 7 | } 8 | 9 | render(){ 10 | return super.render(); 11 | } 12 | } 13 | 14 | SwipeDeleteNavbar.defaultProps = { 15 | title: 'Swipe To Delete' 16 | } 17 | 18 | module.exports = SwipeDeleteNavbar -------------------------------------------------------------------------------- /src/sys.js: -------------------------------------------------------------------------------- 1 | export default { 2 | 3 | getSys (){ 4 | var u = navigator.userAgent; 5 | var dType; 6 | if(!!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/) || u.indexOf('iPhone') > -1 || u.indexOf('iPad') > -1){ 7 | dType = 'ios'; 8 | }else if(u.indexOf('Android') > -1 || u.indexOf('Linux') > -1){ 9 | dType = 'android'; 10 | }else{ 11 | dType = 'pc'; 12 | } 13 | return dType; 14 | } 15 | 16 | } -------------------------------------------------------------------------------- /examples/src/components/pull-to-refresh/PullToRefreshNavbar.js: -------------------------------------------------------------------------------- 1 | import Navbar from '../Navbar' 2 | 3 | class PullToRefreshNavbar extends Navbar{ 4 | 5 | constructor(props) { 6 | super(props); 7 | } 8 | 9 | render(){ 10 | return super.render(); 11 | } 12 | } 13 | 14 | PullToRefreshNavbar.defaultProps = { 15 | title: 'pull-to-refresh' 16 | } 17 | 18 | module.exports = PullToRefreshNavbar -------------------------------------------------------------------------------- /examples/src/components/photo-browser/PhotoBrowserNavbar.js: -------------------------------------------------------------------------------- 1 | import Navbar from '../Navbar' 2 | 3 | class PhotoBrowserNavBar extends Navbar{ 4 | 5 | 6 | constructor(props) { 7 | super(props); 8 | } 9 | 10 | 11 | render(){ 12 | return super.render(); 13 | } 14 | } 15 | 16 | PhotoBrowserNavBar.defaultProps = { 17 | title: 'Photo Browser' 18 | } 19 | module.exports = PhotoBrowserNavBar -------------------------------------------------------------------------------- /examples/src/components/react-animation/AnimationItemsNavbar.js: -------------------------------------------------------------------------------- 1 | import Navbar from '../Navbar' 2 | 3 | class AnimationItemsNavbar extends Navbar{ 4 | 5 | constructor(props) { 6 | super(props); 7 | } 8 | 9 | render(){ 10 | return super.render(); 11 | } 12 | } 13 | 14 | AnimationItemsNavbar.defaultProps = { 15 | title: 'Animation Item' 16 | } 17 | 18 | module.exports = AnimationItemsNavbar -------------------------------------------------------------------------------- /examples/src/components/forms-elements/FormsElementsNavbar.js: -------------------------------------------------------------------------------- 1 | import Navbar from '../Navbar' 2 | 3 | class FormsElementsNavBar extends Navbar{ 4 | 5 | 6 | constructor(props) { 7 | super(props); 8 | } 9 | 10 | 11 | render(){ 12 | return super.render(); 13 | } 14 | } 15 | 16 | FormsElementsNavBar.defaultProps = { 17 | title: 'Form Elements' 18 | } 19 | module.exports = FormsElementsNavBar -------------------------------------------------------------------------------- /src/resources/img/i-form-tel-material.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/resources/img/i-form-name-material.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/resources/img/i-form-password-material.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/resources/img/i-form-toggle-material.svg: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | -------------------------------------------------------------------------------- /examples/src/resources/less/clip-image.less: -------------------------------------------------------------------------------- 1 | .use-header{ 2 | display: block; 3 | width: 80px; 4 | height: 80px; 5 | background-image: url('../img/header.svg'); 6 | background-size:80px 80px; 7 | background-repeat:no-repeat; 8 | border: 1px dashed #000; 9 | position: relative; 10 | margin: auto; 11 | margin-top: 20px; 12 | 13 | input { 14 | position: absolute; 15 | top: 0; 16 | left: 0; 17 | width: 100%; 18 | height: 100%; 19 | opacity: 0; 20 | } 21 | } 22 | 23 | -------------------------------------------------------------------------------- /examples/src/components/swiper/SwiperPaginationProgressNavbar.js: -------------------------------------------------------------------------------- 1 | import Navbar from '../Navbar' 2 | 3 | class SwiperPaginationProgressNavBar extends Navbar{ 4 | 5 | 6 | constructor(props) { 7 | super(props); 8 | } 9 | 10 | 11 | 12 | 13 | render(){ 14 | return super.render(); 15 | } 16 | } 17 | 18 | SwiperPaginationProgressNavBar.defaultProps = { 19 | title: 'Swiper Pagination Progress' 20 | } 21 | module.exports = SwiperPaginationProgressNavBar -------------------------------------------------------------------------------- /src/resources/less/lazy-load.less: -------------------------------------------------------------------------------- 1 | /* === Images Lazy Loading === */ 2 | @import url('_mixins.less'); 3 | @import url('_colors-vars.less'); 4 | 5 | .lazy-loaded.lazy-fadeIn { 6 | .animation(lazyFadeIn 600ms); 7 | } 8 | @-webkit-keyframes lazyFadeIn { 9 | from { 10 | opacity: 0; 11 | } 12 | to { 13 | opacity: 1; 14 | } 15 | } 16 | @keyframes lazyFadeIn { 17 | from { 18 | opacity: 0; 19 | } 20 | to { 21 | opacity: 1; 22 | } 23 | } -------------------------------------------------------------------------------- /examples/src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | ReactUI Example 6 | 7 | 8 | 9 | 10 |
11 |
12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /src/resources/less/editor/top-toolbar.less: -------------------------------------------------------------------------------- 1 | @import url('../_mixins.less'); 2 | @import url('../_colors-vars.less'); 3 | @import url('editor-icon.less'); 4 | 5 | .editor-toolbar { 6 | a.tab-link { 7 | position: relative; 8 | input[type=file]{ 9 | display: block; 10 | position: absolute; 11 | top: 0; 12 | left: 0; 13 | width: 100%; 14 | height: 100%; 15 | z-index: 10; 16 | opacity: 0; 17 | } 18 | } 19 | } 20 | 21 | .editor-toolbar i.icon{ 22 | width: 25px; 23 | height: 25px; 24 | } -------------------------------------------------------------------------------- /examples/src/template.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | ReactUI Example 6 | 7 | 8 | 9 | 10 |
11 |
APPLICATION CONTENT
12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /src/resources/img/i-form-settings-material.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /examples/src/components/tmp/TmpPage.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import AnimationPage from '../Page' 3 | import classnames from 'classnames'; 4 | 5 | class TmpPage extends AnimationPage{ 6 | constructor(props) { 7 | super(props); 8 | } 9 | 10 | componentDidMount(){ 11 | } 12 | 13 | render(){ 14 | return ( 15 |
16 |
17 | 未实现 18 |
19 |
20 | ) 21 | } 22 | } 23 | 24 | module.exports = TmpPage 25 | -------------------------------------------------------------------------------- /src/resources/less/login-screen.less: -------------------------------------------------------------------------------- 1 | /* === Login screen === */ 2 | .login-screen-content { 3 | background: #fff; 4 | .login-screen-title, .list-block, .content-block, .list-block-label { 5 | max-width: 480px; 6 | margin: 25px auto; 7 | } 8 | .list-block ul { 9 | .hairline-remove(top); 10 | .hairline-remove(bottom); 11 | background: none; 12 | } 13 | .list-block-label { 14 | text-align: center; 15 | } 16 | } 17 | .login-screen-title { 18 | text-align: center; 19 | font-size: 30px; 20 | } -------------------------------------------------------------------------------- /examples/src/components/autocomplete/AutocompletePage.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import AnimationPage from '../Page' 3 | import classnames from 'classnames'; 4 | 5 | class AutocompletePage extends AnimationPage{ 6 | constructor(props) { 7 | super(props); 8 | } 9 | 10 | componentDidMount(){ 11 | } 12 | 13 | render(){ 14 | return ( 15 |
16 |
17 | 未实现 18 |
19 |
20 | ) 21 | } 22 | } 23 | 24 | module.exports = AutocompletePage 25 | -------------------------------------------------------------------------------- /src/resources/img/i-form-toggle-ios.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /src/resources/less/scroll.less: -------------------------------------------------------------------------------- 1 | @import url('_mixins.less'); 2 | @import url('_colors-vars.less'); 3 | .scroll{ 4 | .scrollable(); 5 | 6 | } 7 | .no-scrollbar { 8 | .no-scrollbar(); 9 | } 10 | 11 | .x-scroll{ 12 | .scrollable(); 13 | .no-scrollbar(); 14 | overflow-y: hidden; 15 | -webkit-overflow-scrolling: touch; 16 | } 17 | 18 | .y-scroll{ 19 | .scrollable(); 20 | overflow-x: hidden; 21 | -webkit-overflow-scrolling: touch; 22 | } 23 | 24 | .x-scroll-inner{ 25 | position: relative; 26 | width: 100%; 27 | box-sizing: content-box; 28 | .flexbox(); 29 | 30 | } -------------------------------------------------------------------------------- /package/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "f7-react-ui", 3 | "version": "1.2.5", 4 | "description": "a ui framework with reactjs", 5 | "main": "index.js", 6 | 7 | "directories": { 8 | "examples": "examples", 9 | "src": "source codes" 10 | }, 11 | 12 | "repository": { 13 | "type": "git", 14 | "url": "git+https://github.com/wangzhengquan/f7-react-ui.git" 15 | }, 16 | "keywords": [ 17 | "react-ui" 18 | ], 19 | "author": "wangzhengquan", 20 | "license": "ISC", 21 | "bugs": { 22 | "url": "https://github.com/wangzhengquan/f7-react-ui/issues" 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/editor/editor.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Edit from './Edit' 3 | import Toolbar from './toolbar' 4 | require('../resources/less/editor/bottom-toolbar.less') 5 | require('../resources/less/scroll.less') 6 | class Editor extends React.Component{ 7 | constructor(props) { 8 | super(props); 9 | } 10 | 11 | componentDidMount(){ 12 | Toolbar.init(this.edit) 13 | } 14 | 15 | render(){ 16 | return ( 17 |
18 | ) 19 | } 20 | } 21 | 22 | 23 | 24 | 25 | export default Editor; 26 | 27 | 28 | -------------------------------------------------------------------------------- /src/resources/less/contacts.less: -------------------------------------------------------------------------------- 1 | /* === Contacts === */ 2 | .contacts-content { 3 | background: #fff; 4 | } 5 | .contacts-block { 6 | margin: 0; 7 | .list-group-title { 8 | padding: 0 15px; 9 | background: #f7f7f7; 10 | color:#000; 11 | font-weight: 500; 12 | line-height: 22px; 13 | height: 22px; 14 | html.ios-gt-8 & { 15 | font-weight: 600; 16 | } 17 | } 18 | .list-group:first-child ul { 19 | .hairline-remove(top); 20 | } 21 | .list-group:last-child ul { 22 | .hairline-remove(bottom); 23 | } 24 | } -------------------------------------------------------------------------------- /src/support-events.js: -------------------------------------------------------------------------------- 1 | /*=========================== 2 | Features Support Detection 3 | ===========================*/ 4 | var SupportEvents = { 5 | touch: !!(('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch) 6 | 7 | }; 8 | 9 | SupportEvents.touchEvents = { 10 | start: SupportEvents.touch ? 'touchstart' : 'mousedown', 11 | move: SupportEvents.touch ? 'touchmove' : 'mousemove', 12 | end: SupportEvents.touch ? 'touchend' : 'mouseup', 13 | click: SupportEvents.touch ? 'touchend' : 'click' 14 | } 15 | 16 | // Export object 17 | export default SupportEvents; 18 | -------------------------------------------------------------------------------- /examples/dev-server.js: -------------------------------------------------------------------------------- 1 | const webpackDevServer = require('webpack-dev-server'); 2 | const webpack = require('webpack'); 3 | 4 | const config = require('./webpack.config.js'); 5 | // const options = { 6 | // contentBase: './dist', 7 | // hot: true, 8 | // host: 'localhost' 9 | // }; 10 | const options = config.devServer 11 | 12 | webpackDevServer.addDevServerEntrypoints(config, options); 13 | const compiler = webpack(config); 14 | const server = new webpackDevServer(compiler, options); 15 | 16 | server.listen(options.port, options.host, () => { 17 | console.log('dev server listening on port '+ options.port); 18 | }); -------------------------------------------------------------------------------- /examples/server.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const webpack = require('webpack'); 3 | const webpackDevMiddleware = require('webpack-dev-middleware'); 4 | 5 | const app = express(); 6 | const config = require('./webpack.config.js'); 7 | const compiler = webpack(config); 8 | 9 | // Tell express to use the webpack-dev-middleware and use the webpack.config.js 10 | // configuration file as a base. 11 | app.use(webpackDevMiddleware(compiler, { 12 | publicPath: config.output.publicPath 13 | })); 14 | 15 | // Serve the files on port 3000. 16 | app.listen(3000, function () { 17 | console.log('Example app listening on port 3000!\n'); 18 | }); -------------------------------------------------------------------------------- /src/resources/less/badges.less: -------------------------------------------------------------------------------- 1 | .badge { 2 | font-size: 13px; 3 | display: inline-block; 4 | color:#fff; 5 | background: #8e8e93; 6 | border-radius: 20px; 7 | padding: 0px 6px; 8 | height: 20px; 9 | line-height: 20px; 10 | box-sizing: border-box; 11 | text-align: center; 12 | .item-after & { 13 | min-width: 20px; 14 | } 15 | .icon & { 16 | position: absolute; 17 | left: 100%; 18 | margin-left: -10px; 19 | top: -2px; 20 | font-size: 10px; 21 | line-height: 16px; 22 | height: 16px; 23 | border-radius: 16px; 24 | padding: 0px 4px; 25 | min-width: 16px; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/resources/less/widget/hscroll-container.less: -------------------------------------------------------------------------------- 1 | @import url('../_mixins.less'); 2 | @import url('../_colors-vars.less'); 3 | @hscroll-item-padding: 5px; 4 | .hscroll-container{ 5 | margin: 0 auto; 6 | position: relative; 7 | overflow: auto; 8 | z-index: 0; 9 | background: #fff; 10 | .no-scrollbar(); 11 | } 12 | 13 | .hscroll-content{ 14 | position: relative; 15 | width: 100%; 16 | box-sizing: content-box; 17 | .flexbox(); 18 | padding: 0 @hscroll-item-padding; 19 | } 20 | 21 | .hscroll-item { 22 | .flex-shrink(0); 23 | width: 40%; 24 | height: 100%; 25 | position: relative; 26 | box-sizing: border-box; 27 | padding: 0 @hscroll-item-padding; 28 | } -------------------------------------------------------------------------------- /examples/src/components/draft-editor/EditorPage.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import AnimationPage from '../Page' 3 | import classnames from 'classnames'; 4 | import Editor from 'react-ui/draft-editor/editor' 5 | // require('react-ui/editor/plugins/image') 6 | // require('react-ui/editor/lang/zh_CN') 7 | 8 | class EditorPage extends AnimationPage{ 9 | constructor(props) { 10 | super(props); 11 | } 12 | 13 | 14 | render(){ 15 | return ( 16 |
17 | 18 |
19 | 20 |
21 | 22 |
23 | ) 24 | } 25 | } 26 | 27 | module.exports = EditorPage 28 | -------------------------------------------------------------------------------- /src/resources/less/statusbar.less: -------------------------------------------------------------------------------- 1 | /* === Statusbar overlay === */ 2 | @import url('_mixins.less'); 3 | @import url('_colors-vars.less'); 4 | @panelsDuration: 400ms; 5 | @toolbarBg : #f7f7f8; 6 | html.with-statusbar-overlay body{ 7 | padding-top: 20px; 8 | box-sizing: border-box; 9 | .statusbar-overlay { 10 | display: block; 11 | } 12 | .panel { 13 | padding-top: 20px; 14 | } 15 | } 16 | .statusbar-overlay { 17 | background: @toolbarBg; 18 | z-index: 10000; // A bit lower than .modals-overlay 19 | position: absolute; 20 | left: 0; 21 | top: 0; 22 | height: 20px; 23 | width: 100%; 24 | display: none; 25 | .transition(@panelsDuration); 26 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | 5 | # Runtime data 6 | pids 7 | *.pid 8 | *.seed 9 | 10 | # Directory for instrumented libs generated by jscoverage/JSCover 11 | lib-cov 12 | 13 | # Coverage directory used by tools like istanbul 14 | coverage 15 | 16 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 17 | .grunt 18 | 19 | # node-waf configuration 20 | .lock-wscript 21 | 22 | # Compiled binary addons (http://nodejs.org/api/addons.html) 23 | build/ 24 | #dist/ 25 | # Dependency directory 26 | # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git 27 | #node_modules 28 | node_modules/ 29 | 30 | # Bower 31 | bower_components/ 32 | examples/dist/ 33 | -------------------------------------------------------------------------------- /examples/src/components/umeditor/EditorPage.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import AnimationPage from '../Page' 3 | import classnames from 'classnames'; 4 | import Editor from 'react-ui/umeditor' 5 | // require('react-ui/editor/plugins/image') 6 | // require('react-ui/editor/lang/zh_CN') 7 | 8 | class UMEditorPage extends AnimationPage{ 9 | constructor(props) { 10 | super(props); 11 | } 12 | 13 | componentDidMount(){ 14 | 15 | } 16 | 17 | 18 | render(){ 19 | return ( 20 |
21 | 22 |
23 | 24 |
25 | 26 |
27 | ) 28 | } 29 | } 30 | 31 | module.exports = UMEditorPage 32 | -------------------------------------------------------------------------------- /src/resources/less/tabs.less: -------------------------------------------------------------------------------- 1 | @import url('_mixins.less'); 2 | @import url('_colors-vars.less'); 3 | /* === Tabs === */ 4 | .tabs { 5 | .tab { 6 | display: none; 7 | } 8 | .tab.active { 9 | display: block; 10 | } 11 | } 12 | .tabs-animated-wrap { 13 | position: relative; 14 | width: 100%; 15 | overflow: hidden; 16 | height: 100%; 17 | >.tabs { 18 | .flexbox(); 19 | height: 100%; 20 | .transition(300ms); 21 | >.tab { 22 | width: 100%; 23 | display: block; 24 | .flex-shrink(0); 25 | } 26 | } 27 | } 28 | .tabs-swipeable-wrap { 29 | height: 100%; 30 | > .tabs > .tab { 31 | display: block; 32 | } 33 | } 34 | 35 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | var webpack = require('webpack') 2 | 3 | module.exports = { 4 | 5 | output: { 6 | library: 'ReactUI', 7 | libraryTarget: 'umd' 8 | }, 9 | 10 | externals: [ 11 | { 12 | react: { 13 | root: 'React', 14 | commonjs2: 'react', 15 | commonjs: 'react', 16 | amd: 'react' 17 | } 18 | } 19 | ], 20 | 21 | module: { 22 | loaders: [ 23 | { test: /\.js$/, exclude: /node_modules/, loader: 'babel' } 24 | ] 25 | }, 26 | 27 | node: { 28 | Buffer: false 29 | }, 30 | 31 | plugins: [ 32 | new webpack.optimize.OccurenceOrderPlugin(), 33 | new webpack.DefinePlugin({ 34 | 'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV) 35 | }) 36 | ] 37 | 38 | } 39 | -------------------------------------------------------------------------------- /src/resources/img/i-form-gender-material.svg: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | -------------------------------------------------------------------------------- /src/umeditor/plugins/cleardoc.js: -------------------------------------------------------------------------------- 1 | ///import core 2 | ///commands 清空文档 3 | ///commandsName ClearDoc 4 | ///commandsTitle 清空文档 5 | /** 6 | * 7 | * 清空文档 8 | * @function 9 | * @name Plugins.execCommand 10 | * @param {String} cmdName cleardoc清空文档 11 | */ 12 | /* eslint quotes : "off"*/ 13 | import UM from '../um' 14 | import browser from '../core/browser' 15 | 16 | UM.commands['cleardoc'] = { 17 | execCommand : function() { 18 | var me = this, 19 | range = me.selection.getRange(); 20 | me.body.innerHTML = "

"+(browser.ie ? "" : "
")+"

"; 21 | range.setStart(me.body.firstChild,0).setCursor(false,true); 22 | setTimeout(function(){ 23 | me.fireEvent("clearDoc"); 24 | },0); 25 | 26 | } 27 | }; 28 | 29 | -------------------------------------------------------------------------------- /src/resources/less/spinners.less: -------------------------------------------------------------------------------- 1 | /** 2 | * Spinners 3 | * -------------------------------------------------- 4 | */ 5 | @import url('_mixins.less'); 6 | @import url('_colors-vars.less'); 7 | 8 | @spinner-width: 28px; 9 | @spinner-height: 28px; 10 | 11 | @spinner-light-stroke: #fff; 12 | @spinner-light-fill: #fff; 13 | 14 | @spinner-default-stroke: #9b9b9b; 15 | @spinner-default-fill: #9b9b9b; 16 | 17 | .spinner { 18 | stroke: @spinner-default-stroke; 19 | fill: @spinner-default-fill; 20 | svg { 21 | width: @spinner-width; 22 | height: @spinner-height; 23 | } 24 | } 25 | 26 | .spinner-spiral { 27 | .stop1 { 28 | stop-color: @spinner-light-fill; 29 | stop-opacity: 0; 30 | } 31 | 32 | 33 | 34 | } -------------------------------------------------------------------------------- /examples/src/components/slider/SliderPage.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import AnimationPage from '../Page' 3 | import classnames from 'classnames'; 4 | import Slider from 'react-ui/widget/slider' 5 | class SliderPage extends AnimationPage{ 6 | constructor(props) { 7 | super(props); 8 | } 9 | 10 | componentDidMount(){ 11 | } 12 | 13 | render(){ 14 | return ( 15 |
16 |
17 | 18 |
panel-1
19 |
panel-2
20 |
panel-3
21 |
22 |
23 |
24 | ) 25 | } 26 | } 27 | 28 | module.exports = SliderPage 29 | -------------------------------------------------------------------------------- /examples/karma.conf.js: -------------------------------------------------------------------------------- 1 | var webpackCfg = require('./webpack.config'); 2 | 3 | module.exports = function(config) { 4 | config.set({ 5 | basePath: '', 6 | browsers: [ 'PhantomJS' ], 7 | files: [ 8 | 'test/loadtests.js' 9 | ], 10 | port: 8080, 11 | captureTimeout: 60000, 12 | frameworks: [ 'mocha', 'chai' ], 13 | client: { 14 | mocha: {} 15 | }, 16 | singleRun: true, 17 | reporters: [ 'mocha', 'coverage' ], 18 | preprocessors: { 19 | 'test/loadtests.js': [ 'webpack', 'sourcemap' ] 20 | }, 21 | webpack: webpackCfg, 22 | webpackServer: { 23 | noInfo: true 24 | }, 25 | coverageReporter: { 26 | dir: 'coverage/', 27 | reporters: [ 28 | { type: 'html' }, 29 | { type: 'text' } 30 | ] 31 | } 32 | }); 33 | }; 34 | -------------------------------------------------------------------------------- /examples/src/resources/less/animation-items.less: -------------------------------------------------------------------------------- 1 | .swipeout{ 2 | /*transition-duration: 300ms;*/ 3 | } 4 | .item-enter { 5 | height: 0; 6 | .item-content{ 7 | transform: translate3d(-100%, 0px, 0px); 8 | } 9 | } 10 | 11 | .item-enter.item-enter-active { 12 | height: 44px; 13 | transition: height 300ms linear; 14 | .item-content{ 15 | transform: translate3d(0, 0, 0); 16 | transition: transform 300ms linear; 17 | } 18 | } 19 | 20 | .item-leave { 21 | height: 44px; 22 | /*transition: height 300ms linear;*/ 23 | .item-content{ 24 | transform: translate3d(0, 0, 0); 25 | } 26 | 27 | } 28 | 29 | .item-leave.item-leave-active { 30 | height: 0; 31 | transition: height 300ms linear; 32 | .item-content{ 33 | transform: translate3d(-100%, 0px, 0px); 34 | transition: transform 300ms linear; 35 | } 36 | } -------------------------------------------------------------------------------- /examples/webpack.prod.js: -------------------------------------------------------------------------------- 1 | const baseConfig = require('./webpack.base') 2 | const defaultConfig = require('./webpack.default') 3 | const webpack = require('webpack'); 4 | const UglifyJSPlugin = require('uglifyjs-webpack-plugin'); 5 | const merge = require('webpack-merge'); 6 | 7 | module.exports = merge(baseConfig, { 8 | devtool: 'source-map', 9 | output: { 10 | // filename: '[name].js', 11 | // filename: '[name].[chunkhash].js', 12 | filename: '[name].[hash].js', 13 | path: defaultConfig.distDir, 14 | publicPath: './' 15 | }, 16 | 17 | plugins: [ 18 | new UglifyJSPlugin(), 19 | 20 | new webpack.DefinePlugin({ 21 | 'process.env': { 22 | 'NODE_ENV': JSON.stringify('production') 23 | } 24 | }), 25 | 26 | new webpack.HashedModuleIdsPlugin() 27 | ] 28 | 29 | }) -------------------------------------------------------------------------------- /src/resources/img/i-form-email-ios.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /examples/.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "parser": "babel-eslint", 3 | "plugins": [ 4 | "react" 5 | ], 6 | "parserOptions": { 7 | "ecmaVersion": 6, 8 | "sourceType": "module", 9 | "ecmaFeatures": { 10 | "jsx": true 11 | } 12 | }, 13 | "env": { 14 | "browser": true, 15 | "amd": true, 16 | "es6": true, 17 | "node": true, 18 | "mocha": true 19 | }, 20 | "rules": { 21 | "comma-dangle": 1, 22 | "quotes": [ 1, "single" ], 23 | "no-undef": 1, 24 | "global-strict": 0, 25 | "no-extra-semi": 1, 26 | "no-underscore-dangle": 0, 27 | "no-console": [1, { allow: ["warn", "error"] }], 28 | "no-unused-vars": 1, 29 | "no-trailing-spaces": [1, { "skipBlankLines": true }], 30 | "no-unreachable": 1, 31 | "no-alert": 0, 32 | "react/jsx-uses-react": 1, 33 | "react/jsx-uses-vars": 1 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /examples/webpack.dev.js: -------------------------------------------------------------------------------- 1 | const baseConfig = require('./webpack.base.js') 2 | const defaultConfig = require('./webpack.default.js') 3 | const {NamedModulesPlugin, HotModuleReplacementPlugin} = require('webpack'); 4 | const merge = require('webpack-merge'); 5 | 6 | module.exports = merge(baseConfig, { 7 | devtool: 'inline-source-map', 8 | devServer: { 9 | contentBase: defaultConfig.distDir, 10 | hot: true, 11 | historyApiFallback: true, 12 | // compress: true, 13 | host: '0.0.0.0', 14 | port: 8080 15 | }, 16 | output: { 17 | // filename: '[name].js', 18 | // filename: '[name].[chunkhash].js', 19 | filename: '[name].[hash].js', 20 | path: defaultConfig.distDir, 21 | publicPath: '/' 22 | }, 23 | plugins: [ 24 | new NamedModulesPlugin(), 25 | new HotModuleReplacementPlugin() 26 | ] 27 | 28 | }) 29 | -------------------------------------------------------------------------------- /examples/src/components/react-quill/EditorPage.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import {Link} from 'react-router' 3 | import $ from 'react-ui/dom' 4 | import AnimationPage from '../Page' 5 | import classnames from 'classnames'; 6 | import {List} from 'react-ui/lists' 7 | import ReactQuill from 'react-quill' 8 | 9 | require('../../resources/less/quill-snow.less') 10 | class EditorPage extends AnimationPage{ 11 | constructor(props) { 12 | super(props); 13 | this.state = { 14 | 15 | } 16 | } 17 | 18 | componentDidMount(){ 19 | } 20 | 21 | render() { 22 | return ( 23 |
24 |
25 | 26 |
27 |
28 | 29 | ); 30 | } 31 | } 32 | 33 | module.exports = EditorPage 34 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "parser": "babel-eslint", 3 | "plugins": [ 4 | "react" 5 | ], 6 | "parserOptions": { 7 | "ecmaVersion": 6, 8 | "sourceType": "module", 9 | "ecmaFeatures": { 10 | "jsx": true 11 | } 12 | }, 13 | "env": { 14 | "browser": true, 15 | "amd": true, 16 | "es6": true, 17 | "node": true, 18 | "mocha": true 19 | }, 20 | "rules": { 21 | "comma-dangle": 1, 22 | "quotes": [ 1, "single" ], 23 | "no-undef": 1, 24 | "global-strict": 0, 25 | "no-extra-semi": 1, 26 | "no-underscore-dangle": 0, 27 | "no-console": [1, { allow: ["warn", "error"] }], 28 | "no-unused-vars": 1, 29 | // "no-trailing-spaces": [1, { "skipBlankLines": true }], 30 | "no-trailing-spaces": 0, 31 | "no-unreachable": 1, 32 | "no-alert": 0, 33 | "react/jsx-uses-react": 1, 34 | "react/jsx-uses-vars": 1 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/resources/img/i-form-gender-ios.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /src/widget/hscroll-container.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import classnames from 'classnames' 3 | require('../resources/less/widget/hscroll-container.less') 4 | 5 | class HScrollContainer extends React.Component{ 6 | constructor(props) { 7 | super(props); 8 | 9 | } 10 | componentWillUnmount() { 11 | 12 | } 13 | 14 | componentDidMount() { 15 | } 16 | 17 | render(){ 18 | return ( 19 |
20 |
21 | { 22 | this.props.children && this.props.children.map((child, index) => { 23 | return ( 24 |
25 | {child} 26 |
27 | ) 28 | }) 29 | } 30 |
31 |
32 | ) 33 | } 34 | } 35 | 36 | export default HScrollContainer -------------------------------------------------------------------------------- /src/editor/tools/insert-image.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import classnames from 'classnames' 3 | 4 | 5 | class InsertImage extends React.Component{ 6 | constructor(props) { 7 | super(props); 8 | this.doc = document 9 | this.state = { 10 | } 11 | } 12 | 13 | 14 | componentDidMount(){ 15 | } 16 | 17 | 18 | 19 | handleInsertImage(event){ 20 | debugger 21 | var files =[].slice.call(event.target.files, 0), 22 | file = files[0]; 23 | event.target.value = '' 24 | var url = URL.createObjectURL(file); 25 | this.doc.execCommand('insertHTML', false, '
'); 26 | } 27 | 28 | render(){ 29 | return ( 30 |
31 | 32 | 33 |
34 | ) 35 | } 36 | } 37 | 38 | 39 | module.exports = InsertImage 40 | -------------------------------------------------------------------------------- /src/resources/less/utils.less: -------------------------------------------------------------------------------- 1 | .block { 2 | display: block; 3 | clear: both; 4 | &:after { 5 | display: block; 6 | visibility: hidden; 7 | clear: both; 8 | height: 0; 9 | content: "."; 10 | } 11 | } 12 | 13 | .clearfix { 14 | *zoom: 1; 15 | &:before, 16 | &:after { 17 | display: table; 18 | content: ""; 19 | // Fixes Opera/contenteditable bug: 20 | // http://nicolasgallagher.com/micro-clearfix-hack/#comment-36952 21 | line-height: 0; 22 | } 23 | &:after { 24 | clear: both; 25 | } 26 | } 27 | 28 | .clear-float:after { 29 | content: ""; 30 | height: 0; 31 | display: block; 32 | clear: both; 33 | } 34 | 35 | .fl { 36 | float: left; 37 | } 38 | 39 | .fr { 40 | float: right; 41 | } 42 | 43 | .ellipsis { 44 | white-space: nowrap; 45 | overflow: hidden; 46 | text-overflow: ellipsis; 47 | } 48 | 49 | .word-wrap { 50 | white-space: normal; 51 | word-wrap: break-word; 52 | text-align: justify; 53 | } -------------------------------------------------------------------------------- /src/resources/less/editor/rich-editor.less: -------------------------------------------------------------------------------- 1 | @import url('../_mixins.less'); 2 | @import url('../_colors-vars.less'); 3 | 4 | .rich-editor{ 5 | box-sizing: border-box; 6 | background: #fff; 7 | border: 1px solid #ddd; 8 | cursor: text; 9 | font-size: 14px; 10 | /*margin-top: 10px;*/ 11 | height: 100%; 12 | .scrollable(); 13 | 14 | ul { 15 | list-style: disc; 16 | padding-left: 10px; 17 | } 18 | ol { 19 | padding-left: 10px; 20 | } 21 | } 22 | 23 | .rich-editor-area{ 24 | box-sizing: border-box; 25 | min-height: 100%; 26 | padding: 10px; 27 | 28 | p{ 29 | margin: 0 0 8px; 30 | } 31 | .img-wrapper{ 32 | margin-bottom: 8px; 33 | } 34 | } 35 | 36 | .editor-toolbar { 37 | svg{ 38 | width: 25px; 39 | height: 25px; 40 | } 41 | } 42 | 43 | .ql-stroke { 44 | fill: none; 45 | stroke: #444; 46 | stroke-linecap: round; 47 | stroke-linejoin: round; 48 | stroke-width: 1; 49 | } 50 | 51 | .ql-fill { 52 | fill: #444; 53 | } -------------------------------------------------------------------------------- /src/resources/img/i-form-url-material.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/resources/less/editor/draft-editor.less: -------------------------------------------------------------------------------- 1 | @import url('../_mixins.less'); 2 | .RichEditor-editor { 3 | background: #fff; 4 | border: 1px solid #ddd; 5 | cursor: text; 6 | font-size: 14px; 7 | /*margin-top: 10px;*/ 8 | height: 100%; 9 | padding: 8px; 10 | .scrollable(); 11 | } 12 | 13 | 14 | 15 | .RichEditor-editor .public-DraftEditor-content { 16 | min-height: 100px; 17 | } 18 | 19 | .RichEditor-hidePlaceholder .public-DraftEditorPlaceholder-root { 20 | display: none; 21 | } 22 | 23 | .RichEditor-editor .RichEditor-blockquote { 24 | border-left: 5px solid #eee; 25 | color: #666; 26 | font-family: 'Hoefler Text', 'Georgia', serif; 27 | font-style: italic; 28 | margin: 16px 0; 29 | padding: 10px 20px; 30 | } 31 | 32 | .RichEditor-editor .public-DraftStyleDefault-pre { 33 | background-color: rgba(0, 0, 0, 0.05); 34 | font-family: 'Inconsolata', 'Menlo', 'Consolas', monospace; 35 | font-size: 16px; 36 | padding: 20px; 37 | } 38 | 39 | 40 | 41 | figure{ 42 | margin: 0 0 10px; 43 | } 44 | -------------------------------------------------------------------------------- /npm-scripts/postinstall.js: -------------------------------------------------------------------------------- 1 | var stat = require('fs').stat 2 | 3 | stat('lib', function (error, stat) { 4 | if (error || !stat.isDirectory()) { 5 | console.warn( 6 | '-'.repeat(79) + '\n' + 7 | 'Built output not found. It looks like you might be attempting to install React\n' + 8 | 'Router from GitHub. React Router sources need to be transpiled before use. We\n'+ 9 | 'will now make a best-efforts attempt to transpile the code. This will only work\n' + 10 | 'if your development environment is set up appropriately.\n' + 11 | '-'.repeat(79) 12 | ) 13 | 14 | try { 15 | var execSync = require('child_process').execSync 16 | execSync('npm run build', { stdio: [ 0, 1, 2 ] }) 17 | } catch (e) { 18 | console.error( 19 | '-'.repeat(79) + '\n' + 20 | 'Failed to build React Router automatically. Please install React Router from\n' + 21 | 'npm, or clone the repo locally and build the library manually.\n' + 22 | '-'.repeat(79) 23 | ) 24 | throw(e) 25 | } 26 | } 27 | }) 28 | -------------------------------------------------------------------------------- /src/draft-editor/tools/insert-image.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import classnames from 'classnames' 3 | 4 | 5 | class InsertImage extends React.Component{ 6 | constructor(props) { 7 | super(props); 8 | this.edit = props.edit 9 | this.state = { 10 | } 11 | } 12 | 13 | 14 | componentDidMount(){ 15 | } 16 | 17 | handleInsertImage(event){ 18 | var files =[].slice.call(event.target.files, 0), 19 | file = files[0]; 20 | event.target.value = '' 21 | this.props.uploadFileFn(file, (url) => { 22 | // var url = URL.createObjectURL(file); 23 | this.edit.insertAtomicBlock(url, 'image') 24 | }) 25 | 26 | // this.doc.execCommand('insertHTML', false, '
'); 27 | } 28 | 29 | render(){ 30 | return ( 31 | 32 | 33 | 34 | 35 | ) 36 | } 37 | } 38 | 39 | 40 | export default InsertImage 41 | -------------------------------------------------------------------------------- /examples/webpack.config.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const path = require('path'); 4 | // console.log('============') 5 | // console.log(process) 6 | // console.log('============') 7 | const args = require('minimist')(process.argv.slice(2)); 8 | 9 | // List of allowed environments 10 | const allowedEnvs = ['dev', 'prop', 'test']; 11 | 12 | // Set the correct environment 13 | console.log("args._==", args._); 14 | var env; 15 | if (args._.length > 0 && args._.indexOf('start') !== -1) { 16 | env = 'test'; 17 | } else if (args.env) { 18 | env = args.env; 19 | } else { 20 | env = 'prod'; 21 | } 22 | // process.env.REACT_WEBPACK_ENV = env; 23 | 24 | /** 25 | * Build the webpack configuration 26 | * @param {String} wantedEnv The wanted environment 27 | * @return {Object} Webpack config 28 | */ 29 | function buildConfig(wantedEnv) { 30 | let isValid = wantedEnv && wantedEnv.length > 0 && allowedEnvs.indexOf(wantedEnv) !== -1; 31 | let validEnv = isValid ? wantedEnv : 'prod'; 32 | let config = require(path.join(__dirname, 'webpack.' + validEnv)); 33 | return config; 34 | } 35 | 36 | module.exports = buildConfig(env); 37 | -------------------------------------------------------------------------------- /src/lists.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import classNames from 'classnames'; 3 | require('./resources/less/lists.less'); 4 | class List extends React.Component{ 5 | constructor(props) { 6 | super(props); 7 | } 8 | 9 | render(){ 10 | return ( 11 |
12 | 22 |
23 | ); 24 | } 25 | 26 | } 27 | 28 | 29 | let ItemDivider = (props) => ( 30 |
31 | { props.children } 32 |
33 | ) 34 | 35 | let ListGroupTitle = (props) => ( 36 |
37 | { props.children } 38 |
39 | ) 40 | 41 | export { 42 | List, 43 | ItemDivider, 44 | ListGroupTitle 45 | } 46 | 47 | export default List; -------------------------------------------------------------------------------- /src/resources/img/i-form-calendar-ios.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /examples/src/resources/img/header.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/umeditor/plugins/paragraph.js: -------------------------------------------------------------------------------- 1 | ///import core 2 | ///commands 格式 3 | ///commandsName Paragraph 4 | ///commandsTitle 段落格式 5 | /** 6 | * 段落样式 7 | * @function 8 | * @name Plugins.execCommand 9 | * @param {String} cmdName paragraph插入段落执行命令 10 | * @param {String} style 标签值为:'p', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6' 11 | * @param {String} attrs 标签的属性 12 | * @author zhanyi 13 | */ 14 | /* eslint quotes : "off"*/ 15 | import Plugins from './plugins' 16 | // import $ from '../../dom' 17 | // import browser from '../core/browser' 18 | // import utils from '../core/utils' 19 | Plugins.plugins['paragraph'] = function() { 20 | var me = this; 21 | // me.setOpt('paragraph',{'p':'', 'h1':'', 'h2':'', 'h3':'', 'h4':'', 'h5':'', 'h6':''}); 22 | me.commands['paragraph'] = { 23 | execCommand : function( cmdName, style ) { 24 | return this.document.execCommand('formatBlock',false,'<' + style + '>'); 25 | }, 26 | queryCommandValue : function() { 27 | try{ 28 | var val = this.document.queryCommandValue('formatBlock') 29 | }catch(e){ 30 | } 31 | return val ; 32 | } 33 | }; 34 | }; 35 | -------------------------------------------------------------------------------- /src/resources/less/react-ui.ios.less: -------------------------------------------------------------------------------- 1 | @import url('_mixins.less'); 2 | @import url('_colors-vars.less'); 3 | @import url('intro.less'); 4 | @import url('grid.less'); 5 | @import url('views.less'); 6 | @import url('pages.less'); 7 | @import url('toolbars.less'); 8 | @import url('toolbars-pages.less'); 9 | @import url('searchbar.less'); 10 | @import url('messagebar.less'); 11 | @import url('icons.less'); 12 | @import url('badges.less'); 13 | @import url('content-block.less'); 14 | @import url('lists.less'); 15 | @import url('contacts.less'); 16 | @import url('forms.less'); 17 | @import url('accordion.less'); 18 | @import url('cards.less'); 19 | @import url('modals.less'); 20 | @import url('panels.less'); 21 | @import url('lazy-load.less'); 22 | @import url('tabs.less'); 23 | @import url('messages.less'); 24 | @import url('statusbar.less'); 25 | @import url('preloader.less'); 26 | @import url('progressbar.less'); 27 | @import url('pull-to-refresh.less'); 28 | @import url('autocomplete.less'); 29 | @import url('swiper.less'); 30 | @import url('photo-browser.less'); 31 | @import url('picker.less'); 32 | @import url('calendar.less'); 33 | @import url('notifications.less'); 34 | @import url('login-screen.less'); 35 | @import url('disabled.less'); 36 | -------------------------------------------------------------------------------- /src/umeditor/plugins/preview.js: -------------------------------------------------------------------------------- 1 | ///import core 2 | ///commands 预览 3 | ///commandsName Preview 4 | ///commandsTitle 预览 5 | /** 6 | * 预览 7 | * @function 8 | * @name Plugins.execCommand 9 | * @param {String} cmdName preview预览编辑器内容 10 | */ 11 | /* eslint quotes : "off"*/ 12 | import Plugins from './plugins' 13 | // import $ from '../../dom' 14 | // import browser from '../core/browser' 15 | // import utils from '../core/utils' 16 | Plugins.commands['preview'] = { 17 | execCommand : function(){ 18 | var w = window.open('', '_blank', ''), 19 | d = w.document, 20 | c = this.getContent(null,null,true), 21 | path = this.getOpt('PluginsEDITOR_HOME_URL'), 22 | formula = c.indexOf('mathquill-embedded-latex')!=-1 ? 23 | '' + 24 | '' + 25 | '':''; 26 | d.open(); 27 | d.write('' + formula + '
'+c+'
'); 28 | d.close(); 29 | }, 30 | notNeedUndo : 1 31 | }; 32 | -------------------------------------------------------------------------------- /src/umeditor/tools/font-shape.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import classnames from 'classnames' 3 | // var fontShapList = ['bold', 'italic', 'underline'] 4 | require('../plugins/font.js') 5 | 6 | var fontShapList = [ 7 | {label: 'bold', style: 'bold'}, 8 | {label: 'italic', style: 'italic'}, 9 | {label: 'underline', style: 'underline'} 10 | ]; 11 | class FontShape extends React.Component{ 12 | constructor(props) { 13 | super(props); 14 | this.edit = props.edit 15 | 16 | } 17 | 18 | 19 | 20 | 21 | handleClickFontBtn(cmd, e){ 22 | e.preventDefault() 23 | this.edit.execCommand(cmd) 24 | 25 | } 26 | 27 | render(){ 28 | return ( 29 |
30 |
字形
31 |
32 | { 33 | fontShapList.map((item) => ( 34 | 35 | 36 | 37 | )) 38 | } 39 |
40 |
41 | ) 42 | } 43 | } 44 | 45 | 46 | module.exports = FontShape 47 | -------------------------------------------------------------------------------- /src/resources/img/image.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/src/resources/img/image.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/draft-editor/tools/font-shape.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import classnames from 'classnames' 3 | // var fontShapList = ['bold', 'italic', 'underline'] 4 | 5 | var fontShapList = [ 6 | {label: 'bold', style: 'BOLD'}, 7 | {label: 'italic', style: 'ITALIC'}, 8 | {label: 'underline', style: 'UNDERLINE'} 9 | ]; 10 | class FontShape extends React.Component{ 11 | constructor(props) { 12 | super(props); 13 | this.edit = props.edit 14 | 15 | } 16 | 17 | 18 | 19 | 20 | handleClickFontBtn(cmd, e){ 21 | e.preventDefault() 22 | this.props.edit.toggleInlineStyle(cmd) 23 | 24 | } 25 | 26 | render(){ 27 | return ( 28 |
29 |
字形
30 |
31 | { 32 | fontShapList.map((item) => ( 33 | 34 | 35 | 36 | )) 37 | } 38 |
39 |
40 | ) 41 | } 42 | } 43 | 44 | 45 | module.exports = FontShape 46 | -------------------------------------------------------------------------------- /src/resources/less/intro.less: -------------------------------------------------------------------------------- 1 | @imgBaseUrl: "../img"; 2 | @import url('_colors-vars.less'); 3 | html,body { 4 | position: relative; 5 | height: 100%; 6 | width: 100%; 7 | overflow-x: hidden; 8 | } 9 | body { 10 | font-family: -apple-system, SF UI Text, Helvetica Neue, Helvetica, Arial, sans-serif; 11 | margin: 0; 12 | padding: 0; 13 | color: #000; 14 | font-size: 14px; 15 | line-height: 1.4; 16 | width: 100%; 17 | -webkit-text-size-adjust:100%; 18 | background: #fff; 19 | overflow: hidden; 20 | } 21 | img{ 22 | vertical-align: top; 23 | } 24 | ul{ 25 | list-style: none; 26 | } 27 | // Fix for iPad in Safari in Lanscape mode 28 | @media all and (width:1024px) and (height:691px) and (orientation:landscape) { 29 | html, body { 30 | height: 671px; 31 | } 32 | } 33 | @media all and (width:1024px) and (height:692px) and (orientation:landscape) { 34 | html, body { 35 | height: 672px; 36 | } 37 | } 38 | 39 | * { 40 | -webkit-tap-highlight-color: rgba(0,0,0,0); 41 | -webkit-touch-callout:none; 42 | } 43 | a, input, textarea, select { 44 | outline: 0; 45 | } 46 | 47 | a { 48 | text-decoration: none; 49 | color: @themeColor; 50 | cursor: pointer; 51 | } 52 | p { 53 | margin: 1em 0; 54 | } 55 | -------------------------------------------------------------------------------- /src/cookie.js: -------------------------------------------------------------------------------- 1 | var doc = document, MILLISECONDS_OF_DAY = 24 * 60 * 60 * 1E3, encode = encodeURIComponent, decode = decodeURIComponent; 2 | 3 | function isNotEmptyString(val) { 4 | return typeof val === 'string' && val !== '' 5 | } 6 | var Cookie = { 7 | get:function(name) { 8 | var ret, m; 9 | if(isNotEmptyString(name)) { 10 | if(m = String(doc.cookie).match(new RegExp('(?:^| )' + name + '(?:(?:=([^;]*))|;|$)'))) { 11 | ret = m[1] ? decode(m[1]) : '' 12 | } 13 | } 14 | return ret 15 | }, 16 | 17 | set:function(name, val, expires, domain, path, secure) { 18 | var text = String(encode(val)), date = expires; 19 | if(typeof date === 'number') { 20 | date = new Date; 21 | date.setTime(date.getTime() + expires * MILLISECONDS_OF_DAY) 22 | } 23 | if(date instanceof Date) { 24 | text += '; expires=' + date.toUTCString() 25 | } 26 | if(isNotEmptyString(domain)) { 27 | text += '; domain=' + domain 28 | } 29 | if(isNotEmptyString(path)) { 30 | text += '; path=' + path 31 | } 32 | if(secure) { 33 | text += '; secure' 34 | } 35 | doc.cookie = name + '=' + text 36 | }, 37 | 38 | remove:function(name, domain, path, secure) { 39 | this.set(name, '', -1, domain, path, secure) 40 | } 41 | }; 42 | 43 | export default Cookie 44 | 45 | -------------------------------------------------------------------------------- /src/umeditor/plugins/justify.js: -------------------------------------------------------------------------------- 1 | ///import core 2 | ///commands 段落格式,居左,居右,居中,两端对齐 3 | ///commandsName JustifyLeft,JustifyCenter,JustifyRight,JustifyJustify 4 | ///commandsTitle 居左对齐,居中对齐,居右对齐,两端对齐 5 | /** 6 | * @description 居左右中 7 | * @name Plugins.execCommand 8 | * @param {String} cmdName justify执行对齐方式的命令 9 | * @param {String} align 对齐方式:left居左,right居右,center居中,justify两端对齐 10 | * @author zhanyi 11 | */ 12 | /* eslint quotes : "off"*/ 13 | import Plugins from './plugins' 14 | // import browser from '../core/browser' 15 | // import utils from '../core/utils' 16 | Plugins.plugins['justify']=function(){ 17 | var me = this; 18 | 'justifyleft justifyright justifycenter justifyfull'.split(' ').forEach(function(cmdName){ 19 | me.commands[cmdName] = { 20 | execCommand:function (cmdName) { 21 | return this.document.execCommand(cmdName); 22 | }, 23 | queryCommandValue: function (cmdName) { 24 | var val = this.document.queryCommandValue(cmdName); 25 | return val === true || val === 'true' ? cmdName.replace(/justify/,'') : ''; 26 | }, 27 | queryCommandState: function (cmdName) { 28 | return this.document.queryCommandState(cmdName) ? 1 : 0 29 | } 30 | }; 31 | }) 32 | }; 33 | -------------------------------------------------------------------------------- /src/array.js: -------------------------------------------------------------------------------- 1 | var ArrayHelper = {} 2 | 3 | ArrayHelper.isArray = function (val) { 4 | if (!val) { 5 | return false; 6 | } 7 | return Object.prototype.toString.call(val) === '[object Array]'; 8 | }; 9 | 10 | ArrayHelper.toArray = function (obj, offset) { 11 | return Array.prototype.slice.call(obj, offset || 0); 12 | } 13 | 14 | ArrayHelper.each = function (obj, fn) { 15 | if (ArrayHelper.isArray(obj)) { 16 | for (var i = 0, len = obj.length; i < len; i++) { 17 | if (fn.call(obj[i], obj[i], i) === false) { 18 | break; 19 | } 20 | } 21 | } else { 22 | for (var key in obj) { 23 | if (obj.hasOwnProperty(key)) { 24 | if (fn.call(obj[key], obj[key], key) === false) { 25 | break; 26 | } 27 | } 28 | } 29 | } 30 | }; 31 | 32 | ArrayHelper.inArray = function (arr, val) { 33 | for (var i = 0, len = arr.length; i < len; i++) { 34 | if (val === arr[i]) { 35 | return i; 36 | } 37 | } 38 | return -1; 39 | } 40 | 41 | ArrayHelper.unique = function (arr) { 42 | var unique = []; 43 | for (var i = 0; i < arr.length; i++) { 44 | if (unique.indexOf(arr[i]) === -1) unique.push(arr[i]); 45 | } 46 | return unique; 47 | }; 48 | 49 | export default ArrayHelper -------------------------------------------------------------------------------- /gulpfile.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2013-present, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. An additional grant 7 | * of patent rights can be found in the PATENTS file in the same directory. 8 | */ 9 | 10 | 'use strict'; 11 | 12 | var gulp = require('gulp'); 13 | var babel = require('gulp-babel'); 14 | var flatten = require('gulp-flatten'); 15 | var del = require('del'); 16 | // var babelify = require('babelify'); 17 | var copy = require('./copy') 18 | 19 | var paths = { 20 | src: [ 21 | 'src/**/*.js' 22 | 23 | ], 24 | dist: 'build' 25 | }; 26 | 27 | 28 | 29 | 30 | 31 | gulp.task('clean', function() { 32 | return del([paths.dist]); 33 | }); 34 | 35 | gulp.task('modules', function() { 36 | // return gulp 37 | // .src(paths.react.src) 38 | // .transform("babelify", {presets: ["es2015", "react"]}) 39 | // .bundle().pipe(flatten()) 40 | // .pipe(gulp.dest(paths.react.dist)); 41 | copy(['package'], paths.dist) 42 | copy(['src/resources'], paths.dist+'/resources') 43 | return gulp 44 | .src(paths.src) 45 | .pipe(babel()) 46 | //.pipe(flatten()) 47 | .pipe(gulp.dest(paths.dist)); 48 | 49 | 50 | }); 51 | 52 | 53 | gulp.task('default', [ 'modules']); 54 | -------------------------------------------------------------------------------- /src/umeditor/plugins/selectall.js: -------------------------------------------------------------------------------- 1 | ///import core 2 | ///commands 全选 3 | ///commandsName SelectAll 4 | ///commandsTitle 全选 5 | /** 6 | * 选中所有 7 | * @function 8 | * @name Plugins.execCommand 9 | * @param {String} cmdName selectall选中编辑器里的所有内容 10 | * @author zhanyi 11 | */ 12 | /* eslint quotes : "off"*/ 13 | import Plugins from './plugins' 14 | import $ from '../../dom' 15 | import browser from '../core/browser' 16 | // import utils from '../core/utils' 17 | import domUtils from '../core/domUtils' 18 | Plugins.plugins['selectall'] = function(){ 19 | var me = this; 20 | me.commands['selectall'] = { 21 | execCommand : function(){ 22 | //去掉了原生的selectAll,因为会出现报错和当内容为空时,不能出现闭合状态的光标 23 | var me = this,body = me.body, 24 | range = me.selection.getRange(); 25 | range.selectNodeContents(body); 26 | if(domUtils.isEmptyBlock(body)){ 27 | //opera不能自动合并到元素的里边,要手动处理一下 28 | if(browser.opera && body.firstChild && body.firstChild.nodeType == 1){ 29 | range.setStartAtFirst(body.firstChild); 30 | } 31 | range.collapse(true); 32 | } 33 | range.select(true); 34 | }, 35 | notNeedUndo : 1 36 | }; 37 | 38 | 39 | //快捷键 40 | me.addshortcutkey({ 41 | "selectAll" : "ctrl+65" 42 | }); 43 | }; 44 | -------------------------------------------------------------------------------- /src/umeditor/tools/list-item.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import classnames from 'classnames' 3 | 4 | 5 | var listTypes = [ 6 | {label: 'UL', style: 'insertorderedlist', icon: 'icon-unordered-list-item'}, 7 | {label: 'OL', style: 'insertunorderedlist', icon: 'icon-ordered-list-item'} 8 | ]; 9 | 10 | class ListItem extends React.Component{ 11 | constructor(props) { 12 | super(props); 13 | this.edit = props.edit 14 | } 15 | 16 | handleChangeListItem(value){ 17 | // var commandState = this.state.commandState 18 | // commandState[value] = this.doc.queryCommandState(value) 19 | // this.setState(commandState) 20 | 21 | this.edit.execCommand(value) 22 | // this.updateCommandState() 23 | } 24 | 25 | render(){ 26 | return ( 27 |
28 |
项目符合/编号
29 |
30 | { 31 | listTypes.map(item => ( 32 |
33 | 34 | 35 |
36 | )) 37 | } 38 |
39 |
40 | ) 41 | } 42 | } 43 | 44 | 45 | export default ListItem 46 | -------------------------------------------------------------------------------- /src/resources/less/widget/textfield.less: -------------------------------------------------------------------------------- 1 | @import url('../_mixins.less'); 2 | @import url('../_colors-vars.less'); 3 | 4 | .textfield{ 5 | position: relative; 6 | box-sizing: border-box; 7 | width: 100%; 8 | height: 44px; 9 | padding: 0 15px; 10 | background-color: #fff; 11 | .hairline(top, #c8c7cc); 12 | .hairline(bottom, #c8c7cc); 13 | input{ 14 | width: 100%; 15 | height: 43px; 16 | color: #000; 17 | box-sizing: border-box; 18 | border: none; 19 | background: none; 20 | padding-right: 28px; 21 | font-size: 15px; 22 | } 23 | } 24 | .textfield-clear { 25 | position: absolute; 26 | width: 28px; 27 | height: 28px; 28 | right: 15px; 29 | top: 50%; 30 | margin-top: -14px; 31 | opacity: 0; 32 | pointer-events:none; 33 | background-position: center; 34 | background-repeat: no-repeat; 35 | .encoded-svg-background(""); 36 | -webkit-background-size: 14px 14px; 37 | background-size: 14px 14px; 38 | .transition(300ms); 39 | cursor: pointer; 40 | } 41 | 42 | .textfield-not-empty .textfield-clear { 43 | pointer-events: auto; 44 | opacity: 1; 45 | } -------------------------------------------------------------------------------- /src/widget/textfield.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import classnames from 'classnames' 3 | require('../resources/less/forms.less') 4 | require('../resources/less/widget/textfield.less') 5 | 6 | class TextField extends React.Component{ 7 | constructor(props) { 8 | super(props); 9 | this.state = { 10 | value: this.props.value 11 | } 12 | } 13 | 14 | componentDidMount(){ 15 | setTimeout(() => {this.refs.input.focus()}, 500) 16 | } 17 | 18 | handleChange(event){ 19 | var value = event.target.value; 20 | this.setState({value: value}); 21 | this.props.onChange && this.props.onChange(value) 22 | // setTimeout(() => console.log("area state value====", this.state.value), 1000 ) 23 | } 24 | 25 | handleClear(event){ 26 | event.preventDefault() 27 | this.setState({ 28 | value: '' 29 | }) 30 | } 31 | 32 | render(){ 33 | return ( 34 |
35 |
36 | 37 | 38 |
39 |
40 | ); 41 | 42 | } 43 | } 44 | 45 | export default TextField; -------------------------------------------------------------------------------- /src/editor/tools/font-size.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import classnames from 'classnames' 3 | 4 | 5 | var fontsizeList = [10, 12, 16, 18,24, 32,48]; 6 | class FontSize extends React.Component{ 7 | constructor(props) { 8 | super(props); 9 | this.doc = document 10 | this.state = { 11 | 12 | } 13 | } 14 | 15 | 16 | componentDidMount(){ 17 | } 18 | 19 | 20 | 21 | handleChangeFontSize(value , event){ 22 | var size = {} 23 | fontsizeList.forEach( (val, idx) => { 24 | size[val] = idx 25 | }) 26 | this.setState({ 27 | value: value 28 | }) 29 | this.doc.execCommand('fontSize', false, size[value]) 30 | } 31 | 32 | render(){ 33 | return ( 34 |
35 |
字体大小
36 |
37 |
38 | { 39 | fontsizeList.map(value => ( 40 |
41 | 42 | {value}px 43 |
44 | )) 45 | } 46 | 47 | 48 |
49 |
50 |
51 | ) 52 | } 53 | } 54 | 55 | 56 | module.exports = FontSize 57 | -------------------------------------------------------------------------------- /examples/src/components/Navbar.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import ReactDOM from 'react-dom'; 3 | import AnimNavbar from 'react-ui/navbar' 4 | import Panels from 'react-ui/panels' 5 | import history from '../history' 6 | import LeftPanelContent from './panels/LeftPanel' 7 | 8 | export default class Navbar extends AnimNavbar{ 9 | 10 | 11 | constructor(props) { 12 | super(props); 13 | } 14 | 15 | 16 | handleClickOpenLeftPanel(event){ 17 | event.preventDefault() 18 | //panel-reveal 19 | var panel = Panels.openPanel({position: 'left', className: 'layout-dark'}) 20 | var close = () => { 21 | Panels.closePanel(panel) 22 | } 23 | ReactDOM.render(, panel) 24 | } 25 | 26 | render(){ 27 | if(this.canBack === undefined){ 28 | this.canBack = history.canBack; 29 | } 30 | return ( 31 |
32 | { 33 | this.canBack ? 34 |
返回
: '' 35 | } 36 |
{this.props.title}
37 |
38 | 39 |
40 |
41 | ) 42 | } 43 | } 44 | 45 | -------------------------------------------------------------------------------- /src/resources/less/messagebar.less: -------------------------------------------------------------------------------- 1 | /* === Message Bar === */ 2 | .messagebar { 3 | .translate3d(0,0,0); 4 | .transition(0ms); 5 | textarea { 6 | -webkit-appearance: none; 7 | -moz-appearance: none; 8 | -ms-appearance: none; 9 | appearance: none; 10 | -webkit-box-sizing: border-box; 11 | -moz-box-sizing: border-box; 12 | box-sizing: border-box; 13 | border: 1px solid #c8c8cd; 14 | background: #fff; 15 | border-radius: 5px; 16 | box-shadow: none; 17 | display: block; 18 | padding: 3px 8px 3px; 19 | margin: 0; 20 | width: 100%; 21 | height: 28px; 22 | color: #000; 23 | font-size: 17px; 24 | line-height: 20px; 25 | font-family: inherit; 26 | resize:none; 27 | .flex-shrink(1); 28 | } 29 | .link { 30 | .align-self(flex-end); 31 | } 32 | .link.icon-only:first-child { 33 | margin-left: -6px; 34 | } 35 | .link:not(.icon-only) + textarea { 36 | margin-left: 8px; 37 | } 38 | textarea + .link { 39 | margin-left: 8px; 40 | } 41 | .link { 42 | .flex-shrink(0); 43 | } 44 | ~ .page-content { 45 | padding-bottom: @toolbarSize; 46 | } 47 | .page.no-toolbar & ~.page-content { 48 | padding-bottom: @toolbarSize; 49 | } 50 | .hidden-toolbar & { 51 | .translate3d(0,0,0); 52 | .transition(0ms); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/resources/img/i-form-password-ios.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /src/history.js: -------------------------------------------------------------------------------- 1 | /* eslint no-console: 0 */ 2 | 3 | //import { browserHistory } from 'react-router' 4 | 5 | //hash地址 6 | import { hashHistory } from 'react-router' 7 | var browserHistory = hashHistory 8 | 9 | 10 | const PATHS_LENGTH = -1 11 | let paths = browserHistory.paths = browserHistory.paths || [] 12 | 13 | //防止测试环境加载两次的问题 14 | if(!browserHistory.unlisten){ 15 | 16 | browserHistory.unlisten = browserHistory.listen(location => { 17 | let pathname = location.pathname 18 | if(pathname.charAt(0) !== '/'){ 19 | pathname = '/'.concat(pathname) 20 | } 21 | 22 | let len = paths.length 23 | 24 | browserHistory.isBack = (len > 1 && pathname === paths[len-2]) 25 | if(browserHistory.isBack) { 26 | paths.pop() 27 | } else if (len === 0 || paths[len-1] !== pathname){ 28 | if(PATHS_LENGTH === -1 || len < PATHS_LENGTH) 29 | paths.push(pathname) 30 | else{ 31 | for(let i = 0; i < len - 1; i++){ 32 | paths[i] = paths[i+1] 33 | } 34 | paths[len - 1] = pathname 35 | } 36 | } 37 | 38 | 39 | 40 | browserHistory.canBack = (paths.length > 1) 41 | }) 42 | 43 | 44 | window.addEventListener('popstate', function () { 45 | // if(paths.length > 1){ 46 | // paths.pop() 47 | // paths.pop() 48 | // browserHistory.canBack = (paths.length > 1) 49 | // } 50 | console.log('popstate') 51 | 52 | browserHistory.isBack = true 53 | 54 | }) 55 | } 56 | 57 | export default browserHistory 58 | -------------------------------------------------------------------------------- /src/resources/img/i-form-comment-ios.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /src/umeditor/tools/insert-image.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | // import classnames from 'classnames' 3 | require('../plugins/inserthtml.js') 4 | require('../plugins/image.js') 5 | 6 | class InsertImage extends React.Component{ 7 | constructor(props) { 8 | super(props); 9 | this.edit = props.edit 10 | this.state = { 11 | } 12 | } 13 | 14 | 15 | componentDidMount(){ 16 | } 17 | 18 | handleInsertImage(event){ 19 | var files =[].slice.call(event.target.files, 0), 20 | file = files[0]; 21 | event.target.value = '' 22 | 23 | if(this.props.handler) { 24 | this.props.handler( file, (url) => { 25 | this.edit.execCommand('insertimage', { 26 | src: url, 27 | width: '100%' 28 | }, this, event) 29 | }) 30 | } else { 31 | this.edit.execCommand('insertimage', { 32 | src: URL.createObjectURL(file), 33 | width: '100%' 34 | }) 35 | } 36 | 37 | 38 | } 39 | 40 | render(){ 41 | return ( 42 | 43 | 44 | 45 | 46 | ) 47 | } 48 | } 49 | 50 | 51 | export default InsertImage 52 | -------------------------------------------------------------------------------- /examples/src/components/swiper/SwiperPaginationProgressPage.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import AnimationPage from '../Page' 3 | import classnames from 'classnames'; 4 | import Swiper from 'react-ui/swiper' 5 | 6 | class SwiperPaginationProgressPage extends AnimationPage{ 7 | constructor(props) { 8 | super(props); 9 | } 10 | 11 | componentDidMount(){ 12 | new Swiper(this.refs.slider, {pagination:'.swiper-pagination', paginationType: 'progress'}) 13 | } 14 | 15 | render(){ 16 | return ( 17 |
18 |
19 |
20 |
21 |
22 |
Slide 1
23 |
Slide 2
24 |
Slide 3
25 |
Slide 4
26 |
Slide 5
27 |
Slide 6
28 |
Slide 7
29 |
Slide 8
30 |
Slide 9
31 |
Slide 10
32 |
33 |
34 |
35 |
36 | ) 37 | } 38 | } 39 | 40 | module.exports = SwiperPaginationProgressPage 41 | -------------------------------------------------------------------------------- /src/umeditor/plugins/print.js: -------------------------------------------------------------------------------- 1 | ///import core 2 | ///commands 打印 3 | ///commandsName Print 4 | ///commandsTitle 打印 5 | /** 6 | * @description 打印 7 | * @name baidu.editor.execCommand 8 | * @param {String} cmdName print打印编辑器内容 9 | * @author zhanyi 10 | */ 11 | /* eslint quotes : "off"*/ 12 | import UM from '../um' 13 | import $ from '../../dom' 14 | // import browser from '../core/browser' 15 | // import utils from '../core/utils' 16 | UM.commands['print'] = { 17 | execCommand : function(){ 18 | var me = this, 19 | id = 'editor_print_' + +new Date(); 20 | 21 | $('').attr('id', id) 22 | .css({ 23 | width:'0px', 24 | height:'0px', 25 | 'overflow':'hidden', 26 | 'float':'left', 27 | 'position':'absolute', 28 | top:'-10000px', 29 | left:'-10000px' 30 | }) 31 | .appendTo(me.$container.find('.edui-dialog-container')); 32 | 33 | var w = window.open('', id, ''), 34 | d = w.document; 35 | d.open(); 36 | d.write('
'+this.getContent(null,null,true)+'
'); 44 | d.close(); 45 | }, 46 | notNeedUndo : 1 47 | }; -------------------------------------------------------------------------------- /examples/src/components/clip-image/ClipImagePage.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import AnimationPage from '../Page' 3 | import classnames from 'classnames'; 4 | import ImageCliper from 'react-ui/image-cliper' 5 | require('../../resources/less/clip-image.less') 6 | class ClipImagePage extends AnimationPage{ 7 | constructor(props) { 8 | super(props); 9 | this.state = {} 10 | } 11 | 12 | componentDidMount(){ 13 | } 14 | 15 | 16 | 17 | onSelectImage(event){ 18 | var files =[].slice.call(event.target.files, 0), 19 | file = files[0]; 20 | 21 | var onClip = (blob) => { 22 | var url = URL.createObjectURL(blob); 23 | this.setState({ 24 | url : url 25 | }) 26 | } 27 | 28 | ImageCliper.imageCliper({ 29 | type: 'page', 30 | file: file, 31 | onClip: onClip, 32 | ratio:1, 33 | fill: true 34 | }).open() 35 | event.target.value = '' 36 | } 37 | 38 | render(){ 39 | return ( 40 |
41 |
42 |
43 | 44 |
45 | 46 |
47 | {this.state.url ? : ''} 48 |
49 | 50 |
51 |
52 | ) 53 | } 54 | } 55 | 56 | module.exports = ClipImagePage 57 | -------------------------------------------------------------------------------- /src/draft-editor/tools/list-item.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import classnames from 'classnames' 3 | 4 | 5 | var listTypes = [ 6 | {label: 'UL', style: 'unordered-list-item', icon: 'icon-unordered-list-item'}, 7 | {label: 'OL', style: 'ordered-list-item', icon: 'icon-ordered-list-item'} 8 | ]; 9 | 10 | class ListItem extends React.Component{ 11 | constructor(props) { 12 | super(props); 13 | this.edit = props.edit 14 | } 15 | 16 | handleChangeListItem(value){ 17 | // var commandState = this.state.commandState 18 | // commandState[value] = this.doc.queryCommandState(value) 19 | // this.setState(commandState) 20 | 21 | this.edit.toggleBlockType(value) 22 | // this.updateCommandState() 23 | } 24 | 25 | render(){ 26 | var selection = this.edit.state.editorState.getSelection(); 27 | var blockType = this.edit.state.editorState.getCurrentContent().getBlockForKey(selection.getStartKey()).getType(); 28 | return ( 29 |
30 |
项目符合/编号
31 |
32 | { 33 | listTypes.map(item => ( 34 |
35 | 36 | 37 |
38 | )) 39 | } 40 |
41 |
42 | ) 43 | } 44 | } 45 | 46 | 47 | export default ListItem 48 | -------------------------------------------------------------------------------- /examples/src/components/tabs/TabsPage.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import {Link} from 'react-router' 3 | import AnimationPage from '../Page' 4 | import classNames from 'classnames'; 5 | import {List} from 'react-ui/lists' 6 | 7 | class TabsPage extends AnimationPage{ 8 | constructor(props) { 9 | super(props); 10 | } 11 | 12 | 13 | 14 | render(){ 15 | return ( 16 |
17 |
18 | 19 | 20 |
21 |
22 |
Static Tabs
23 |
24 | 25 |
26 |
27 |
Animated Tabs
28 |
29 | 30 |
31 |
32 |
Swipeable Tabs
33 |
NEW
34 |
35 |
36 |
37 |
38 | ) 39 | } 40 | } 41 | 42 | module.exports = TabsPage 43 | -------------------------------------------------------------------------------- /src/resources/img/i-form-settings-ios.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/draft-editor/tools/font-size.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import classnames from 'classnames' 3 | require('../../resources/less/scroll.less') 4 | var prefix = 'fontSize' 5 | var fontsizeList = [12, 16, 18, 24, 32, 48]; 6 | var fontSizeStyleMap = (function(){ 7 | return fontsizeList.reduce((res, item) => { 8 | 9 | res[prefix+item] = { 10 | 'fontSize': item+'px' 11 | } 12 | return res; 13 | }, {}) 14 | })() 15 | 16 | class FontSize extends React.Component{ 17 | constructor(props) { 18 | super(props); 19 | this.edit = props.edit 20 | this.state = { 21 | } 22 | } 23 | 24 | handleChangeFontSize(value ){ 25 | 26 | this.setState({ 27 | value: value 28 | }) 29 | this.edit.toggleFontSize(prefix+value) 30 | } 31 | 32 | render(){ 33 | return ( 34 |
35 |
字体大小
36 |
37 |
38 | { 39 | fontsizeList.map(value => ( 40 |
41 | 42 | {value}px 43 |
44 | )) 45 | } 46 | 47 | 48 |
49 |
50 |
51 | ) 52 | } 53 | } 54 | 55 | export { 56 | fontSizeStyleMap 57 | } 58 | 59 | export default FontSize 60 | -------------------------------------------------------------------------------- /src/umeditor/tools/justify.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import classnames from 'classnames' 3 | 4 | var justifyList = ['justifyLeft', 'justifyCenter', 'justifyRight', 'justifyFull']; 5 | var justifyIcons = { 6 | justifyLeft: 'icon-justify-left', 7 | justifyCenter: 'icon-justify-center', 8 | justifyRight: 'icon-justify-right', 9 | justifyFull: 'icon-justify-full' 10 | } 11 | 12 | class Justify extends React.Component{ 13 | constructor(props) { 14 | super(props); 15 | this.doc = document 16 | this.state = { 17 | commandState: {} 18 | } 19 | this.destroyList = [] 20 | } 21 | 22 | 23 | 24 | destroy(){ 25 | this.destroyList.forEach((fun) => { 26 | fun() 27 | }) 28 | } 29 | 30 | handleChangeJustify(value){ 31 | // var commandState = this.state.commandState 32 | // commandState[value] = this.doc.queryCommandState(value) 33 | // this.setState(commandState) 34 | 35 | this.doc.execCommand(value) 36 | // this.updateCommandState() 37 | } 38 | 39 | render(){ 40 | return ( 41 |
42 |
对齐
43 |
44 | { 45 | justifyList.map(value => ( 46 |
47 | 48 | 49 |
50 | )) 51 | } 52 |
53 |
54 | ) 55 | } 56 | } 57 | 58 | 59 | module.exports = Justify 60 | -------------------------------------------------------------------------------- /src/draft-editor/tools/justify.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import classnames from 'classnames' 3 | 4 | var justifyList = ['justifyLeft', 'justifyCenter', 'justifyRight', 'justifyFull']; 5 | var justifyIcons = { 6 | justifyLeft: 'icon-justify-left', 7 | justifyCenter: 'icon-justify-center', 8 | justifyRight: 'icon-justify-right', 9 | justifyFull: 'icon-justify-full' 10 | } 11 | 12 | class Justify extends React.Component{ 13 | constructor(props) { 14 | super(props); 15 | this.doc = document 16 | this.state = { 17 | commandState: {} 18 | } 19 | this.destroyList = [] 20 | } 21 | 22 | 23 | 24 | destroy(){ 25 | this.destroyList.forEach((fun) => { 26 | fun() 27 | }) 28 | } 29 | 30 | handleChangeJustify(value){ 31 | // var commandState = this.state.commandState 32 | // commandState[value] = this.doc.queryCommandState(value) 33 | // this.setState(commandState) 34 | 35 | this.doc.execCommand(value) 36 | // this.updateCommandState() 37 | } 38 | 39 | render(){ 40 | return ( 41 |
42 |
对齐
43 |
44 | { 45 | justifyList.map(value => ( 46 |
47 | 48 | 49 |
50 | )) 51 | } 52 |
53 |
54 | ) 55 | } 56 | } 57 | 58 | 59 | module.exports = Justify 60 | -------------------------------------------------------------------------------- /src/resources/less/content-block.less: -------------------------------------------------------------------------------- 1 | @import url('_mixins.less'); 2 | @import url('_colors-vars.less'); 3 | 4 | /* === Content Block === */ 5 | @contentBlockBorderColor: #c8c7cc; 6 | @contentBlockColor: #6d6d72; 7 | @contentBlockTitle: @contentBlockColor; 8 | .content-block { 9 | margin: 35px 0; 10 | padding: 0 15px; 11 | color: @contentBlockTitle; 12 | box-sizing: border-box; 13 | } 14 | .content-block-title { 15 | position: relative; 16 | overflow: hidden; 17 | margin: 0; 18 | white-space: nowrap; 19 | text-overflow: ellipsis; 20 | font-size: 14px; 21 | text-transform: uppercase; 22 | line-height: 1; 23 | color: @contentBlockColor; 24 | margin: 35px 15px 10px; 25 | + .list-block, + .content-block, +.card { 26 | margin-top: 10px; 27 | } 28 | } 29 | .content-block-inner { 30 | background: #fff; 31 | padding: 10px 15px; 32 | margin-left: -15px; 33 | width: 100%; 34 | position: relative; 35 | .hairline(top, @contentBlockBorderColor); 36 | .hairline(bottom, @contentBlockBorderColor); 37 | color: #000; 38 | } 39 | .content-block.inset { 40 | margin-left: 15px; 41 | margin-right: 15px; 42 | border-radius: 7px; 43 | .content-block-inner { 44 | .hairline-remove(top); 45 | .hairline-remove(bottom); 46 | border-radius: 7px; 47 | } 48 | } 49 | @media all and (min-width:768px) { 50 | .content-block.tablet-inset { 51 | margin-left: 15px; 52 | margin-right: 15px; 53 | border-radius: 7px 54 | } 55 | 56 | .content-block.tablet-inset .content-block-inner { 57 | .hairline-remove(top); 58 | .hairline-remove(bottom); 59 | border-radius: 7px; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/resources/img/i-form-name-ios.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /src/plugins.js: -------------------------------------------------------------------------------- 1 | /*======================================= 2 | ************ Plugins API ************ 3 | =======================================*/ 4 | import reactUI from './react-ui' 5 | import PARAMS from './params' 6 | var plugins = {} 7 | var _plugins = []; 8 | 9 | var $ = {} 10 | $.initPlugins = reactUI.initPlugins = function () { 11 | // Initialize plugins 12 | for (var plugin in plugins) { 13 | var p = plugins[plugin](reactUI, PARAMS[plugin]); 14 | if (p) _plugins.push(p); 15 | } 16 | }; 17 | // Plugin Hooks 18 | $.pluginHook = reactUI.pluginHook = function (hook) { 19 | for (var i = 0; i < _plugins.length; i++) { 20 | if (_plugins[i].hooks && hook in _plugins[i].hooks) { 21 | _plugins[i].hooks[hook](arguments[1], arguments[2], arguments[3], arguments[4], arguments[5]); 22 | } 23 | } 24 | }; 25 | // Prevented by plugin 26 | $.pluginPrevent = reactUI.pluginPrevent = function (action) { 27 | var prevent = false; 28 | for (var i = 0; i < _plugins.length; i++) { 29 | if (_plugins[i].prevents && action in _plugins[i].prevents) { 30 | if (_plugins[i].prevents[action](arguments[1], arguments[2], arguments[3], arguments[4], arguments[5])) prevent = true; 31 | } 32 | } 33 | return prevent; 34 | }; 35 | // Preprocess content by plugin 36 | $.pluginProcess = reactUI.pluginProcess = function (process, data) { 37 | var processed = data; 38 | for (var i = 0; i < _plugins.length; i++) { 39 | if (_plugins[i].preprocess && process in _plugins[i].preprocess) { 40 | processed = _plugins[i].preprocess[process](data, arguments[2], arguments[3], arguments[4], arguments[5], arguments[6]); 41 | } 42 | } 43 | return processed; 44 | }; 45 | 46 | export default $; 47 | 48 | -------------------------------------------------------------------------------- /examples/src/components/kind-editor/EditorPage.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import AnimationPage from '../Page' 3 | import classnames from 'classnames'; 4 | import Editor from 'react-ui/editor' 5 | // require('react-ui/editor/plugins/image') 6 | require('react-ui/editor/lang/zh_CN') 7 | 8 | class EditorPage extends AnimationPage{ 9 | constructor(props) { 10 | super(props); 11 | } 12 | 13 | componentDidMount(){ 14 | this.editor = Editor.create('textarea[name="content"]', { 15 | resizeType : 1, 16 | allowPreviewEmoticons : false, 17 | allowImageUpload : true, 18 | // fullscreenMode: true, 19 | width: '100%', 20 | height: '100%', 21 | items : [ 22 | 'fontname', 'fontsize', '|', 'forecolor', 'hilitecolor', 'bold', 'italic', 'underline', 23 | 'removeformat', '|', 'justifyleft', 'justifycenter', 'justifyright', 'insertorderedlist', 24 | 'insertunorderedlist', '|', 'emoticons', 'image', 'link'] 25 | }); 26 | } 27 | handleGetHtml(e){ 28 | e.preventDefault() 29 | alert(this.editor.html()); 30 | } 31 | render(){ 32 | return ( 33 |
34 |
35 |
36 | 37 |
38 |
39 |
40 |
41 | Get Html 42 | Menu 43 |
44 |
45 |
46 | ) 47 | } 48 | } 49 | 50 | module.exports = EditorPage 51 | -------------------------------------------------------------------------------- /src/draft-editor/tools/link.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import TextFieldEditor from '../../widget/textfield-editor' 3 | 4 | class CreateLink extends React.Component{ 5 | constructor(props) { 6 | super(props); 7 | this.edit = props.edit 8 | this.state = { 9 | } 10 | } 11 | 12 | 13 | componentDidMount(){ 14 | } 15 | 16 | handleCreateLink(event){ 17 | event.preventDefault() 18 | const {editorState} = this.edit.state; 19 | const selection = editorState.getSelection(); 20 | if (selection.isCollapsed()) { 21 | alert('请选择加超链接的文本') 22 | return; 23 | } 24 | TextFieldEditor.open({ 25 | title: '填写链接地址', 26 | showType: 'popup', 27 | onOk: (val) => { 28 | this.edit.createLink(val) 29 | } 30 | }) 31 | // this.doc.execCommand('insertHTML', false, '
'); 32 | } 33 | 34 | render(){ 35 | return ( 36 | 37 | 38 | 39 | ) 40 | } 41 | } 42 | 43 | class RemoveLink extends React.Component{ 44 | constructor(props) { 45 | super(props); 46 | this.edit = props.edit 47 | this.state = { 48 | } 49 | } 50 | 51 | 52 | componentDidMount(){ 53 | } 54 | 55 | handleRemoveLink(event){ 56 | event.preventDefault() 57 | this.edit.removeLink() 58 | // this.doc.execCommand('insertHTML', false, '
'); 59 | } 60 | 61 | render(){ 62 | return ( 63 | 64 | 65 | 66 | ) 67 | } 68 | } 69 | 70 | export { 71 | CreateLink, 72 | RemoveLink 73 | } 74 | 75 | export default CreateLink 76 | -------------------------------------------------------------------------------- /examples/src/components/View.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import ReactTransitionGroup from 'react/lib/ReactTransitionGroup' 3 | import ReactUI from 'react-ui/react-ui' 4 | import classNames from 'classnames'; 5 | 6 | class View extends React.Component{ 7 | constructor(props) { 8 | super(props); 9 | } 10 | 11 | render(){ 12 | let navbar = this.props.navbar 13 | let page = this.props.page 14 | let toolbar =this.props.toolbar 15 | 16 | return ( 17 | 18 |
19 | {/*-----navbar------*/} 20 | 21 | {navbar ? React.cloneElement(navbar, { 22 | key: (this.props.location ? this.props.location.pathname.concat('/navbar') : ReactUI.guid() ), 23 | pageName: location.pathname==='/' ? 'index' : location.pathname.charAt(0) === '/' ? location.pathname.substring(1) : location.pathname 24 | }) : '' } 25 | 26 | 27 | {/*-----pages-------*/} 28 | 29 | {React.cloneElement(page, { 30 | className: {'navbar-through': !!navbar, 'toolbar-through': !!toolbar, 'tabbar-labels-through': !!toolbar}, 31 | key: (this.props.location ? this.props.location.pathname : ReactUI.guid() ), 32 | pageName: location.pathname==='/' ? 'index' : location.pathname.charAt(0) === '/' ? location.pathname.substring(1) : location.pathname 33 | })} 34 | 35 | 36 | {/*-----Toobar-------*/} 37 | 38 | { toolbar ? toolbar : ''} 39 | {/*-----toolbar end -------*/} 40 |
41 | ); 42 | } 43 | 44 | } 45 | 46 | module.exports = View 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /examples/src/components/panels/RightPanel.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | require('react-ui/resources/less/lists.less') 3 | require('react-ui/resources/less/content-block.less') 4 | 5 | export default class RightPanel extends React.Component{ 6 | render(){ 7 | return ( 8 |
9 |
10 |
11 |
Right Panel
12 |
13 |
14 |
15 |
16 |
17 |
18 |

This is a right side panel. You can close it by clicking outsite or on this link: 19 | close me. 20 | You can put here anything, even another isolated view, try it: 21 |

22 |
23 | 45 |
46 |
47 |
48 |
49 | 50 | ) 51 | } 52 | } -------------------------------------------------------------------------------- /src/resources/img/i-form-tel-ios.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /src/view.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | //import ReactTransitionGroup from 'react/lib/ReactTransitionGroup'; 3 | import ReactTransitionGroup from 'ReactTransitionGroup' 4 | import ReactUI from './react-ui'; 5 | import classNames from 'classnames'; 6 | 7 | class View extends React.Component{ 8 | constructor(props) { 9 | super(props); 10 | } 11 | 12 | render(){ 13 | let navbar = this.props.navbar 14 | let page = this.props.page 15 | let toolbar =this.props.toolbar 16 | 17 | return ( 18 | 19 |
20 | {/*-----navbar------*/} 21 | 22 | {navbar ? React.cloneElement(navbar, { 23 | key: (this.props.location ? this.props.location.pathname.concat('/navbar') : ReactUI.guid() ), 24 | pageName: location.pathname==='/' ? 'index' : location.pathname.charAt(0) === '/' ? location.pathname.substring(1) : location.pathname 25 | }) : '' } 26 | 27 | 28 | {/*-----pages-------*/} 29 | 30 | {React.cloneElement(page, { 31 | className: {'navbar-through': !!navbar, 'toolbar-through': !!toolbar, 'tabbar-labels-through': !!toolbar}, 32 | key: (this.props.location ? this.props.location.pathname : ReactUI.guid() ), 33 | pageName: location.pathname==='/' ? 'index' : location.pathname.charAt(0) === '/' ? location.pathname.substring(1) : location.pathname 34 | })} 35 | 36 | 37 | {/*-----Toobar-------*/} 38 | 39 | { toolbar ? toolbar : ''} 40 | {/*-----toolbar end -------*/} 41 |
42 | ); 43 | } 44 | 45 | } 46 | 47 | module.exports = View 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /examples/src/components/Tabbar.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Link, IndexLink } from 'react-router' 3 | import Navbar from './Navbar' 4 | import Page from './Page' 5 | let classNames = require('classnames'); 6 | 7 | class Tabbar extends React.Component{ 8 | constructor(props) { 9 | super(props); 10 | } 11 | 12 | handleTabClick(){ 13 | Page.anim = false 14 | Navbar.anim = false 15 | //window.alert('cick') 16 | } 17 | 18 | render(){ 19 | return ( 20 |
21 |
22 | 23 | 24 | 首页 25 | 26 | 27 | 28 | 29 | 社团 30 | 31 | 32 | 33 | 34 | 类目 35 | 36 | 37 | 38 | 39 | 动态 40 | 41 | 42 | 43 | 44 | 4 45 | 46 | 设置 47 | 48 |
49 |
50 | ); 51 | } 52 | } 53 | 54 | module.exports = Tabbar 55 | -------------------------------------------------------------------------------- /src/browser.js: -------------------------------------------------------------------------------- 1 | var agent = navigator.userAgent.toLowerCase(), 2 | opera = window.opera; 3 | var browser = { 4 | /** 5 | * 微信 6 | * 7 | */ 8 | weixin : /micromessenger/i.test(agent), 9 | /** 10 | * @property {boolean} ie 检测当前浏览器是否为IE 11 | * @example 12 | * ```javascript 13 | * if ( UE.browser.ie ) { 14 | * console.log( '当前浏览器是IE' ); 15 | * } 16 | * ``` 17 | */ 18 | ie : /(msie\s|trident.*rv:)([\w.]+)/.test(agent), 19 | 20 | /** 21 | * @property {boolean} opera 检测当前浏览器是否为Opera 22 | * @example 23 | * ```javascript 24 | * if ( UE.browser.opera ) { 25 | * console.log( '当前浏览器是Opera' ); 26 | * } 27 | * ``` 28 | */ 29 | opera : ( !!opera && opera.version ), 30 | 31 | /** 32 | * @property {boolean} webkit 检测当前浏览器是否是webkit内核的浏览器 33 | * @example 34 | * ```javascript 35 | * if ( UE.browser.webkit ) { 36 | * console.log( '当前浏览器是webkit内核浏览器' ); 37 | * } 38 | * ``` 39 | */ 40 | webkit : ( agent.indexOf( ' applewebkit/' ) > -1 ), 41 | 42 | /** 43 | * @property {boolean} mac 检测当前浏览器是否是运行在mac平台下 44 | * @example 45 | * ```javascript 46 | * if ( UE.browser.mac ) { 47 | * console.log( '当前浏览器运行在mac平台下' ); 48 | * } 49 | * ``` 50 | */ 51 | mac : ( agent.indexOf( 'macintosh' ) > -1 ), 52 | 53 | /** 54 | * @property {boolean} quirks 检测当前浏览器是否处于“怪异模式”下 55 | * @example 56 | * ```javascript 57 | * if ( UE.browser.quirks ) { 58 | * console.log( '当前浏览器运行处于“怪异模式”' ); 59 | * } 60 | * ``` 61 | */ 62 | quirks : ( document.compatMode == 'BackCompat' ) 63 | }; 64 | 65 | /** 66 | * @property {boolean} gecko 检测当前浏览器内核是否是gecko内核 67 | * @example 68 | * ```javascript 69 | * if ( UE.browser.gecko ) { 70 | * console.log( '当前浏览器内核是gecko内核' ); 71 | * } 72 | * ``` 73 | */ 74 | browser.gecko =( navigator.product == 'Gecko' && !browser.webkit && !browser.opera && !browser.ie); 75 | 76 | export default browser; 77 | -------------------------------------------------------------------------------- /src/editor/tools/font-color.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import classnames from 'classnames' 3 | require('../../resources/less/grid.less') 4 | 5 | var fontColorList = [ 6 | ['#E53333', '#E56600', '#FF9900', '#64451D'], 7 | ['#DFC5A4', '#FFE500', '#009900', '#006600'], 8 | ['#99BB00', '#B8D100', '#60D978', '#00D5FF'], 9 | ['#337FE5', '#003399', '#4C33E5', '#9933E5'], 10 | ['#CC33E5', '#EE33EE', '#FFFFFF', '#CCCCCC'], 11 | ['#999999', '#666666', '#333333', '#000000'] 12 | ]; 13 | 14 | class FontColor extends React.Component{ 15 | constructor(props) { 16 | super(props); 17 | this.doc = document 18 | this.state = { 19 | 20 | } 21 | } 22 | 23 | 24 | componentDidMount(){ 25 | } 26 | 27 | 28 | 29 | handleChangeFontColor(value , event){ 30 | 31 | this.setState({ 32 | value: value 33 | }) 34 | this.doc.execCommand('forecolor', false, value) 35 | } 36 | 37 | render(){ 38 | return ( 39 |
40 |
字体颜色
41 |
42 |
43 | { 44 | fontColorList.map((list, index) => { 45 | return ( 46 |
47 | { 48 | list.map((val) => ( 49 |
50 |
51 | 52 |
53 |
54 | )) 55 | } 56 |
57 | ) 58 | }) 59 | } 60 |
61 |
62 |
63 | ) 64 | } 65 | } 66 | 67 | 68 | module.exports = FontColor 69 | -------------------------------------------------------------------------------- /src/resources/less/autocomplete.less: -------------------------------------------------------------------------------- 1 | /* === Autocomplete === */ 2 | .autocomplete-page { 3 | .autocomplete-found { 4 | display: block; 5 | } 6 | .autocomplete-not-found { 7 | display: none; 8 | } 9 | .autocomplete-values { 10 | display: block; 11 | } 12 | .list-block ul:empty { 13 | display: none; 14 | } 15 | } 16 | .autocomplete-preloader:not(.autocomplete-preloader-visible) { 17 | -webkit-animation: none; 18 | animation: none; 19 | visibility: hidden; 20 | } 21 | 22 | .autocomplete-dropdown { 23 | background: #fff; 24 | box-sizing: border-box; 25 | position: absolute; 26 | z-index: 500; 27 | box-shadow: 0px 3px 3px rgba(0,0,0,0.2); 28 | width: 100%; 29 | left: 0; 30 | .autocomplete-dropdown-inner { 31 | position: relative; 32 | overflow: auto; 33 | -webkit-overflow-scrolling: touch; 34 | height: 100%; 35 | z-index: 1; 36 | } 37 | .autocomplete-preloader { 38 | display: none; 39 | position: absolute; 40 | right: 15px; 41 | bottom: 100%; 42 | margin-bottom: 12px; 43 | width: 20px; 44 | height: 20px; 45 | } 46 | .autocomplete-preloader-visible { 47 | display: block; 48 | } 49 | .autocomplete-dropdown-placeholder { 50 | color: #a9a9a9; 51 | } 52 | .list-block { 53 | margin: 0; 54 | ul { 55 | .hairline-remove(top); 56 | .hairline-remove(bottom); 57 | background: none !important; 58 | } 59 | b { 60 | font-weight: 500; 61 | html.ios-gt-8 & { 62 | font-weight: 600; 63 | } 64 | } 65 | } 66 | } 67 | .list-block { 68 | .item-content-dropdown-expand { 69 | .item-title.label { 70 | width: 0; 71 | .flex-shrink(10); 72 | + .item-input { 73 | margin-left: 0; 74 | } 75 | } 76 | .item-input { 77 | width: 100%; 78 | } 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /examples/src/components/tabs-static/TabsStaticNavbar.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import ReactDOM from 'react-dom'; 3 | import Navbar from '../Navbar' 4 | import Panels from 'react-ui/panels' 5 | import Tabs from 'react-ui/tabs' 6 | import history from 'react-ui/history' 7 | import LeftPanelContent from '../panels/LeftPanel' 8 | 9 | class TabsNavBar extends Navbar{ 10 | 11 | 12 | constructor(props) { 13 | super(props); 14 | 15 | } 16 | 17 | componentDidMount(){ 18 | super.componentDidMount() 19 | new Tabs({tabbar: this.refs.tabbar}) 20 | } 21 | 22 | handleClickOpenLeftPanel(event){ 23 | event.preventDefault() 24 | //panel-reveal 25 | var panel = Panels.openPanel({position: 'left', className: 'layout-dark'}) 26 | var onClose = (event) => { 27 | event.preventDefault() 28 | Panels.closePanel(panel) 29 | } 30 | ReactDOM.render(, panel) 31 | } 32 | 33 | render(){ 34 | if(this.canBack === undefined){ 35 | this.canBack = history.canBack; 36 | } 37 | return ( 38 |
39 | { 40 | this.canBack ? 41 |
返回
: '' 42 | } 43 |
Tabs Static
44 |
45 | 46 |
47 |
48 |
49 | Tab 1 50 | Tab 2 51 | Tab 3 52 |
53 |
54 |
55 | ) 56 | } 57 | } 58 | 59 | 60 | module.exports = TabsNavBar -------------------------------------------------------------------------------- /src/editor/tools/font-shape.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import classnames from 'classnames' 3 | import $ from '../../dom' 4 | import SupportEvents from '../../support-events' 5 | var fontShapList = ['bold', 'italic', 'underline'] 6 | class FontShape extends React.Component{ 7 | constructor(props) { 8 | super(props); 9 | this.doc = document 10 | this.state = { 11 | commandState: {} 12 | } 13 | this.destroyList = [] 14 | } 15 | 16 | 17 | 18 | 19 | updateCommandState(){ 20 | var commandState = this.state.commandState; 21 | fontShapList.forEach(val => { 22 | commandState[val] = this.doc.queryCommandState(val) 23 | }) 24 | this.setState({ 25 | commandState: commandState 26 | }) 27 | } 28 | 29 | componentDidMount(){ 30 | 31 | var fn = () => { 32 | // console.log('bold', this.doc.queryCommandState('bold'), typeof this.doc.queryCommandState('bold')) 33 | this.updateCommandState() 34 | } 35 | 36 | $(this.doc).on(SupportEvents.touchEvents.end, fn) 37 | 38 | this.destroyList.push(()=> { 39 | $(this.doc).off(SupportEvents.touchEvents.end, fn) 40 | }) 41 | } 42 | 43 | componentWillUnmount(){ 44 | this.destroy() 45 | } 46 | 47 | destroy(){ 48 | this.destroyList.forEach((fun) => { 49 | fun() 50 | }) 51 | } 52 | 53 | handleClickFontBtn(cmd, e){ 54 | e.preventDefault() 55 | console.log('font-shap', cmd) 56 | this.doc.execCommand(cmd) 57 | this.updateCommandState() 58 | } 59 | 60 | render(){ 61 | return ( 62 |
63 |
字形
64 |
65 | { 66 | fontShapList.map(val => ( 67 | 68 | 69 | 70 | )) 71 | } 72 |
73 |
74 | ) 75 | } 76 | } 77 | 78 | 79 | module.exports = FontShape 80 | -------------------------------------------------------------------------------- /examples/src/components/tabs-animated/TabsAnimatedNavbar.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import ReactDOM from 'react-dom'; 3 | import Navbar from '../Navbar' 4 | import Panels from 'react-ui/panels' 5 | import Tabs from 'react-ui/tabs' 6 | import history from 'react-ui/history' 7 | 8 | import LeftPanelContent from '../panels/LeftPanel' 9 | 10 | 11 | 12 | 13 | class TabsNavBar extends Navbar{ 14 | 15 | 16 | constructor(props) { 17 | super(props); 18 | 19 | } 20 | 21 | componentDidMount(){ 22 | super.componentDidMount() 23 | var tabs = new Tabs({tabbar: this.refs.tabbar}) 24 | } 25 | 26 | handleClickOpenLeftPanel(event){ 27 | event.preventDefault() 28 | //panel-reveal 29 | var panel = Panels.openPanel({position: 'left', className: 'layout-dark'}) 30 | var onClose = (event) => { 31 | event.preventDefault() 32 | Panels.closePanel(panel) 33 | } 34 | ReactDOM.render(, panel) 35 | } 36 | 37 | render(){ 38 | if(this.canBack === undefined){ 39 | this.canBack = history.canBack; 40 | } 41 | return ( 42 |
43 | { 44 | this.canBack ? 45 |
返回
: '' 46 | } 47 |
Tabs Animated
48 |
49 | 50 |
51 |
52 |
53 | Tab 1 54 | Tab 2 55 | Tab 3 56 |
57 |
58 |
59 | ) 60 | } 61 | } 62 | 63 | 64 | module.exports = TabsNavBar -------------------------------------------------------------------------------- /examples/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-redux-tpl", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "cross-env BABEL_ENV=commonjs NODE_ENV=test mocha --compilers js:babel-register --recursive", 8 | "dev": "./node_modules/.bin/webpack --config webpack.dev.js", 9 | "build": "./node_modules/.bin/webpack --config webpack.prod.js", 10 | "start": "./node_modules/.bin/webpack-dev-server --open --config webpack.dev.js", 11 | "server": "node dev-server.js", 12 | "server:prod": "node server.js" 13 | }, 14 | "keywords": [], 15 | "author": "", 16 | "license": "ISC", 17 | "devDependencies": { 18 | "babel": "^6.23.0", 19 | "babel-core": "^6.26.0", 20 | "babel-eslint": "^8.0.1", 21 | "babel-loader": "^7.1.2", 22 | "babel-preset-es2015": "^6.24.1", 23 | "babel-preset-react": "^6.24.1", 24 | "babel-preset-stage-2": "^6.24.1", 25 | "chai": "^4.1.2", 26 | "clean-webpack-plugin": "^0.1.17", 27 | "cross-env": "^5.1.1", 28 | "css-loader": "^0.28.7", 29 | "eslint": "^4.10.0", 30 | "eslint-loader": "^1.9.0", 31 | "eslint-plugin-react": "^7.4.0", 32 | "express": "^4.16.2", 33 | "file-loader": "^1.1.5", 34 | "html-webpack-plugin": "^2.30.1", 35 | "jsdom": "^11.3.0", 36 | "less": "^2.7.3", 37 | "less-loader": "^4.0.5", 38 | "minimist": "^1.2.0", 39 | "mocha": "^4.0.1", 40 | "style-loader": "^0.19.0", 41 | "webpack": "^3.8.1", 42 | "webpack-dev-middleware": "^1.12.0", 43 | "webpack-dev-server": "^2.9.3", 44 | "webpack-manifest-plugin": "^1.3.2", 45 | "webpack-merge": "^4.1.1" 46 | }, 47 | "dependencies": { 48 | "classnames": "^2.2.5", 49 | "f7-react-ui": "^1.2.5", 50 | "lodash": "^4.17.4", 51 | "prop-types": "^15.6.0", 52 | "react": "^15.0.0", 53 | "react-dom": "^15.0.0", 54 | "react-redux": "^5.0.6", 55 | "react-router": "^2.8.1", 56 | "react-transition-group": "^1.2.1", 57 | "redux": "^3.7.2", 58 | 59 | "babel-polyfill": "^6.26.0", 60 | "draft-editor": "0.0.0", 61 | "draft-js": "^0.9.1", 62 | "quill": "^1.0.6", 63 | "react-contenteditable": "^2.0.5" 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/umeditor/tools/font-color.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import classnames from 'classnames' 3 | require('../../resources/less/grid.less') 4 | // var prefix = 'color' 5 | var fontColorList = [ 6 | ['#E53333', '#E56600', '#FF9900', '#64451D'], 7 | ['#DFC5A4', '#FFE500', '#009900', '#006600'], 8 | ['#99BB00', '#B8D100', '#60D978', '#00D5FF'], 9 | ['#337FE5', '#003399', '#4C33E5', '#9933E5'], 10 | ['#CC33E5', '#EE33EE', '#FFFFFF', '#CCCCCC'], 11 | ['#999999', '#666666', '#333333', '#000000'] 12 | ]; 13 | 14 | 15 | class FontColor extends React.Component{ 16 | constructor(props) { 17 | super(props); 18 | this.edit = props.edit 19 | this.state = { 20 | active: false 21 | } 22 | 23 | this.edit.addListener('selectionchange', () => { 24 | var state = this.edit.queryCommandState('forecolor'); 25 | this.setState({ 26 | value: state 27 | }) 28 | // $btn.edui().disabled(state == -1).active(state == 1) 29 | }); 30 | } 31 | 32 | handleExecCommand(value , event){ 33 | 34 | this.setState({ 35 | value: value 36 | }) 37 | this.edit.execCommand('forecolor', value) 38 | } 39 | 40 | render(){ 41 | return ( 42 |
43 |
字体颜色
44 |
45 |
46 | { 47 | fontColorList.map((list, index) => { 48 | return ( 49 |
50 | { 51 | list.map((val) => ( 52 |
53 | 54 | 55 |
56 | )) 57 | } 58 |
59 | ) 60 | }) 61 | } 62 |
63 |
64 |
65 | ) 66 | } 67 | } 68 | 69 | 70 | export default FontColor 71 | -------------------------------------------------------------------------------- /examples/src/components/popover/PopoverNavbar.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import ReactDOM from 'react-dom'; 3 | import Navbar from '../Navbar' 4 | import history from 'react-ui/history' 5 | import Modals from 'react-ui/modals' 6 | import List from 'react-ui/lists' 7 | 8 | class PopoverNavBar extends Navbar{ 9 | 10 | 11 | constructor(props) { 12 | super(props); 13 | } 14 | 15 | handleClickOpenPopoverMenu(e){ 16 | e.preventDefault() 17 | 18 | var modal = Modals.popover(e.target) 19 | var href = function(path){ 20 | history.push(path); 21 | Modals.closeModal(modal); 22 | } 23 | let PopoverMenu = () => ( 24 | 25 | Modals 26 | Popover 27 | Tabs 28 | Side Panels 29 | List View 30 | Forms 31 | 32 | ) 33 | 34 | ReactDOM.render(, modal.querySelector('.popover-inner')); 35 | modal.sizePopover() 36 | } 37 | 38 | render(){ 39 | if(this.canBack === undefined){ 40 | this.canBack = history.canBack; 41 | } 42 | return ( 43 |
44 | { 45 | this.canBack ? 46 | : '' 47 | } 48 | 49 |
{this.props.title || ''}
50 |
51 | 52 |
53 |
54 | ) 55 | } 56 | } 57 | 58 | PopoverNavBar.defaultProps = { 59 | title: 'Popover' 60 | } 61 | 62 | module.exports = PopoverNavBar -------------------------------------------------------------------------------- /src/editor/tag-map.js: -------------------------------------------------------------------------------- 1 | import Util from './util' 2 | 3 | var _INLINE_TAG_MAP = Util.toMap('a,abbr,acronym,b,basefont,bdo,big,br,button,cite,code,del,dfn,em,font,i,img,input,ins,kbd,label,map,q,s,samp,select,small,span,strike,strong,sub,sup,textarea,tt,u,var') 4 | var _BLOCK_TAG_MAP = Util.toMap('address,applet,blockquote,body,center,dd,dir,div,dl,dt,fieldset,form,frameset,h1,h2,h3,h4,h5,h6,head,hr,html,iframe,ins,isindex,li,map,menu,meta,noframes,noscript,object,ol,p,pre,script,style,table,tbody,td,tfoot,th,thead,title,tr,ul') 5 | var _SINGLE_TAG_MAP = Util.toMap('area,base,basefont,br,col,frame,hr,img,input,isindex,link,meta,param,embed') 6 | var _STYLE_TAG_MAP = Util.toMap('b,basefont,big,del,em,font,i,s,small,span,strike,strong,sub,sup,u') 7 | var _CONTROL_TAG_MAP = Util.toMap('img,table,input,textarea,button') 8 | var _PRE_TAG_MAP = Util.toMap('pre,style,script') 9 | var _NOSPLIT_TAG_MAP = Util.toMap('html,head,body,td,tr,table,ol,ul,li') 10 | var _AUTOCLOSE_TAG_MAP = Util.toMap('colgroup,dd,dt,li,options,p,td,tfoot,th,thead,tr') 11 | var _FILL_ATTR_MAP = Util.toMap('checked,compact,declare,defer,disabled,ismap,multiple,nohref,noresize,noshade,nowrap,readonly,selected') 12 | var _VALUE_TAG_MAP = Util.toMap('input,button,textarea,select') 13 | 14 | 15 | var _INPUT_KEY_MAP = Util.toMap('8,9,13,32,46,48..57,59,61,65..90,106,109..111,188,190..192,219..222'); 16 | // 移动光标的键值 17 | var _CURSORMOVE_KEY_MAP = Util.toMap('33..40'); 18 | // 输入文字或移动光标的键值 19 | var _CHANGE_KEY_MAP = {}; 20 | Util.each(_INPUT_KEY_MAP, function(key, val) { 21 | _CHANGE_KEY_MAP[key] = val; 22 | }); 23 | Util.each(_CURSORMOVE_KEY_MAP, function(key, val) { 24 | _CHANGE_KEY_MAP[key] = val; 25 | }); 26 | 27 | var map = {} 28 | Object.assign(map, { 29 | INLINE_TAG_MAP: _INLINE_TAG_MAP, 30 | BLOCK_TAG_MAP: _BLOCK_TAG_MAP, 31 | SINGLE_TAG_MAP: _SINGLE_TAG_MAP, 32 | STYLE_TAG_MAP: _STYLE_TAG_MAP, 33 | CONTROL_TAG_MAP: _CONTROL_TAG_MAP, 34 | PRE_TAG_MAP: _PRE_TAG_MAP, 35 | NOSPLIT_TAG_MAP: _NOSPLIT_TAG_MAP, 36 | AUTOCLOSE_TAG_MAP: _AUTOCLOSE_TAG_MAP, 37 | FILL_ATTR_MAP: _FILL_ATTR_MAP, 38 | VALUE_TAG_MAP: _VALUE_TAG_MAP, 39 | 40 | INPUT_KEY_MAP: _INPUT_KEY_MAP, 41 | CURSORMOVE_KEY_MAP: _CURSORMOVE_KEY_MAP, 42 | CHANGE_KEY_MAP: _CHANGE_KEY_MAP 43 | }) 44 | 45 | export default map; 46 | -------------------------------------------------------------------------------- /src/resources/less/pull-to-refresh.less: -------------------------------------------------------------------------------- 1 | /* === Pull To Refresh === */ 2 | @import url('_mixins.less'); 3 | @import url('_colors-vars.less'); 4 | 5 | @toolbarSize: 44px; 6 | 7 | .pull-to-refresh-layer { 8 | position:absolute; 9 | position: relative; 10 | margin-top: -@toolbarSize; 11 | left:0; 12 | top:0; 13 | width:100%; 14 | height:@toolbarSize; 15 | 16 | .preloader { 17 | position: absolute; 18 | left: 50%; 19 | top: 50%; 20 | margin-left: -10px; 21 | margin-top: -10px; 22 | visibility: hidden; 23 | 24 | } 25 | .pull-to-refresh-arrow { 26 | width: 13px; 27 | height: 20px; 28 | position: absolute; 29 | left: 50%; 30 | top: 50%; 31 | margin-left: -6px; 32 | margin-top: -10px; 33 | background: no-repeat center; 34 | .encoded-svg-background(""); 35 | background-size: 13px 20px; 36 | z-index: 10; 37 | .transform(rotate(0deg) translate3d(0,0,0)); 38 | .transition(300ms); 39 | } 40 | 41 | } 42 | .pull-to-refresh-content { 43 | &.pull-to-refresh-no-navbar { 44 | margin-top: -@toolbarSize; 45 | height: ~"-webkit-calc(100% + @{toolbarSize})"; 46 | height: ~"-moz-calc(100% + @{toolbarSize})"; 47 | height: ~"calc(100% + @{toolbarSize})"; 48 | .pull-to-refresh-layer { 49 | margin-top: 0; 50 | } 51 | } 52 | &.transitioning, &.refreshing { 53 | .transition(400ms); 54 | } 55 | &:not(.refreshing) { 56 | .pull-to-refresh-layer .preloader { 57 | .animation(none); 58 | } 59 | } 60 | &.refreshing { 61 | .translate3d(0,@toolbarSize,0); 62 | .pull-to-refresh-arrow { 63 | visibility: hidden; 64 | .transition(0ms); 65 | } 66 | .preloader { 67 | visibility: visible; 68 | } 69 | } 70 | &.pull-up { 71 | .pull-to-refresh-arrow { 72 | .transform(rotate(180deg) translate3d(0,0,0)); 73 | } 74 | } 75 | 76 | } 77 | -------------------------------------------------------------------------------- /src/umeditor/tools/link.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import classnames from 'classnames' 3 | import TextFieldEditor from '../../widget/textfield-editor' 4 | require('../plugins/link.js') 5 | class CreateLink extends React.Component{ 6 | constructor(props) { 7 | super(props); 8 | this.edit = props.edit 9 | this.state = { 10 | } 11 | } 12 | 13 | 14 | componentDidMount(){ 15 | } 16 | 17 | handleCreateLink(event){ 18 | event.preventDefault() 19 | // const {editorState} = this.edit.state; 20 | // const selection = editorState.getSelection(); 21 | // if (selection.isCollapsed()) { 22 | // alert('请选择加超链接的文本') 23 | // return; 24 | // } 25 | TextFieldEditor.open({ 26 | title: '填写链接地址', 27 | showType: 'popup', 28 | onOk: (val) => { 29 | this.edit.execCommand('link', val) 30 | } 31 | }) 32 | } 33 | 34 | render(){ 35 | return ( 36 | 37 | 38 | 39 | ) 40 | } 41 | } 42 | 43 | class RemoveLink extends React.Component{ 44 | constructor(props) { 45 | super(props); 46 | this.edit = props.edit 47 | this.state = { 48 | } 49 | } 50 | 51 | 52 | componentDidMount(){ 53 | } 54 | 55 | handleRemoveLink(event){ 56 | event.preventDefault() 57 | this.edit.removeLink() 58 | // this.doc.execCommand('insertHTML', false, '
'); 59 | } 60 | 61 | render(){ 62 | return ( 63 | 64 | 65 | 66 | ) 67 | } 68 | } 69 | 70 | export { 71 | CreateLink, 72 | RemoveLink 73 | } 74 | 75 | export default CreateLink 76 | -------------------------------------------------------------------------------- /src/umeditor/top-toolbar-editor.js: -------------------------------------------------------------------------------- 1 | import Editor from './editor' 2 | import React from 'react' 3 | import ContentEditable from 'react-contenteditable' 4 | 5 | // import FontSize from './tools/font-size' 6 | // import FontColor from './tools/font-color' 7 | // import BackColor from './tools/back-color' 8 | // import FontShape from './tools/font-shape' 9 | // import FontFamily from './tools/font-family' 10 | // import Justify from './tools/justify' 11 | import InsertImage from './tools/insert-image' 12 | // import ListItem from './tools/list-item' 13 | // import HeadLine from './tools/headline' 14 | import {CreateLink} from './tools/link' 15 | require('../resources/less/editor/top-toolbar.less') 16 | require('../resources/less/editor/rich-editor.less') 17 | 18 | class Toolbar extends React.Component{ 19 | constructor(props) { 20 | super(props); 21 | this.handlers = this.props.handlers || {} 22 | 23 | } 24 | 25 | componentDidMount(){ 26 | } 27 | 28 | 29 | render(){ 30 | return ( 31 |
32 |
33 | 34 | 35 |
36 |
37 | ) 38 | } 39 | } 40 | 41 | class DefaultEditor extends Editor{ 42 | constructor(props) { 43 | super(props); 44 | this.state = { 45 | value: this.props.value || '' 46 | } 47 | } 48 | 49 | 50 | render(){ 51 | return ( 52 |
53 | 54 |
55 | 60 |
61 | 62 |
63 | ) 64 | } 65 | } 66 | 67 | 68 | const styles = { 69 | editorWrapper: { 70 | position: 'relative', 71 | width: '100%', 72 | height: '100%', 73 | overflow: 'hidden' 74 | 75 | } 76 | } 77 | 78 | export default DefaultEditor -------------------------------------------------------------------------------- /examples/src/components/tabs-swipeable/TabsSwipeableNavbar.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import ReactDOM from 'react-dom'; 3 | import Navbar from '../Navbar' 4 | import Panels from 'react-ui/panels' 5 | import Tabs from 'react-ui/tabs' 6 | import history from 'react-ui/history' 7 | 8 | import LeftPanelContent from '../panels/LeftPanel' 9 | 10 | 11 | 12 | class TabsNavBar extends Navbar{ 13 | 14 | 15 | constructor(props) { 16 | super(props); 17 | 18 | } 19 | componentWillUnmount(){ 20 | this.tabs.destroy() 21 | } 22 | 23 | componentDidMount(){ 24 | super.componentDidMount() 25 | this.tabs = new Tabs({tabbar: this.refs.tabbar}) 26 | this.tabs.on('show', (tab, tablink) => { 27 | console.log('tab', tab) 28 | }) 29 | } 30 | 31 | handleClickOpenLeftPanel(event){ 32 | event.preventDefault() 33 | //panel-reveal 34 | var panel = Panels.openPanel({position: 'left', className: 'layout-dark'}) 35 | var onClose = (event) => { 36 | event.preventDefault() 37 | Panels.closePanel(panel) 38 | } 39 | ReactDOM.render(, panel) 40 | } 41 | 42 | render(){ 43 | if(this.canBack === undefined){ 44 | this.canBack = history.canBack; 45 | } 46 | return ( 47 |
48 | { 49 | this.canBack ? 50 | : '' 51 | } 52 |
Tabs Swipeable
53 |
54 | 55 |
56 |
57 |
58 | Tab 1 59 | Tab 2 60 | Tab 3 61 |
62 |
63 |
64 | ) 65 | } 66 | } 67 | 68 | 69 | module.exports = TabsNavBar -------------------------------------------------------------------------------- /examples/src/index.js: -------------------------------------------------------------------------------- 1 | // import 'core-js/fn/object/assign'; 2 | // import React from 'react'; 3 | // import ReactDOM from 'react-dom'; 4 | // import { Router, Route,browserHistory,IndexRoute } from 'react-router' 5 | 6 | // import HomeView from './components/home/HomeView' 7 | // import SettingView from './components/tab/SettingView' 8 | // import AnimationView from './components/tab/AnimationView' 9 | // import App from './App'; 10 | // require('react-ui/resources/less/intro.less'); 11 | // require('react-ui/resources/less/icons.less'); 12 | // require('react-ui/resources/less/views.less'); 13 | // require('react-ui/resources/less/pages.less'); 14 | // require('./resources/less/app.less') 15 | // require('react-ui/resources/less/react-ui.ios.colors.less') 16 | 17 | // // Render the main component into the dom 18 | // ReactDOM.render( 19 | // 20 | // 21 | // /* add it here, as a child of `/` */ 22 | // 23 | // /*no used*/ 24 | // 25 | // 26 | // 27 | 28 | // , document.getElementById('my-app')); 29 | 30 | 31 | import 'babel-polyfill'; 32 | import React from 'react'; 33 | import ReactDOM from 'react-dom'; 34 | import { Router} from 'react-router' 35 | import history from './history' 36 | import rootRoute from './router' 37 | import 'react-ui/fast-clicks' 38 | require('react-ui/resources/less/intro.less'); 39 | require('react-ui/resources/less/icons.less'); 40 | require('react-ui/resources/less/views.less'); 41 | require('react-ui/resources/less/pages.less'); 42 | require('react-ui/resources/less/statusbar.less'); 43 | require('react-ui/resources/less/toolbars.less'); 44 | require('react-ui/resources/less/toolbars-pages.less'); 45 | require('react-ui/resources/less/tabs.less'); 46 | require('react-ui/resources/less/badges.less'); 47 | require('./resources/less/app.less'); 48 | 49 | 50 | 51 | // require('react-ui/resources/less/react-ui.ios.less') 52 | 53 | require('react-ui/resources/less/react-ui.ios.colors.less') 54 | 55 | require('./resources/less/app.less') 56 | ReactDOM.render( 57 | , 58 | document.getElementById('app') 59 | ) 60 | -------------------------------------------------------------------------------- /copy.js: -------------------------------------------------------------------------------- 1 | var fs = require( 'fs' ); 2 | 3 | /* 4 | * 复制目录中的所有文件包括子目录 5 | * @param{ String } 需要复制的目录 6 | * @param{ String } 复制到指定的目录 7 | */ 8 | // var copy = function( src, dst ){ 9 | // // 读取目录中的所有文件/目录 10 | // fs.readdir( src, function( err, paths ){ 11 | // if( err ){ 12 | // throw err; 13 | // } 14 | // paths.forEach(function( path ){ 15 | // var _src = src + '/' + path, 16 | // _dst = dst + '/' + path, 17 | // readable, writable; 18 | // stat( _src, function( err, st ){ 19 | // if( err ){ 20 | // throw err; 21 | // } 22 | // // 判断是否为文件 23 | // if( st.isFile() ){ 24 | // // 创建读取流 25 | // readable = fs.createReadStream( _src ); 26 | // // 创建写入流 27 | // writable = fs.createWriteStream( _dst ); 28 | // // 通过管道来传输流 29 | // readable.pipe( writable ); 30 | // } 31 | // // 如果是目录则递归调用自身 32 | // else if( st.isDirectory() ){ 33 | // exists( _src, _dst, copy ); 34 | // } 35 | // }); 36 | // }); 37 | // }); 38 | // }; 39 | // // 在复制目录前需要判断该目录是否存在,不存在需要先创建目录 40 | // var exists = function( src, dst, callback ){ 41 | // fs.exists( dst, function( exists ){ 42 | // // 已存在 43 | // if( exists ){ 44 | // callback( src, dst ); 45 | // } 46 | // // 不存在 47 | // else{ 48 | // fs.mkdir( dst, function(){ 49 | // callback( src, dst ); 50 | // }); 51 | // } 52 | // }); 53 | // }; 54 | 55 | var copy = function(src, dst){ 56 | if(Array.isArray(src)){ 57 | src.forEach(function(path){ 58 | copy(path, dst) 59 | }) 60 | return; 61 | } 62 | var st = fs.statSync(src) 63 | if(st.isFile()){ 64 | fs.createReadStream( src ).pipe(fs.createWriteStream( dst )); 65 | }else if(st.isDirectory()){ 66 | if(!fs.existsSync(dst)){ 67 | fs.mkdirSync(dst) 68 | } 69 | fs.readdirSync(src).forEach(function(path){ 70 | // console.log("path=", path) 71 | copy(src + '/' + path, dst + '/' + path) 72 | }) 73 | } 74 | 75 | } 76 | module.exports = copy -------------------------------------------------------------------------------- /src/draft-editor/tools/font-color.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import classnames from 'classnames' 3 | require('../../resources/less/grid.less') 4 | var prefix = 'color' 5 | var fontColorList = [ 6 | ['#E53333', '#E56600', '#FF9900', '#64451D'], 7 | ['#DFC5A4', '#FFE500', '#009900', '#006600'], 8 | ['#99BB00', '#B8D100', '#60D978', '#00D5FF'], 9 | ['#337FE5', '#003399', '#4C33E5', '#9933E5'], 10 | ['#CC33E5', '#EE33EE', '#FFFFFF', '#CCCCCC'], 11 | ['#999999', '#666666', '#333333', '#000000'] 12 | ]; 13 | 14 | var fontColorStyleMap = (function(){ 15 | var styleMap = {} 16 | fontColorList.forEach((list) => { 17 | list.forEach(color => { 18 | styleMap[prefix+color] = {color: color}; 19 | }) 20 | }) 21 | return styleMap; 22 | })() 23 | 24 | class FontColor extends React.Component{ 25 | constructor(props) { 26 | super(props); 27 | this.edit = props.edit 28 | this.state = { 29 | } 30 | } 31 | 32 | handleChangeFontColor(value , event){ 33 | 34 | this.setState({ 35 | value: value 36 | }) 37 | this.edit.toggleColor(prefix+value) 38 | // this.doc.execCommand('forecolor', false, value) 39 | } 40 | 41 | render(){ 42 | return ( 43 |
44 |
字体颜色
45 |
46 |
47 | { 48 | fontColorList.map((list, index) => { 49 | return ( 50 |
51 | { 52 | list.map((val) => ( 53 |
54 |
55 | 56 |
57 |
58 | )) 59 | } 60 |
61 | ) 62 | }) 63 | } 64 |
65 |
66 |
67 | ) 68 | } 69 | } 70 | 71 | export { 72 | fontColorStyleMap 73 | } 74 | export default FontColor 75 | -------------------------------------------------------------------------------- /src/umeditor/tools/back-color.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import classnames from 'classnames' 3 | require('../../resources/less/grid.less') 4 | var prefix = 'backColor' 5 | var backColorList = [ 6 | ['#E53333', '#E56600', '#FF9900', '#64451D'], 7 | ['#DFC5A4', '#FFE500', '#009900', '#006600'], 8 | ['#99BB00', '#B8D100', '#60D978', '#00D5FF'], 9 | ['#337FE5', '#003399', '#4C33E5', '#9933E5'], 10 | ['#CC33E5', '#EE33EE', '#FFFFFF', '#CCCCCC'], 11 | ['#999999', '#666666', '#333333', '#000000'] 12 | ]; 13 | 14 | var backColorStyleMap = (function(){ 15 | var styleMap = {} 16 | backColorList.forEach((list) => { 17 | list.forEach(color => { 18 | styleMap[prefix+color] = {backgroundColor: color}; 19 | }) 20 | }) 21 | return styleMap; 22 | })() 23 | 24 | class BackColor extends React.Component{ 25 | constructor(props) { 26 | super(props); 27 | this.edit = props.edit 28 | this.state = { 29 | } 30 | } 31 | 32 | 33 | componentDidMount(){ 34 | } 35 | 36 | 37 | 38 | handleChangeBackColor(value){ 39 | 40 | this.setState({ 41 | value: value 42 | }) 43 | this.edit.toggleBackColor(prefix+value) 44 | // this.doc.execCommand('forecolor', false, value) 45 | } 46 | 47 | render(){ 48 | return ( 49 |
50 |
突出显示
51 |
52 |
53 | { 54 | backColorList.map((list, index) => { 55 | return ( 56 |
57 | { 58 | list.map((val) => ( 59 |
60 |
61 | 62 |
63 |
64 | )) 65 | } 66 |
67 | ) 68 | }) 69 | } 70 |
71 |
72 |
73 | ) 74 | } 75 | } 76 | 77 | export { 78 | backColorStyleMap 79 | } 80 | export default BackColor 81 | -------------------------------------------------------------------------------- /src/umeditor/plugins/horizontal.js: -------------------------------------------------------------------------------- 1 | ///import core 2 | ///import plugins\inserthtml.js 3 | ///commands 分割线 4 | ///commandsName Horizontal 5 | ///commandsTitle 分隔线 6 | /** 7 | * 分割线 8 | * @function 9 | * @name Plugins.execCommand 10 | * @param {String} cmdName horizontal插入分割线 11 | */ 12 | /* eslint quotes : "off"*/ 13 | import Plugins from './plugins' 14 | import $ from '../../dom' 15 | import browser from '../core/browser' 16 | import domUtils from '../core/domUtils' 17 | import dtd from '../core/dtd' 18 | Plugins.plugins['horizontal'] = function(){ 19 | var me = this; 20 | me.commands['horizontal'] = { 21 | execCommand : function( ) { 22 | this.document.execCommand('insertHorizontalRule'); 23 | var rng = me.selection.getRange().txtToElmBoundary(true), 24 | start = rng.startContainer; 25 | if(domUtils.isBody(rng.startContainer)){ 26 | var next = rng.startContainer.childNodes[rng.startOffset]; 27 | if(!next){ 28 | next = $('

').appendTo(rng.startContainer).html(browser.ie ? ' ' : '
')[0] 29 | } 30 | rng.setStart(next,0).setCursor() 31 | }else{ 32 | 33 | while(dtd.$inline[start.tagName] && start.lastChild === start.firstChild){ 34 | 35 | var parent = start.parentNode; 36 | parent.appendChild(start.firstChild); 37 | parent.removeChild(start); 38 | start = parent; 39 | } 40 | while(dtd.$inline[start.tagName]){ 41 | start = start.parentNode; 42 | } 43 | if(start.childNodes.length == 1 && start.lastChild.nodeName == 'HR'){ 44 | var hr = start.lastChild; 45 | $(hr).insertBefore(start); 46 | rng.setStart(start,0).setCursor(); 47 | }else{ 48 | hr = $('hr',start)[0]; 49 | domUtils.breakParent(hr,start); 50 | var pre = hr.previousSibling; 51 | if(pre && domUtils.isEmptyBlock(pre)){ 52 | $(pre).remove() 53 | } 54 | rng.setStart(hr.nextSibling,0).setCursor(); 55 | } 56 | 57 | } 58 | } 59 | }; 60 | 61 | }; 62 | 63 | -------------------------------------------------------------------------------- /src/draft-editor/tools/back-color.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import classnames from 'classnames' 3 | require('../../resources/less/grid.less') 4 | var prefix = 'backColor' 5 | var backColorList = [ 6 | ['#E53333', '#E56600', '#FF9900', '#64451D'], 7 | ['#DFC5A4', '#FFE500', '#009900', '#006600'], 8 | ['#99BB00', '#B8D100', '#60D978', '#00D5FF'], 9 | ['#337FE5', '#003399', '#4C33E5', '#9933E5'], 10 | ['#CC33E5', '#EE33EE', '#FFFFFF', '#CCCCCC'], 11 | ['#999999', '#666666', '#333333', '#000000'] 12 | ]; 13 | 14 | var backColorStyleMap = (function(){ 15 | var styleMap = {} 16 | backColorList.forEach((list) => { 17 | list.forEach(color => { 18 | styleMap[prefix+color] = {backgroundColor: color}; 19 | }) 20 | }) 21 | return styleMap; 22 | })() 23 | 24 | class BackColor extends React.Component{ 25 | constructor(props) { 26 | super(props); 27 | this.edit = props.edit 28 | this.state = { 29 | } 30 | } 31 | 32 | 33 | componentDidMount(){ 34 | } 35 | 36 | 37 | 38 | handleChangeBackColor(value){ 39 | 40 | this.setState({ 41 | value: value 42 | }) 43 | this.edit.toggleBackColor(prefix+value) 44 | // this.doc.execCommand('forecolor', false, value) 45 | } 46 | 47 | render(){ 48 | return ( 49 |
50 |
突出显示
51 |
52 |
53 | { 54 | backColorList.map((list, index) => { 55 | return ( 56 |
57 | { 58 | list.map((val) => ( 59 |
60 |
61 | 62 |
63 |
64 | )) 65 | } 66 |
67 | ) 68 | }) 69 | } 70 |
71 |
72 |
73 | ) 74 | } 75 | } 76 | 77 | export { 78 | backColorStyleMap 79 | } 80 | export default BackColor 81 | -------------------------------------------------------------------------------- /src/editor/tools/font-family.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import classnames from 'classnames' 3 | import List from '../../lists' 4 | require('../../resources/less/forms.less') 5 | 6 | var fontFamilyList = [ 7 | { name: '宋体', value: '宋体,SimSun'}, 8 | { name: '微软雅黑', value: '微软雅黑,Microsoft YaHei'}, 9 | { name: '楷体', value: '楷体,楷体_GB2312, SimKai'}, 10 | { name: '黑体', value: '黑体, SimHei'}, 11 | { name: '隶书', value: '隶书, SimLi'}, 12 | { name: 'andale mono', value: 'andale mono'}, 13 | { name: 'arial', value: 'arial, helvetica,sans-serif'}, 14 | { name: 'arial black', value: 'arial black,avant garde'}, 15 | { name: 'comic sans ms', value: 'comic sans ms'}, 16 | { name: 'impact', value: 'impact,chicago'}, 17 | { name: 'timesNewRoman', value: 'times new roman'}, 18 | { name: 'sans-serif',value:'sans-serif'} 19 | ] 20 | 21 | class FontFamily extends React.Component{ 22 | constructor(props) { 23 | super(props); 24 | this.doc = document 25 | this.state = {} 26 | } 27 | 28 | 29 | componentDidMount(){ 30 | } 31 | 32 | 33 | 34 | handleChangeFontFamily(val){ 35 | this.setState({ 36 | value: val 37 | }) 38 | this.doc.execCommand('fontName', false, val) 39 | } 40 | 41 | render(){ 42 | return ( 43 |
44 |
字体
45 |
46 |
47 | 48 | { 49 | fontFamilyList.map((item) => ( 50 | 56 | )) 57 | } 58 | 59 |
60 |
61 |
62 | ) 63 | } 64 | } 65 | 66 | 67 | module.exports = FontFamily 68 | -------------------------------------------------------------------------------- /examples/webpack.base.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const HtmlWebpackPlugin = require('html-webpack-plugin'); 3 | const CleanWebpackPlugin = require('clean-webpack-plugin'); 4 | const ManifestPlugin = require('webpack-manifest-plugin'); 5 | const webpack = require('webpack'); 6 | 7 | const defaultConfig = require('./webpack.default') 8 | 9 | module.exports = { 10 | entry: { 11 | app: path.join(defaultConfig.srcDir, 'index.js') 12 | 13 | 14 | }, 15 | 16 | module: { 17 | rules: [{ 18 | test: /\.css$/, 19 | use: [ 20 | 'style-loader', 21 | 'css-loader' 22 | ] 23 | },{ 24 | test: /\.less$/, 25 | use: [ 26 | 'style-loader', 27 | 'css-loader', 28 | 'less-loader' 29 | ] 30 | }, { 31 | test: /\.(png|svg|jpg|jpeg|gif)$/, 32 | use: [ 33 | 'file-loader' 34 | ] 35 | }, { 36 | test: /\.(woff|woff2|eot|ttf|otf)$/, 37 | use: [ 38 | 'file-loader' 39 | ] 40 | }, { 41 | test: /\.(js|jsx)$/, 42 | use: [ 43 | 44 | 'babel-loader' 45 | 46 | ], 47 | include: [ 48 | defaultConfig.srcDir, 49 | '/Users/wangzhengquan/WK/web/f7-react-ui/src' 50 | ] 51 | 52 | }] 53 | }, 54 | 55 | resolve: { 56 | alias: { 57 | //'react-ui': '/Users/wangzhengquan/WK/web/f7-react-ui/src', 58 | 'react-ui' : 'f7-react-ui', 59 | styles: `${defaultConfig.srcDir}/styles/`, 60 | images: `${defaultConfig.srcDir}/images/` 61 | } 62 | }, 63 | 64 | plugins: [ 65 | new CleanWebpackPlugin([defaultConfig.distDir]), 66 | /** 67 | * https://github.com/jantimon/html-webpack-plugin 68 | * @type {String} 69 | */ 70 | new HtmlWebpackPlugin({ 71 | title: '一起嗨', 72 | template: path.join(defaultConfig.srcDir, 'index.html') 73 | }), 74 | 75 | 76 | new webpack.optimize.CommonsChunkPlugin({ 77 | name: 'runtime' // Specify the common bundle's name. 78 | }), 79 | 80 | /** 81 | * generate manifest.json 82 | */ 83 | new ManifestPlugin() 84 | ] 85 | }; -------------------------------------------------------------------------------- /src/message-box.js: -------------------------------------------------------------------------------- 1 | import Modals from './modals' 2 | import $ from 'react-ui/dom' 3 | var MessageBox = { 4 | params: { 5 | buttonsText: { 6 | ok: '确定', 7 | yes: '是', 8 | no: '否', 9 | cancel: '取消' 10 | } 11 | }, 12 | alert (text, title, callbackOk) { 13 | if (typeof title === 'function') { 14 | callbackOk = arguments[1]; 15 | title = undefined; 16 | } 17 | return Modals.modal({ 18 | text: text || '', 19 | title: typeof title === 'undefined' ? '' : title, 20 | buttons: [ {text: this.params.buttonsText.ok, bold: true, onClick: callbackOk} ] 21 | }); 22 | }, 23 | 24 | confirm (text, title, callbackOk, callbackCancel) { 25 | if (typeof title === 'function') { 26 | callbackCancel = arguments[2]; 27 | callbackOk = arguments[1]; 28 | title = undefined; 29 | } 30 | return Modals.modal({ 31 | text: text || '', 32 | title: typeof title === 'undefined' ? '' : title, 33 | buttons: [ 34 | {text: this.params.buttonsText.cancel, onClick: callbackCancel}, 35 | {text: this.params.buttonsText.ok, bold: true, onClick: callbackOk} 36 | ] 37 | }); 38 | }, 39 | 40 | prompt (text, title, callbackOk, callbackCancel) { 41 | if (typeof title === 'function') { 42 | callbackCancel = arguments[2]; 43 | callbackOk = arguments[1]; 44 | title = undefined; 45 | } 46 | return Modals.modal({ 47 | text: text || '', 48 | title: typeof title === 'undefined' ? '' : title, 49 | afterText: '
', 50 | buttons: [ 51 | { 52 | text: this.params.buttonsText.cancel 53 | }, 54 | { 55 | text: this.params.buttonsText.ok, 56 | bold: true 57 | } 58 | ], 59 | onClick: function (modal, index) { 60 | if (index === 0 && callbackCancel) callbackCancel($(modal).find('.modal-text-input').val()); 61 | if (index === 1 && callbackOk) callbackOk($(modal).find('.modal-text-input').val()); 62 | } 63 | }); 64 | } 65 | } 66 | 67 | Object.assign(Modals, { 68 | alert: MessageBox.alert.bind(MessageBox), 69 | confirm: MessageBox.confirm.bind(MessageBox), 70 | prompt: MessageBox.prompt.bind(MessageBox) 71 | }) 72 | console.log('modals modals==',Modals) 73 | module.exports = MessageBox; -------------------------------------------------------------------------------- /src/umeditor/plugins/image.js: -------------------------------------------------------------------------------- 1 | ///import core 2 | ///import plugins\inserthtml.js 3 | ///commands 插入图片,操作图片的对齐方式 4 | ///commandsName InsertImage,ImageNone,ImageLeft,ImageRight,ImageCenter 5 | ///commandsTitle 图片,默认,居左,居右,居中 6 | ///commandsDialog dialogs\image 7 | /** 8 | * Created by . 9 | * User: zhanyi 10 | * for image 11 | */ 12 | /* eslint quotes : "off"*/ 13 | import UM from '../um' 14 | // import $ from '../../dom' 15 | // import browser from '../core/browser' 16 | import utils from '../core/utils' 17 | UM.commands['insertimage'] = { 18 | execCommand:function (cmd, opt) { 19 | opt = utils.isArray(opt) ? opt : [opt]; 20 | if (!opt.length) { 21 | return; 22 | } 23 | var me = this; 24 | var html = [], str = '', ci; 25 | ci = opt[0]; 26 | if (opt.length == 1) { 27 | str = '
' + ci.alt + '
'; 36 | 37 | html.push(str); 38 | 39 | } else { 40 | for (var i = 0; ci = opt[i++];) { 41 | str = '

'; 47 | html.push(str); 48 | } 49 | } 50 | 51 | me.execCommand('insertHtml', html.join(''), true); 52 | } 53 | }; -------------------------------------------------------------------------------- /src/umeditor/tools/headline.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import List from '../../lists' 3 | require('../../resources/less/forms.less') 4 | 5 | const headLineList = [ 6 | {label: 'AaBb(正文)', value: 'p'}, 7 | {label: 'AaBb(标题一)', value: 'h1'}, 8 | {label: 'AaBb(标题二)', value: 'h2'}, 9 | {label: 'AaBb(标题三)', value: 'h3'}, 10 | {label: 'AaBb(标题四)', value: 'h4'} 11 | 12 | ] 13 | class HeadLine extends React.Component { 14 | constructor(props) { 15 | super(props); 16 | this.edit = props.edit 17 | this.state = { 18 | value: props.value 19 | } 20 | } 21 | 22 | 23 | handleChange(val){ 24 | this.setState({ 25 | value: val 26 | }) 27 | this.edit.execCommand('paragraph', val) 28 | // $('.public-DraftEditor-content[contenteditable=true]')[0].blur() 29 | } 30 | 31 | render() { 32 | 33 | return ( 34 |
35 |
样式
36 |
37 |
38 | 39 | { 40 | headLineList.map((item) => ( 41 | 61 | )) 62 | } 63 | 64 |
65 |
66 |
67 | ) 68 | } 69 | } 70 | 71 | export default HeadLine; -------------------------------------------------------------------------------- /src/url.js: -------------------------------------------------------------------------------- 1 | var URLUtil = {} 2 | URLUtil.parseUrlQuery = function(url) { 3 | var query = {}, 4 | i, params, param; 5 | 6 | url = url || window.location.toString() 7 | 8 | if (url.indexOf('?') >= 0) url = url.split('?')[1] 9 | else return query 10 | 11 | if (url.indexOf('#') >= 0) url = url.split('#')[0]; 12 | 13 | params = url.split('&'); 14 | for (i = 0; i < params.length; i++) { 15 | param = params[i].split('='); 16 | query[param[0]] = param[1]; 17 | } 18 | return query; 19 | }; 20 | 21 | URLUtil.serializeObject = URLUtil.param = function(obj, parents) { 22 | if (typeof obj === 'string') return obj; 23 | var resultArray = []; 24 | var separator = '&'; 25 | parents = parents || []; 26 | var newParents; 27 | 28 | function var_name(name) { 29 | if (parents.length > 0) { 30 | var _parents = ''; 31 | for (var j = 0; j < parents.length; j++) { 32 | if (j === 0) _parents += parents[j]; 33 | else _parents += '[' + encodeURIComponent(parents[j]) + ']'; 34 | } 35 | return _parents + '[' + encodeURIComponent(name) + ']'; 36 | } else { 37 | return encodeURIComponent(name); 38 | } 39 | } 40 | 41 | function var_value(value) { 42 | return encodeURIComponent(value); 43 | } 44 | for (var prop in obj) { 45 | if (obj.hasOwnProperty(prop)) { 46 | var toPush; 47 | if (Array.isArray(obj[prop])) { 48 | toPush = []; 49 | for (var i = 0; i < obj[prop].length; i++) { 50 | if (!Array.isArray(obj[prop][i]) && typeof obj[prop][i] === 'object') { 51 | newParents = parents.slice(); 52 | newParents.push(prop); 53 | newParents.push(i + ''); 54 | toPush.push(URLUtil.serializeObject(obj[prop][i], newParents)); 55 | } else { 56 | toPush.push(var_name(prop) + '[]=' + var_value(obj[prop][i])); 57 | } 58 | 59 | } 60 | if (toPush.length > 0) resultArray.push(toPush.join(separator)); 61 | } else if (typeof obj[prop] === 'object') { 62 | // Object, convert to named array 63 | newParents = parents.slice(); 64 | newParents.push(prop); 65 | toPush = URLUtil.serializeObject(obj[prop], newParents); 66 | if (toPush !== '') resultArray.push(toPush); 67 | } else /*if (typeof obj[prop] !== 'undefined' && obj[prop] !== '')*/ { 68 | // Should be string or plain value 69 | resultArray.push(var_name(prop) + '=' + var_value(obj[prop])); 70 | } 71 | } 72 | } 73 | return resultArray.join(separator); 74 | }; 75 | 76 | export default URLUtil; -------------------------------------------------------------------------------- /src/resources/less/panels.less: -------------------------------------------------------------------------------- 1 | @import url('_mixins.less'); 2 | @import url('_colors-vars.less'); 3 | /* === Panels === */ 4 | @panelWidth:260px; 5 | @panelsDuration: 400ms; 6 | .panel-overlay { 7 | position: absolute; 8 | left: 0; 9 | top: 0; 10 | width: 100%; 11 | height: 100%; 12 | background: rgba(0,0,0,0); 13 | opacity: 0; 14 | z-index: 5999; 15 | display: none; 16 | } 17 | .panel { 18 | z-index: 1000; 19 | display: none; 20 | background: #111; 21 | box-sizing: border-box; 22 | .scrollable(); 23 | position: absolute; 24 | width: @panelWidth; 25 | top: 0; 26 | height: 100%; 27 | .translate3d(0); 28 | .transition(@panelsDuration); 29 | 30 | &.panel-left { 31 | &.panel-cover { 32 | z-index: 6000; 33 | left: -@panelWidth; 34 | } 35 | &.panel-reveal { 36 | left: 0; 37 | } 38 | } 39 | &.panel-right { 40 | &.panel-cover { 41 | z-index: 6000; 42 | right: -@panelWidth; 43 | } 44 | &.panel-reveal { 45 | right: 0; 46 | } 47 | } 48 | } 49 | body.with-panel-left-cover, body.with-panel-right-cover { 50 | .views { 51 | .translate3d(0); 52 | } 53 | .panel-overlay { 54 | display: block; 55 | } 56 | } 57 | body.with-panel-left-reveal, body.with-panel-right-reveal { 58 | .views { 59 | .transition(@panelsDuration); 60 | -webkit-transition-property: -webkit-transform; 61 | -moz-transition-property: -moz-transform; 62 | transition-property: transform; 63 | } 64 | .panel-overlay { 65 | display: block; 66 | } 67 | } 68 | body.with-panel-left-reveal { 69 | .views { 70 | .translate3d(@panelWidth); 71 | } 72 | .panel-overlay { 73 | margin-left: @panelWidth; 74 | } 75 | } 76 | body.with-panel-left-cover { 77 | .panel-left { 78 | .translate3d(@panelWidth); 79 | } 80 | } 81 | body.with-panel-right-reveal { 82 | .views { 83 | .translate3d(-@panelWidth); 84 | } 85 | .panel-overlay { 86 | margin-left: -@panelWidth; 87 | } 88 | } 89 | body.with-panel-right-cover { 90 | .panel-right { 91 | .translate3d(-@panelWidth); 92 | } 93 | } 94 | body.panel-closing { 95 | .views { 96 | .transition(@panelsDuration); 97 | -webkit-transition-property: -webkit-transform; 98 | -moz-transition-property: -moz-transform; 99 | transition-property: transform; 100 | } 101 | } -------------------------------------------------------------------------------- /src/editor/tools/justify.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import classnames from 'classnames' 3 | import $ from '../../dom' 4 | import SupportEvents from '../../support-events' 5 | 6 | 7 | var justifyList = ['justifyLeft', 'justifyCenter', 'justifyRight', 'justifyFull']; 8 | var justifyIcons = { 9 | justifyLeft: 'icon-justify-left', 10 | justifyCenter: 'icon-justify-center', 11 | justifyRight: 'icon-justify-right', 12 | justifyFull: 'icon-justify-full' 13 | } 14 | 15 | class Justify extends React.Component{ 16 | constructor(props) { 17 | super(props); 18 | this.doc = document 19 | this.state = { 20 | commandState: {} 21 | } 22 | this.destroyList = [] 23 | } 24 | 25 | updateCommandState(){ 26 | var commandState = this.state.commandState; 27 | justifyList.forEach(val => { 28 | commandState[val] = this.doc.queryCommandState(val) 29 | }) 30 | this.setState({ 31 | commandState: commandState 32 | }) 33 | } 34 | 35 | componentDidMount(){ 36 | 37 | var fn = () => { 38 | // console.log('bold', this.doc.queryCommandState('bold'), typeof this.doc.queryCommandState('bold')) 39 | this.updateCommandState() 40 | } 41 | 42 | $(this.doc).on(SupportEvents.touchEvents.end, fn) 43 | 44 | this.destroyList.push(()=> { 45 | $(this.doc).off(SupportEvents.touchEvents.end, fn) 46 | }) 47 | } 48 | 49 | componentWillUnmount(){ 50 | this.destroy() 51 | } 52 | 53 | destroy(){ 54 | this.destroyList.forEach((fun) => { 55 | fun() 56 | }) 57 | } 58 | 59 | handleChangeJustify(value){ 60 | // var commandState = this.state.commandState 61 | // commandState[value] = this.doc.queryCommandState(value) 62 | // this.setState(commandState) 63 | 64 | this.doc.execCommand(value) 65 | this.updateCommandState() 66 | } 67 | 68 | render(){ 69 | console.log(this.state) 70 | console.log(this.state.commandState['justifyCenter']) 71 | return ( 72 |
73 |
对齐
74 |
75 | { 76 | justifyList.map(value => ( 77 |
78 | 79 | 80 |
81 | )) 82 | } 83 |
84 |
85 | ) 86 | } 87 | } 88 | 89 | 90 | module.exports = Justify 91 | -------------------------------------------------------------------------------- /src/number.js: -------------------------------------------------------------------------------- 1 | 2 | export default { 3 | /** 4 | * 转换为有符号数字串 5 | * 将 10 转换成 '+10', 6 | * 将 -10 转换成 '-10'. 7 | * @method toSignedNumberString 8 | * @param zeroPrefix {String} : 0之前的字符,一般用 +号,默认为空字符串。 9 | * @return {String} 10 | */ 11 | toSignedNumberString: function(num, zeroPrefix) { 12 | if (num > 0) { 13 | return '+' + String(num); 14 | } else if (num == 0) { 15 | return (zeroPrefix || '') + String(num); 16 | } else { 17 | return String(num); 18 | } 19 | }, 20 | 21 | /** 22 | * Return the hexidecimal string representation of an integer 23 | * @method toHex 24 | * @return {String} 25 | */ 26 | toHex: function(num) { 27 | return num.toString(16); 28 | }, 29 | 30 | /** 31 | * 将数字转换成金额大写格式. 32 | * @static 33 | * @method toAmountWords 34 | * @param {Number} 35 | * @return {String} 36 | */ 37 | toAmountWords: function(amount) { 38 | var dw2 = ["", "万", "亿"]; //大单位 39 | var dw1 = ["拾", "佰", "仟"]; //小单位 40 | var dw = ["零", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖"]; //整数部分用 41 | 42 | var amountSource = String(amount).split('.'); 43 | 44 | //转换整数部分 45 | var k1 = 0; //计小单位 46 | var k2 = 0; //计大单位 47 | var sum = 0; 48 | var str = ""; 49 | var n = 0; 50 | 51 | for (var i = 1, len = amountSource[0].length; i <= len; i++) { 52 | n = amountSource[0].charAt(len - i); //取得个位数上的数字 53 | var bn = 0; 54 | if (len - i - 1 >= 0) { 55 | bn = amountSource[0].charAt(len - i - 1); //取得某个位数前一位上的数字 56 | } 57 | sum = sum + Number(n); 58 | if (sum != 0) { 59 | str = dw[Number(n)].concat(str); //取得该数字对应的大写数字,并插入到str字符串的前面 60 | if (n == '0') sum = 0; 61 | } 62 | if (len - i - 1 >= 0) { //在数字范围内 63 | if (k1 != 3) { //加小单位 64 | if (bn != 0) { 65 | str = dw1[k1].concat(str); 66 | } 67 | k1++; 68 | } else { //不加小单位,加大单位 69 | k1 = 0; 70 | if (str.charAt(0) == "万" || str.charAt(0) == "亿") //若大单位前没有数字则舍去大单位 71 | str = str.substr(1, str.length - 1); 72 | str = dw2[k2].concat(str); 73 | sum = 0; 74 | } 75 | } 76 | if (k1 == 3) { //小单位到千则大单位进一 77 | k2++; 78 | } 79 | } 80 | str += "元"; 81 | 82 | //转换小数部分 83 | if (amountSource[1]) { 84 | n = amountSource[1].charAt(0); 85 | if (n != 0) { 86 | str += dw[Number(n)] + "角"; 87 | } 88 | n = amountSource[1].charAt(1); 89 | if (n != 0) { 90 | str += dw[Number(n)] + "分"; 91 | } 92 | } else { 93 | str += '整'; 94 | } 95 | 96 | return str; 97 | } 98 | } 99 | --------------------------------------------------------------------------------