├── .gitignore ├── .jshintrc ├── .travis.yml ├── README.md ├── bower.json ├── dist └── react-kendo.js ├── lib ├── KendoTemplate.js ├── KendoWidgetMixin.js ├── index.js └── widgets │ ├── Grid.js │ └── index.js ├── package.json └── test.js /.gitignore: -------------------------------------------------------------------------------- 1 | *.sw* 2 | node_modules 3 | 4 | -------------------------------------------------------------------------------- /.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "indent": 2, 3 | "maxdepth": 6, 4 | "maxlen": 120, 5 | "esnext": true, 6 | "expr": true, 7 | "trailing": true, 8 | "node": true, 9 | "esnext": true, 10 | "globals": { 11 | "describe": true, 12 | "it": true, 13 | "before": true, 14 | "after": true 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - '4.2' 4 | 5 | sudo: false 6 | 7 | notifications: 8 | email: false 9 | 10 | before_script: 11 | - npm install react react-dom lodash 12 | 13 | deploy: 14 | provider: npm 15 | email: me@traviswebb.com 16 | api_key: 17 | secure: g8+dmH4cRtJCyHQbQteKTETRDfCUTZtD4o1QyyJNrpnj7CxqUKkgrnBCEOpFMnitXJ59WDv2/yCMhyLEFIdwhnYLFef2mILQwMRtuV0u5asPp5o6zjtdfl04ILPml5Fh4qb7JuUCGz7IT23NXlIjgOxqk+5c1ZGAF+duROTrU+0= 18 | on: 19 | tags: true 20 | repo: tjwebb/react-kendo 21 | all_branches: true 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # react-kendo 2 | 3 | [![npm version][npm-image]][npm-url] 4 | [![Build status][travis-image]][travis-url] 5 | [![Dependency Status][daviddm-image]][daviddm-url] 6 | 7 | React Component Library for Kendo UI Widgets. There exists a React Component 8 | named for every Kendo widget in the 9 | [kendo.ui](http://docs.telerik.com/kendo-ui/api/javascript/ui/ui) and [kendo.ui.mobile](http://docs.telerik.com/kendo-ui/api/javascript/mobile/application) namespaces. 10 | Tested on React 0.13 and KendoUI 2014.3.1411. 11 | 12 | ## Install 13 | 14 | ```sh 15 | $ npm install react-kendo --save 16 | ``` 17 | 18 | ```html 19 | 20 | 21 | 22 | ``` 23 | 24 | Please note: Kendo Professional Components require 25 | [a License](http://www.telerik.com/purchase/kendo-ui). 26 | 27 | ## Usage 28 | ```js 29 | var React = require('react'); 30 | var k = React.Kendo = require('react-kendo'); 31 | 32 | /** 33 | * Instead of, e.g. 34 | * $('#my-splitter').kendoSplitter(splitterOptions); 35 | */ 36 | var splitterOptions = { 37 | orientation: 'horizontal', 38 | panes: [ 39 | { collapsible: false, size: '300px' }, 40 | { resizable: true } 41 | ] 42 | }; 43 | var treeOptions = { /* ... */ }; 44 | var gridOptions = { /* ... */ }; 45 | 46 | var Workstation = React.createClass({ 47 | render: function () { 48 | return ( 49 | 50 | 51 | 52 | 53 | ); 54 | } 55 | }); 56 | ``` 57 | 58 | ## Properties 59 | 60 | ### `options` 61 | The main Kendo options object that is sent into the constructor. e.g. 62 | `$('#my-splitter').kendoSplitter(options);` 63 | 64 | ### `tag` 65 | The `tag` property specifies the html tag that the Kendo widget will be bound 66 | to. This is `div` by default, but can be set to 67 | [any tag supported by React](http://facebook.github.io/react/docs/tags-and-attributes.html#html-elements). 68 | 69 | ### `reactive` 70 | Version 0.13 and later support automatically re-initializing the Kendo Widget 71 | when the `options` property is updated. This is useful for re-loading Grids 72 | with new data, among other things. This is `false` by default. 73 | 74 | ### `debug` 75 | Set `debug=true` to log detailed information on the lifecycle events of your 76 | react-kendo component. 77 | 78 | ## Additional Components 79 | 80 | ### `React.Kendo.Template` 81 | 82 | A React Component that represents a [Kendo Template](http://docs.telerik.com/kendo-ui/framework/templates/overview). 83 | Easily create a Kendo Template from a React Component. Additionally mixin 84 | `React.Kendo.TemplateMixin`. 85 | 86 | ```js 87 | var k = React.Kendo; 88 | var MyListItem = React.createClass({ 89 | mixins: [ 90 | k.TemplateMixin 91 | ], 92 | render: function () { 93 | var item = this.props.item; 94 | return ( 95 | {item.title} 96 | ); 97 | } 98 | }); 99 | var KendoList = React.createClass({ 100 | render: function () { 101 | return ( 102 | ); 105 | } 106 | } /> 107 | ); 108 | } 109 | }); 110 | ``` 111 | 112 | 113 | ## Supplemental Functions 114 | 115 | `react-kendo` also includes some extra functionality that isn't included in 116 | Kendo. These functions are added to the Kendo components via React mixins. 117 | 118 | 119 | ### `Grid.enableDraggableRows(group, options)` 120 | 121 | Invoke this function to make Grid rows draggable. This is not possible by 122 | default in the kendo-ui library. 123 | 124 | ```js 125 | var k = React.Kendo; 126 | var KendoList = React.createClass({ 127 | componentDidMount: function () { 128 | this.refs.grid.enableDraggableRows('myGroup', { 129 | drag: function (e) { 130 | // some custom stuff 131 | } 132 | }); 133 | }, 134 | render: function () { 135 | return ( 136 | 137 | ); 138 | } 139 | }); 140 | ``` 141 | 142 | ## License 143 | MIT 144 | 145 | ## Maintained By 146 | [](http://langa.io) 147 | 148 | [npm-image]: https://img.shields.io/npm/v/react-kendo.svg?style=flat-square 149 | [npm-url]: https://npmjs.org/package/react-kendo 150 | [travis-image]: https://img.shields.io/travis/tjwebb/react-kendo.svg?style=flat-square 151 | [travis-url]: https://travis-ci.org/tjwebb/react-kendo 152 | [daviddm-image]: http://img.shields.io/david/tjwebb/react-kendo.svg?style=flat-square 153 | [daviddm-url]: https://david-dm.org/tjwebb/react-kendo 154 | -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-kendo", 3 | "version": "0.13.1", 4 | "description": "React Component Library for Kendo UI Widgets. There exists a React Component named for every Kendo widget in the kendo.ui namespace. Tested on React 0.12 and KendoUI 2014.3.1411.", 5 | "homepage": "https://github.com/tjwebb/react-kendo", 6 | "main": "dist/react-kendo.js", 7 | "authors": [ 8 | "Travis Webb " 9 | ], 10 | "moduleType": [ 11 | "node" 12 | ], 13 | "keywords": [ 14 | "react", 15 | "kendo", 16 | "react.js", 17 | "react-component", 18 | "kendo-ui", 19 | "telerik", 20 | "components", 21 | "widgets" 22 | ], 23 | "license": "MIT", 24 | "ignore": [ 25 | "**/.*", 26 | "node_modules", 27 | "bower_components", 28 | "test", 29 | "tests" 30 | ] 31 | } 32 | -------------------------------------------------------------------------------- /dist/react-kendo.js: -------------------------------------------------------------------------------- 1 | (function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.ReactKendo = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o tr', 203 | group: group, 204 | cursorOffset: { 205 | top: 0, 206 | left: 0 207 | }, 208 | hint: function (e) { 209 | // XXX clean up 210 | return $('
' + e.html() + '
'); 211 | }, 212 | dragend: function (e) { 213 | if (e.sender.dropped) { 214 | this.enableDraggableRows(group, options); 215 | } 216 | }.bind(this) 217 | })); 218 | } 219 | }; 220 | 221 | module.exports = Grid; 222 | 223 | }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) 224 | },{}],5:[function(require,module,exports){ 225 | module.exports = { 226 | Grid: require('./Grid') 227 | }; 228 | 229 | },{"./Grid":4}]},{},[3])(3) 230 | }); -------------------------------------------------------------------------------- /lib/KendoTemplate.js: -------------------------------------------------------------------------------- 1 | var ReactDOMServer = require('react-dom/server'); 2 | 3 | var KendoTemplate = function (component) { 4 | return ReactDOMServer.renderToStaticMarkup(component); 5 | }; 6 | KendoTemplate.wrap = function (component) { 7 | return function (props) { 8 | return KendoTemplate(component(props)); 9 | }; 10 | }; 11 | 12 | module.exports = KendoTemplate; 13 | -------------------------------------------------------------------------------- /lib/KendoWidgetMixin.js: -------------------------------------------------------------------------------- 1 | /* global kendo */ 2 | 3 | var React = require('react'); 4 | var ReactDOM = require('react-dom'); 5 | var _ = require('lodash'); 6 | var reactTags = _.keys(React.DOM); 7 | 8 | function mountKendoWidget (component, widget) { 9 | component.$elem[widget](component.props.options); 10 | return component.$elem.data(widget); 11 | } 12 | 13 | /** 14 | * Use for all Kendo objects that inherit from kendo.ui.Widget 15 | * 16 | * @param widget e.g. 'kendoGrid' for Grid 17 | */ 18 | var KendoWidgetMixin = function (widget) { 19 | return { 20 | 21 | propTypes: { 22 | options: React.PropTypes.object, 23 | debug: React.PropTypes.bool, 24 | tag: React.PropTypes.oneOf(reactTags).isRequired 25 | }, 26 | 27 | getDefaultProps: function () { 28 | return { 29 | options: { }, 30 | debug: false, 31 | reactive: false, 32 | tag: 'div' 33 | }; 34 | }, 35 | 36 | componentWillMount: function () { 37 | if (this.props.debug) console.log('willMount kendo widget', widget, '...'); 38 | }, 39 | 40 | /** 41 | * Initialize Kendo component 42 | */ 43 | componentDidMount: function () { 44 | if (this.props.debug) console.log('kendo widget mounting... ', widget); 45 | 46 | this.elem = this.refs.elem; 47 | this.$elem = $(this.elem); 48 | this.$widget = mountKendoWidget(this, widget); 49 | 50 | if (this.props.debug) console.log('kendo widget mounted:', widget, ', widget=', this.$widget); 51 | if (this.props.debug) console.log('elem=', this.elem); 52 | if (this.props.debug) console.log('$elem=', this.$elem); 53 | }, 54 | 55 | componentWillUpdate: function () { 56 | if (this.props.debug) console.log('willUpdate kendo widget', widget, '...'); 57 | }, 58 | 59 | /** 60 | * Pass updated options into kendo widget 61 | */ 62 | componentDidUpdate: function () { 63 | if (this.props.debug) console.log('didUpdate kendo widget', widget); 64 | if (this.props.debug) console.log('new options:', this.props.options); 65 | 66 | if (!this.props.reactive) return; 67 | 68 | if (this.props.debug) console.log('[', widget, '] refreshing "reactive" widget...'); 69 | 70 | this.$widget.unbind(); 71 | if (this.$widget.element) { 72 | kendo.destroy(this.$widget); 73 | } 74 | if (this.$widget.dataSource) { 75 | this.$widget.dataSource.unbind('change', this.$widget._refreshHandler); 76 | this.$widget.dataSource.unbind('error', this.$widget._errorHandler); 77 | } 78 | 79 | this.$elem.empty(); 80 | this.$widget = mountKendoWidget(this, widget); 81 | }, 82 | 83 | /** 84 | * Destroy kendo widget 85 | */ 86 | componentWillUnmount: function () { 87 | if (this.props.debug) console.log('unmounting kendo widget', widget, '...'); 88 | 89 | this.$widget.unbind(); 90 | if (this.$widget.element) { 91 | kendo.destroy(this.$widget); 92 | } 93 | 94 | if (this.$widget.dataSource) { 95 | this.$widget.dataSource.unbind('change', this.$widget._refreshHandler); 96 | this.$widget.dataSource.unbind('error', this.$widget._errorHandler); 97 | } 98 | 99 | if (this.props.debug) console.log('kendo widget unmounted:', widget); 100 | }, 101 | 102 | /** 103 | * Accessor function for the Kendo Widget object. 104 | */ 105 | getWidget: function () { 106 | return this.$widget; 107 | }, 108 | 109 | getElement: function () { 110 | return this.$elem; 111 | }, 112 | 113 | /** 114 | * Default Kendo widget renderer 115 | */ 116 | render: function () { 117 | var other = _.omit(this.props, [ 'options', 'children', 'tag' ]); 118 | other.ref = "elem"; 119 | return React.DOM[this.props.tag](other, this.props.children); 120 | } 121 | }; 122 | }; 123 | 124 | module.exports = KendoWidgetMixin; 125 | -------------------------------------------------------------------------------- /lib/index.js: -------------------------------------------------------------------------------- 1 | var _ = require('lodash'); 2 | var React = require('react'); 3 | var KendoWidgetMixin = require('./KendoWidgetMixin'); 4 | var widgetMixins = require('./widgets'); 5 | var kendo = global.kendo || require('kendo'); 6 | 7 | if (!kendo || !kendo.ui) { 8 | throw new Error('kendo.ui not found'); 9 | } 10 | 11 | function kendoWidgetName(prefix, name) { 12 | return 'kendo' + prefix + name; 13 | } 14 | 15 | function buildComponent (widget, name, prefix) { 16 | var mixins = [ 17 | KendoWidgetMixin(kendoWidgetName(prefix, name)) 18 | ]; 19 | if (widgetMixins[name]) { 20 | mixins.push(widgetMixins[name]); 21 | } 22 | return React.createClass({ 23 | mixins: mixins 24 | }); 25 | } 26 | 27 | var KendoUi = _.mapValues(kendo.ui, function (widget, name) { 28 | return buildComponent(widget, name, ''); 29 | }); 30 | 31 | var KendoDataViz = _.mapValues(kendo.dataviz && kendo.dataviz.ui, function (widget, name) { 32 | return buildComponent(widget, name, ''); 33 | }); 34 | 35 | var KendoMobileUi = _.mapValues(kendo.mobile && kendo.mobile.ui, function (widget, name) { 36 | return buildComponent(widget, name, 'Mobile'); 37 | }); 38 | 39 | module.exports = _.extend({ 40 | Template: require('./KendoTemplate'), 41 | mobile: KendoMobileUi, 42 | dataviz: KendoDataViz 43 | }, 44 | KendoUi 45 | ); 46 | -------------------------------------------------------------------------------- /lib/widgets/Grid.js: -------------------------------------------------------------------------------- 1 | /* global kendo */ 2 | 3 | var React = require('react'); 4 | var _ = require('lodash'); 5 | 6 | var Grid = { 7 | /** 8 | * @param group draggable group 9 | * @param options 10 | */ 11 | enableDraggableRows: function (group, options) { 12 | this.getWidget().table.kendoDraggable(_.defaults(options || { }, { 13 | filter: 'tbody > tr', 14 | group: group, 15 | cursorOffset: { 16 | top: 0, 17 | left: 0 18 | }, 19 | hint: function (e) { 20 | // XXX clean up 21 | return $('
' + e.html() + '
'); 22 | }, 23 | dragend: function (e) { 24 | if (e.sender.dropped) { 25 | this.enableDraggableRows(group, options); 26 | } 27 | }.bind(this) 28 | })); 29 | } 30 | }; 31 | 32 | module.exports = Grid; 33 | -------------------------------------------------------------------------------- /lib/widgets/index.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | Grid: require('./Grid') 3 | }; 4 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-kendo", 3 | "version": "0.14.0", 4 | "description": "React Component Library for Kendo UI Widgets. There exists a React Component named for every Kendo widget in the kendo.ui namespace. Tested on React 0.12 and KendoUI 2014.3.1411.", 5 | "main": "lib/index.js", 6 | "scripts": { 7 | "dist": "browserify lib/index.js -o dist/react-kendo.js --standalone ReactKendo -t browserify-shim", 8 | "test": "mocha --reporter spec" 9 | }, 10 | "repository": { 11 | "type": "git", 12 | "url": "https://github.com/tjwebb/react-kendo.git" 13 | }, 14 | "keywords": [ 15 | "react", 16 | "kendo", 17 | "react.js", 18 | "react-component", 19 | "kendo-ui", 20 | "telerik", 21 | "components", 22 | "widgets" 23 | ], 24 | "author": "Travis Webb ", 25 | "license": "MIT", 26 | "bugs": { 27 | "url": "https://github.com/tjwebb/react-kendo/issues" 28 | }, 29 | "homepage": "https://github.com/tjwebb/react-kendo", 30 | "peerDependencies": { 31 | "react": ">=0.14.0", 32 | "react-dom": ">=0.14.0", 33 | "lodash": ">=3.0.0" 34 | }, 35 | "devDependencies": { 36 | "browserify": "^11.2.0", 37 | "browserify-shim": "^3.8.10", 38 | "jsdom": "^7.0.1", 39 | "mocha": "^2.3.3" 40 | }, 41 | "browserify-shim": { 42 | "react": "global:React", 43 | "react-dom/server": "global:React", 44 | "react-dom": "global:ReactDOM", 45 | "lodash": "global:_" 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /test.js: -------------------------------------------------------------------------------- 1 | var _ = require('lodash'); 2 | var assert = require('assert'); 3 | var jsdom = require('jsdom'); 4 | 5 | describe('react-kendo', function () { 6 | var env; 7 | 8 | describe('pre-requisites', function () { 9 | it('should check prerequisite existence of kendo.ui', function () { 10 | assert.throws(function () { 11 | require('./'); 12 | }, Error); 13 | }); 14 | }); 15 | 16 | describe('sanity', function () { 17 | 18 | before(function (done) { 19 | this.timeout(20000); 20 | env = jsdom.env({ 21 | html: '
', 22 | scripts: [ 23 | 'https://code.jquery.com/jquery-2.1.3.min.js', 24 | 'http://cdn.kendostatic.com/2014.3.1411/js/kendo.all.min.js' 25 | ], 26 | done: function (err, window) { 27 | global.kendo = window.kendo; 28 | done(err); 29 | } 30 | }); 31 | }); 32 | 33 | describe('kendo.ui', function () { 34 | it('should load widgets', function () { 35 | var k = require('./'); 36 | assert(_.isObject(k)); 37 | assert(k.Grid); 38 | assert(k.Splitter); 39 | assert(k.TreeView); 40 | }); 41 | }); 42 | 43 | describe('kendo.mobile.ui', function () { 44 | it('should load widgets', function () { 45 | var k = require('./'); 46 | assert(_.isObject(k.mobile)); 47 | assert(k.mobile.Widget); 48 | }); 49 | }); 50 | 51 | describe('kendo.dataviz.ui', function () { 52 | it('should load widgets', function () { 53 | var k = require('./'); 54 | assert(_.isObject(k.dataviz)); 55 | assert(k.dataviz.Chart); 56 | }); 57 | }); 58 | 59 | }); 60 | }); 61 | --------------------------------------------------------------------------------