├── .gitignore ├── README.md ├── TODO.md ├── build-docs.js ├── devtools ├── chrome │ ├── packed.zip │ └── unpacked │ │ ├── build │ │ ├── backend.js │ │ ├── background.js │ │ ├── contentScript.js │ │ ├── inject.js │ │ ├── main.js │ │ └── panel.js │ │ ├── icons │ │ ├── 128-deadcode.png │ │ ├── 128-development.png │ │ ├── 128-disabled.png │ │ ├── 128-outdated.png │ │ ├── 128-production.png │ │ ├── 128-unminified.png │ │ ├── 16-deadcode.png │ │ ├── 16-development.png │ │ ├── 16-disabled.png │ │ ├── 16-outdated.png │ │ ├── 16-production.png │ │ ├── 16-unminified.png │ │ ├── 32-deadcode.png │ │ ├── 32-development.png │ │ ├── 32-disabled.png │ │ ├── 32-outdated.png │ │ ├── 32-production.png │ │ ├── 32-unminified.png │ │ ├── 48-deadcode.png │ │ ├── 48-development.png │ │ ├── 48-disabled.png │ │ ├── 48-outdated.png │ │ ├── 48-production.png │ │ ├── 48-unminified.png │ │ ├── deadcode.svg │ │ ├── development.svg │ │ ├── disabled.svg │ │ ├── outdated.svg │ │ └── production.svg │ │ ├── main.html │ │ ├── manifest.json │ │ ├── panel.html │ │ └── popups │ │ ├── deadcode.html │ │ ├── development.html │ │ ├── disabled.html │ │ ├── outdated.html │ │ ├── production.html │ │ ├── shared.js │ │ └── unminified.html └── firefox │ ├── packed.zip │ └── unpacked │ ├── build │ ├── backend.js │ ├── background.js │ ├── contentScript.js │ ├── inject.js │ ├── main.js │ └── panel.js │ ├── icons │ ├── 128-deadcode.png │ ├── 128-development.png │ ├── 128-disabled.png │ ├── 128-outdated.png │ ├── 128-production.png │ ├── 128-unminified.png │ ├── 16-deadcode.png │ ├── 16-development.png │ ├── 16-disabled.png │ ├── 16-outdated.png │ ├── 16-production.png │ ├── 16-unminified.png │ ├── 32-deadcode.png │ ├── 32-development.png │ ├── 32-disabled.png │ ├── 32-outdated.png │ ├── 32-production.png │ ├── 32-unminified.png │ ├── 48-deadcode.png │ ├── 48-development.png │ ├── 48-disabled.png │ ├── 48-outdated.png │ ├── 48-production.png │ ├── 48-unminified.png │ ├── deadcode.svg │ ├── development.svg │ ├── disabled.svg │ ├── outdated.svg │ └── production.svg │ ├── main.html │ ├── manifest.json │ ├── panel.html │ └── popups │ ├── deadcode.html │ ├── development.html │ ├── disabled.html │ ├── outdated.html │ ├── production.html │ ├── shared.js │ └── unminified.html ├── dist ├── index.js └── index.js.map ├── docs ├── build.js ├── chapters │ ├── component.md │ ├── databinding.md │ ├── guides.md │ ├── link.md │ ├── record.md │ └── releasenotes.md ├── examples │ ├── babel-boilerplate │ │ ├── .babelrc │ │ ├── dist │ │ │ ├── app.js │ │ │ └── app.js.map │ │ ├── index.html │ │ ├── package-lock.json │ │ ├── package.json │ │ ├── src │ │ │ ├── index.jsx │ │ │ └── styles.css │ │ └── webpack.config.js │ ├── checklistTree │ │ ├── .babelrc │ │ ├── README.md │ │ ├── dist │ │ │ ├── app.js │ │ │ └── app.js.map │ │ ├── index.html │ │ ├── package-lock.json │ │ ├── package.json │ │ ├── screenshot.png │ │ ├── src │ │ │ ├── index.jsx │ │ │ ├── model.js │ │ │ └── styles.css │ │ └── webpack.config.js │ ├── flux-comparison │ │ ├── README.md │ │ ├── application.png │ │ ├── cart.png │ │ ├── index.html │ │ ├── js │ │ │ ├── app.js │ │ │ ├── components │ │ │ │ ├── App.jsx │ │ │ │ ├── CartContainer.jsx │ │ │ │ └── ProductsContainer.jsx │ │ │ └── models │ │ │ │ ├── Cart.js │ │ │ │ └── Product.js │ │ ├── product.png │ │ ├── sloc-comparison.png │ │ └── unidirectional-data-flow.jpg │ ├── todomvc │ │ ├── .babelrc │ │ ├── SLOC-comparison.jpg │ │ ├── css │ │ │ └── app.css │ │ ├── dist │ │ │ ├── app.js │ │ │ └── app.js.map │ │ ├── index.html │ │ ├── js │ │ │ ├── addtodo.jsx │ │ │ ├── filter.jsx │ │ │ ├── main.jsx │ │ │ ├── model.js │ │ │ └── todolist.jsx │ │ ├── package-lock.json │ │ ├── package.json │ │ ├── pure-components.jpg │ │ ├── readme.md │ │ └── webpack.config.js │ └── userslist │ │ ├── .babelrc │ │ ├── README.md │ │ ├── dist │ │ ├── app.js │ │ └── app.js.map │ │ ├── index.html │ │ ├── main.css │ │ ├── main.jsx │ │ ├── package-lock.json │ │ ├── package.json │ │ └── webpack.config.js ├── images │ ├── logo-dark.png │ ├── logo.png │ ├── navbar.png │ ├── overview.png │ └── volicon_verizon_dm.png ├── index.html ├── index.md └── lib │ ├── fonts │ ├── icomoon.eot │ ├── icomoon.svg │ ├── icomoon.ttf │ ├── icomoon.woff │ ├── slate.eot │ ├── slate.svg │ ├── slate.ttf │ ├── slate.woff │ └── slate.woff2 │ ├── javascripts │ ├── all.js │ ├── all2.js │ ├── all_nosearch.js │ ├── app │ │ ├── _lang.js │ │ ├── _search.js │ │ └── _toc.js │ └── lib │ │ ├── _energize.js │ │ ├── _imagesloaded.min.js │ │ ├── _jquery.highlight.js │ │ ├── _jquery.tocify.js │ │ ├── _jquery_ui.js │ │ └── _lunr.js │ ├── layouts │ └── layout.html │ └── stylesheets │ ├── default.css │ ├── icon-font.css │ ├── normalize.css │ ├── print.css │ ├── screen.css │ ├── syntax.css │ └── variables.css ├── examples ├── babel-boilerplate │ ├── .babelrc │ ├── dist │ │ ├── app.js │ │ └── app.js.map │ ├── index.html │ ├── package-lock.json │ ├── package.json │ ├── src │ │ ├── index.jsx │ │ └── styles.css │ └── webpack.config.js ├── checklistTree │ ├── .babelrc │ ├── README.md │ ├── dist │ │ ├── app.js │ │ └── app.js.map │ ├── index.html │ ├── package-lock.json │ ├── package.json │ ├── screenshot.png │ ├── src │ │ ├── index.jsx │ │ ├── model.js │ │ └── styles.css │ └── webpack.config.js ├── flux-comparison │ ├── README.md │ ├── application.png │ ├── cart.png │ ├── index.html │ ├── js │ │ ├── app.js │ │ ├── components │ │ │ ├── App.jsx │ │ │ ├── CartContainer.jsx │ │ │ └── ProductsContainer.jsx │ │ └── models │ │ │ ├── Cart.js │ │ │ └── Product.js │ ├── product.png │ ├── sloc-comparison.png │ └── unidirectional-data-flow.jpg ├── todomvc │ ├── .babelrc │ ├── SLOC-comparison.jpg │ ├── css │ │ └── app.css │ ├── dist │ │ ├── app.js │ │ └── app.js.map │ ├── index.html │ ├── js │ │ ├── addtodo.jsx │ │ ├── filter.jsx │ │ ├── main.jsx │ │ ├── model.js │ │ └── todolist.jsx │ ├── package-lock.json │ ├── package.json │ ├── pure-components.jpg │ ├── readme.md │ └── webpack.config.js └── userslist │ ├── .babelrc │ ├── README.md │ ├── dist │ ├── app.js │ └── app.js.map │ ├── index.html │ ├── main.css │ ├── main.jsx │ ├── package-lock.json │ ├── package.json │ └── webpack.config.js ├── lib ├── component.d.ts ├── component.js ├── component.js.map ├── define │ ├── common.d.ts │ ├── common.js │ ├── common.js.map │ ├── context.d.ts │ ├── context.js │ ├── context.js.map │ ├── index.d.ts │ ├── index.js │ ├── index.js.map │ ├── props.d.ts │ ├── props.js │ ├── props.js.map │ ├── pureRender.d.ts │ ├── pureRender.js │ ├── pureRender.js.map │ ├── state.d.ts │ ├── state.js │ ├── state.js.map │ ├── store.d.ts │ ├── store.js │ ├── store.js.map │ ├── typeSpecs.d.ts │ ├── typeSpecs.js │ └── typeSpecs.js.map ├── index.d.ts ├── index.js ├── index.js.map ├── link.d.ts ├── link.js └── link.js.map ├── package.json ├── rollup.config.js ├── src ├── component.ts ├── define │ ├── common.ts │ ├── context.ts │ ├── index.ts │ ├── props.ts │ ├── pureRender.ts │ ├── state.ts │ ├── store.ts │ └── typeSpecs.ts ├── index.ts └── link.ts ├── tags.js ├── tags.jsx ├── tsconfig.json └── yarn.lock /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .idea -------------------------------------------------------------------------------- /TODO.md: -------------------------------------------------------------------------------- 1 | # v3 Roadmap 2 | 3 | ## Major goals 4 | 5 | - Support new React lifecycle hooks 6 | - Support new version of Type-R 7 | 8 | ## Tasks 9 | 10 | - New, more efficient implementation of pure render. 11 | - Create tokens for Date and Transactional props only. 12 | - Update tokens in place. 13 | - Make sure shouldComponentUpdate remembers that some props were changed if called many times. 14 | - Add PureComponent class. 15 | - New implementation of watchers. 16 | - Should use the same approach as the new pure render. 17 | - Deep changes detection. 18 | - Use shouldComponentUpdate to invoke watchers 19 | - Make sure watcher will be called once no matter how many times shouldComponentUpdate is called. 20 | - Ad-hoc component.afterRender() lifecycle hook to be used from render and watchers. 21 | - Remove dependency from propTypes package. 22 | - Rename `state` to `model`. 23 | - (?) Delay asyncUpdate() between shouldComponentUpdate and componentDidUpdate. 24 | - (?) Check if update throttling works with inputs. 25 | - (?) Use setState() instead of forceUpdate(). 26 | - (?) Put both model and store into the standard component state. 27 | -------------------------------------------------------------------------------- /devtools/chrome/packed.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VoliJS/React-Type-R/8d157b9afd76850f680c677d62437e4516191b77/devtools/chrome/packed.zip -------------------------------------------------------------------------------- /devtools/chrome/unpacked/build/background.js: -------------------------------------------------------------------------------- 1 | !function(modules) { 2 | function __webpack_require__(moduleId) { 3 | if (installedModules[moduleId]) return installedModules[moduleId].exports; 4 | var module = installedModules[moduleId] = { 5 | exports: {}, 6 | id: moduleId, 7 | loaded: !1 8 | }; 9 | return modules[moduleId].call(module.exports, module, module.exports, __webpack_require__), 10 | module.loaded = !0, module.exports; 11 | } 12 | var installedModules = {}; 13 | return __webpack_require__.m = modules, __webpack_require__.c = installedModules, 14 | __webpack_require__.p = "", __webpack_require__(0); 15 | }([ function(module, exports) { 16 | "use strict"; 17 | function isNumeric(str) { 18 | return +str + "" === str; 19 | } 20 | function installContentScript(tabId) { 21 | chrome.tabs.executeScript(tabId, { 22 | file: "/build/contentScript.js" 23 | }, function() {}); 24 | } 25 | function doublePipe(one, two) { 26 | function lOne(message) { 27 | two.postMessage(message); 28 | } 29 | function lTwo(message) { 30 | one.postMessage(message); 31 | } 32 | function shutdown() { 33 | one.onMessage.removeListener(lOne), two.onMessage.removeListener(lTwo), one.disconnect(), 34 | two.disconnect(); 35 | } 36 | one.onMessage.addListener(lOne), two.onMessage.addListener(lTwo), one.onDisconnect.addListener(shutdown), 37 | two.onDisconnect.addListener(shutdown); 38 | } 39 | function setIconAndPopup(reactBuildType, tabId) { 40 | chrome.browserAction.setIcon({ 41 | tabId: tabId, 42 | path: { 43 | "16": "icons/16-" + reactBuildType + ".png", 44 | "32": "icons/32-" + reactBuildType + ".png", 45 | "48": "icons/48-" + reactBuildType + ".png", 46 | "128": "icons/128-" + reactBuildType + ".png" 47 | } 48 | }), chrome.browserAction.setPopup({ 49 | tabId: tabId, 50 | popup: "popups/" + reactBuildType + ".html" 51 | }); 52 | } 53 | var ports = {}, IS_FIREFOX = navigator.userAgent.indexOf("Firefox") >= 0; 54 | chrome.runtime.onConnect.addListener(function(port) { 55 | var tab = null, name = null; 56 | isNumeric(port.name) ? (tab = port.name, name = "devtools", installContentScript(+port.name)) : (tab = port.sender.tab.id, 57 | name = "content-script"), ports[tab] || (ports[tab] = { 58 | devtools: null, 59 | "content-script": null 60 | }), ports[tab][name] = port, ports[tab].devtools && ports[tab]["content-script"] && doublePipe(ports[tab].devtools, ports[tab]["content-script"]); 61 | }), IS_FIREFOX && chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) { 62 | tab.active && "loading" === changeInfo.status && setIconAndPopup("disabled", tabId); 63 | }), chrome.runtime.onMessage.addListener(function(req, sender) { 64 | if (req.hasDetectedReact && sender.tab) { 65 | var reactBuildType = req.reactBuildType; 66 | sender.url.indexOf("facebook.github.io/react") !== -1 && (reactBuildType = "production"), 67 | setIconAndPopup(reactBuildType, sender.tab.id); 68 | } 69 | }); 70 | } ]); -------------------------------------------------------------------------------- /devtools/chrome/unpacked/build/contentScript.js: -------------------------------------------------------------------------------- 1 | !function(modules) { 2 | function __webpack_require__(moduleId) { 3 | if (installedModules[moduleId]) return installedModules[moduleId].exports; 4 | var module = installedModules[moduleId] = { 5 | exports: {}, 6 | id: moduleId, 7 | loaded: !1 8 | }; 9 | return modules[moduleId].call(module.exports, module, module.exports, __webpack_require__), 10 | module.loaded = !0, module.exports; 11 | } 12 | var installedModules = {}; 13 | return __webpack_require__.m = modules, __webpack_require__.c = installedModules, 14 | __webpack_require__.p = "", __webpack_require__(0); 15 | }([ function(module, exports) { 16 | "use strict"; 17 | function handleMessageFromDevtools(message) { 18 | window.postMessage({ 19 | source: "react-devtools-content-script", 20 | payload: message 21 | }, "*"); 22 | } 23 | function handleMessageFromPage(evt) { 24 | evt.source === window && evt.data && "react-devtools-bridge" === evt.data.source && port.postMessage(evt.data.payload); 25 | } 26 | function handleDisconnect() { 27 | window.removeEventListener("message", handleMessageFromPage), window.postMessage({ 28 | source: "react-devtools-content-script", 29 | payload: { 30 | type: "event", 31 | evt: "shutdown" 32 | } 33 | }, "*"); 34 | } 35 | var port = chrome.runtime.connect({ 36 | name: "content-script" 37 | }); 38 | port.onMessage.addListener(handleMessageFromDevtools), port.onDisconnect.addListener(handleDisconnect), 39 | window.addEventListener("message", handleMessageFromPage), window.postMessage({ 40 | source: "react-devtools-content-script", 41 | hello: !0 42 | }, "*"); 43 | } ]); -------------------------------------------------------------------------------- /devtools/chrome/unpacked/build/main.js: -------------------------------------------------------------------------------- 1 | !function(modules) { 2 | function __webpack_require__(moduleId) { 3 | if (installedModules[moduleId]) return installedModules[moduleId].exports; 4 | var module = installedModules[moduleId] = { 5 | exports: {}, 6 | id: moduleId, 7 | loaded: !1 8 | }; 9 | return modules[moduleId].call(module.exports, module, module.exports, __webpack_require__), 10 | module.loaded = !0, module.exports; 11 | } 12 | var installedModules = {}; 13 | return __webpack_require__.m = modules, __webpack_require__.c = installedModules, 14 | __webpack_require__.p = "", __webpack_require__(0); 15 | }([ function(module, exports) { 16 | "use strict"; 17 | function createPanelIfReactLoaded() { 18 | panelCreated || chrome.devtools.inspectedWindow.eval("!!(\n Object.keys(window.__REACT_DEVTOOLS_GLOBAL_HOOK__._renderers).length || window.React\n )", function(pageHasReact, err) { 19 | pageHasReact && !panelCreated && (clearInterval(loadCheckInterval), panelCreated = !0, 20 | chrome.devtools.panels.create("React", "", "panel.html", function(panel) { 21 | var reactPanel = null; 22 | panel.onShown.addListener(function(window) { 23 | window.panel.getNewSelection(), reactPanel = window.panel, reactPanel.resumeTransfer(); 24 | }), panel.onHidden.addListener(function() { 25 | reactPanel && (reactPanel.hideHighlight(), reactPanel.pauseTransfer()); 26 | }); 27 | })); 28 | }); 29 | } 30 | var panelCreated = !1; 31 | chrome.devtools.network.onNavigated.addListener(function() { 32 | createPanelIfReactLoaded(); 33 | }); 34 | var loadCheckInterval = setInterval(function() { 35 | createPanelIfReactLoaded(); 36 | }, 1e3); 37 | createPanelIfReactLoaded(); 38 | } ]); -------------------------------------------------------------------------------- /devtools/chrome/unpacked/icons/128-deadcode.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VoliJS/React-Type-R/8d157b9afd76850f680c677d62437e4516191b77/devtools/chrome/unpacked/icons/128-deadcode.png -------------------------------------------------------------------------------- /devtools/chrome/unpacked/icons/128-development.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VoliJS/React-Type-R/8d157b9afd76850f680c677d62437e4516191b77/devtools/chrome/unpacked/icons/128-development.png -------------------------------------------------------------------------------- /devtools/chrome/unpacked/icons/128-disabled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VoliJS/React-Type-R/8d157b9afd76850f680c677d62437e4516191b77/devtools/chrome/unpacked/icons/128-disabled.png -------------------------------------------------------------------------------- /devtools/chrome/unpacked/icons/128-outdated.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VoliJS/React-Type-R/8d157b9afd76850f680c677d62437e4516191b77/devtools/chrome/unpacked/icons/128-outdated.png -------------------------------------------------------------------------------- /devtools/chrome/unpacked/icons/128-production.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VoliJS/React-Type-R/8d157b9afd76850f680c677d62437e4516191b77/devtools/chrome/unpacked/icons/128-production.png -------------------------------------------------------------------------------- /devtools/chrome/unpacked/icons/128-unminified.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VoliJS/React-Type-R/8d157b9afd76850f680c677d62437e4516191b77/devtools/chrome/unpacked/icons/128-unminified.png -------------------------------------------------------------------------------- /devtools/chrome/unpacked/icons/16-deadcode.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VoliJS/React-Type-R/8d157b9afd76850f680c677d62437e4516191b77/devtools/chrome/unpacked/icons/16-deadcode.png -------------------------------------------------------------------------------- /devtools/chrome/unpacked/icons/16-development.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VoliJS/React-Type-R/8d157b9afd76850f680c677d62437e4516191b77/devtools/chrome/unpacked/icons/16-development.png -------------------------------------------------------------------------------- /devtools/chrome/unpacked/icons/16-disabled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VoliJS/React-Type-R/8d157b9afd76850f680c677d62437e4516191b77/devtools/chrome/unpacked/icons/16-disabled.png -------------------------------------------------------------------------------- /devtools/chrome/unpacked/icons/16-outdated.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VoliJS/React-Type-R/8d157b9afd76850f680c677d62437e4516191b77/devtools/chrome/unpacked/icons/16-outdated.png -------------------------------------------------------------------------------- /devtools/chrome/unpacked/icons/16-production.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VoliJS/React-Type-R/8d157b9afd76850f680c677d62437e4516191b77/devtools/chrome/unpacked/icons/16-production.png -------------------------------------------------------------------------------- /devtools/chrome/unpacked/icons/16-unminified.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VoliJS/React-Type-R/8d157b9afd76850f680c677d62437e4516191b77/devtools/chrome/unpacked/icons/16-unminified.png -------------------------------------------------------------------------------- /devtools/chrome/unpacked/icons/32-deadcode.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VoliJS/React-Type-R/8d157b9afd76850f680c677d62437e4516191b77/devtools/chrome/unpacked/icons/32-deadcode.png -------------------------------------------------------------------------------- /devtools/chrome/unpacked/icons/32-development.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VoliJS/React-Type-R/8d157b9afd76850f680c677d62437e4516191b77/devtools/chrome/unpacked/icons/32-development.png -------------------------------------------------------------------------------- /devtools/chrome/unpacked/icons/32-disabled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VoliJS/React-Type-R/8d157b9afd76850f680c677d62437e4516191b77/devtools/chrome/unpacked/icons/32-disabled.png -------------------------------------------------------------------------------- /devtools/chrome/unpacked/icons/32-outdated.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VoliJS/React-Type-R/8d157b9afd76850f680c677d62437e4516191b77/devtools/chrome/unpacked/icons/32-outdated.png -------------------------------------------------------------------------------- /devtools/chrome/unpacked/icons/32-production.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VoliJS/React-Type-R/8d157b9afd76850f680c677d62437e4516191b77/devtools/chrome/unpacked/icons/32-production.png -------------------------------------------------------------------------------- /devtools/chrome/unpacked/icons/32-unminified.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VoliJS/React-Type-R/8d157b9afd76850f680c677d62437e4516191b77/devtools/chrome/unpacked/icons/32-unminified.png -------------------------------------------------------------------------------- /devtools/chrome/unpacked/icons/48-deadcode.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VoliJS/React-Type-R/8d157b9afd76850f680c677d62437e4516191b77/devtools/chrome/unpacked/icons/48-deadcode.png -------------------------------------------------------------------------------- /devtools/chrome/unpacked/icons/48-development.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VoliJS/React-Type-R/8d157b9afd76850f680c677d62437e4516191b77/devtools/chrome/unpacked/icons/48-development.png -------------------------------------------------------------------------------- /devtools/chrome/unpacked/icons/48-disabled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VoliJS/React-Type-R/8d157b9afd76850f680c677d62437e4516191b77/devtools/chrome/unpacked/icons/48-disabled.png -------------------------------------------------------------------------------- /devtools/chrome/unpacked/icons/48-outdated.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VoliJS/React-Type-R/8d157b9afd76850f680c677d62437e4516191b77/devtools/chrome/unpacked/icons/48-outdated.png -------------------------------------------------------------------------------- /devtools/chrome/unpacked/icons/48-production.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VoliJS/React-Type-R/8d157b9afd76850f680c677d62437e4516191b77/devtools/chrome/unpacked/icons/48-production.png -------------------------------------------------------------------------------- /devtools/chrome/unpacked/icons/48-unminified.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VoliJS/React-Type-R/8d157b9afd76850f680c677d62437e4516191b77/devtools/chrome/unpacked/icons/48-unminified.png -------------------------------------------------------------------------------- /devtools/chrome/unpacked/icons/deadcode.svg: -------------------------------------------------------------------------------- 1 | development780780 -------------------------------------------------------------------------------- /devtools/chrome/unpacked/icons/development.svg: -------------------------------------------------------------------------------- 1 | development780780 -------------------------------------------------------------------------------- /devtools/chrome/unpacked/icons/disabled.svg: -------------------------------------------------------------------------------- 1 | disabled -------------------------------------------------------------------------------- /devtools/chrome/unpacked/icons/outdated.svg: -------------------------------------------------------------------------------- 1 | outdated -------------------------------------------------------------------------------- /devtools/chrome/unpacked/icons/production.svg: -------------------------------------------------------------------------------- 1 | production -------------------------------------------------------------------------------- /devtools/chrome/unpacked/main.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /devtools/chrome/unpacked/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "manifest_version": 2, 3 | "name": "React Developer Tools", 4 | "description": "Adds React debugging tools to the Chrome Developer Tools.", 5 | "version": "2.5.2", 6 | 7 | "minimum_chrome_version": "49", 8 | 9 | "icons": { 10 | "16": "icons/16-production.png", 11 | "32": "icons/32-production.png", 12 | "48": "icons/48-production.png", 13 | "128": "icons/128-production.png" 14 | }, 15 | 16 | "browser_action": { 17 | "default_icon": { 18 | "16": "icons/16-disabled.png", 19 | "32": "icons/32-disabled.png", 20 | "48": "icons/48-disabled.png", 21 | "128": "icons/128-disabled.png" 22 | }, 23 | 24 | "default_popup": "popups/disabled.html" 25 | }, 26 | 27 | "devtools_page": "main.html", 28 | 29 | "content_security_policy": "script-src 'self' 'unsafe-eval'; object-src 'self'", 30 | "web_accessible_resources": [ "main.html", "panel.html", "build/backend.js"], 31 | 32 | "background": { 33 | "scripts": [ "build/background.js" ], 34 | "persistent": false 35 | }, 36 | 37 | "permissions": [ 38 | "file:///*", 39 | "http://*/*", 40 | "https://*/*" 41 | ], 42 | 43 | "content_scripts": [ 44 | { 45 | "matches": [""], 46 | "js": ["build/inject.js"], 47 | "run_at": "document_start" 48 | } 49 | ] 50 | } 51 | -------------------------------------------------------------------------------- /devtools/chrome/unpacked/panel.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 26 | 27 | 28 | 29 |
Unable to find React on the page.
30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /devtools/chrome/unpacked/popups/deadcode.html: -------------------------------------------------------------------------------- 1 | 2 | 17 |

18 | This page includes an extra development build of React. 🚧 19 |

20 |

21 | The React build on this page includes both development and production versions because dead code elimination has not been applied correctly. 22 |
23 |
24 | This makes its size larger, and causes React to run slower. 25 |
26 |
27 | Make sure to set up dead code elimination before deployment. 28 |

29 |
30 |

31 | Open the developer tools, and the React tab will appear to the right. 32 |

33 | -------------------------------------------------------------------------------- /devtools/chrome/unpacked/popups/development.html: -------------------------------------------------------------------------------- 1 | 2 | 17 |

18 | This page is using the development build of React. 🚧 19 |

20 |

21 | Note that the development build is not suitable for production. 22 |
23 | Make sure to use the production build before deployment. 24 |

25 |
26 |

27 | Open the developer tools, and the React tab will appear to the right. 28 |

29 | -------------------------------------------------------------------------------- /devtools/chrome/unpacked/popups/disabled.html: -------------------------------------------------------------------------------- 1 | 2 | 17 |

18 | This page doesn’t appear to be using React. 19 |
20 | If this seems wrong, follow the troubleshooting instructions. 21 |

22 | -------------------------------------------------------------------------------- /devtools/chrome/unpacked/popups/outdated.html: -------------------------------------------------------------------------------- 1 | 2 | 17 |

18 | This page is using an outdated version of React. ⌛ 19 |

20 |

21 | We recommend updating React to ensure that you receive important bugfixes and performance improvements. 22 |
23 |
24 | You can find the upgrade instructions on the React blog. 25 |

26 |
27 |

28 | Open the developer tools, and the React tab will appear to the right. 29 |

30 | -------------------------------------------------------------------------------- /devtools/chrome/unpacked/popups/production.html: -------------------------------------------------------------------------------- 1 | 2 | 17 |

18 | This page is using the production build of React. ✅ 19 |
20 | Open the developer tools, and the React tab will appear to the right. 21 |

22 | -------------------------------------------------------------------------------- /devtools/chrome/unpacked/popups/shared.js: -------------------------------------------------------------------------------- 1 | /* globals chrome */ 2 | 3 | document.addEventListener('DOMContentLoaded', function() { 4 | // Make links work 5 | var links = document.getElementsByTagName('a'); 6 | for (var i = 0; i < links.length; i++) { 7 | (function() { 8 | var ln = links[i]; 9 | var location = ln.href; 10 | ln.onclick = function() { 11 | chrome.tabs.create({active: true, url: location}); 12 | }; 13 | })(); 14 | } 15 | 16 | // Work around https://bugs.chromium.org/p/chromium/issues/detail?id=428044 17 | document.body.style.opacity = 0; 18 | document.body.style.transition = 'opacity ease-out .4s'; 19 | requestAnimationFrame(function() { 20 | document.body.style.opacity = 1; 21 | }); 22 | }); 23 | -------------------------------------------------------------------------------- /devtools/chrome/unpacked/popups/unminified.html: -------------------------------------------------------------------------------- 1 | 2 | 17 |

18 | This page is using an unminified build of React. 🚧 19 |

20 |

21 | The React build on this page appears to be unminified. 22 |
23 | This makes its size larger, and causes React to run slower. 24 |
25 |
26 | Make sure to set up minification before deployment. 27 |

28 |
29 |

30 | Open the developer tools, and the React tab will appear to the right. 31 |

32 | -------------------------------------------------------------------------------- /devtools/firefox/packed.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VoliJS/React-Type-R/8d157b9afd76850f680c677d62437e4516191b77/devtools/firefox/packed.zip -------------------------------------------------------------------------------- /devtools/firefox/unpacked/build/contentScript.js: -------------------------------------------------------------------------------- 1 | !function(modules) { 2 | function __webpack_require__(moduleId) { 3 | if (installedModules[moduleId]) return installedModules[moduleId].exports; 4 | var module = installedModules[moduleId] = { 5 | exports: {}, 6 | id: moduleId, 7 | loaded: !1 8 | }; 9 | return modules[moduleId].call(module.exports, module, module.exports, __webpack_require__), 10 | module.loaded = !0, module.exports; 11 | } 12 | var installedModules = {}; 13 | return __webpack_require__.m = modules, __webpack_require__.c = installedModules, 14 | __webpack_require__.p = "", __webpack_require__(0); 15 | }([ function(module, exports) { 16 | "use strict"; 17 | function handleMessageFromDevtools(message) { 18 | window.postMessage({ 19 | source: "react-devtools-content-script", 20 | payload: message 21 | }, "*"); 22 | } 23 | function handleMessageFromPage(evt) { 24 | evt.source === window && evt.data && "react-devtools-bridge" === evt.data.source && port.postMessage(evt.data.payload); 25 | } 26 | function handleDisconnect() { 27 | window.removeEventListener("message", handleMessageFromPage), window.postMessage({ 28 | source: "react-devtools-content-script", 29 | payload: { 30 | type: "event", 31 | evt: "shutdown" 32 | } 33 | }, "*"); 34 | } 35 | var port = chrome.runtime.connect({ 36 | name: "content-script" 37 | }); 38 | port.onMessage.addListener(handleMessageFromDevtools), port.onDisconnect.addListener(handleDisconnect), 39 | window.addEventListener("message", handleMessageFromPage), window.postMessage({ 40 | source: "react-devtools-content-script", 41 | hello: !0 42 | }, "*"); 43 | } ]); -------------------------------------------------------------------------------- /devtools/firefox/unpacked/build/main.js: -------------------------------------------------------------------------------- 1 | !function(modules) { 2 | function __webpack_require__(moduleId) { 3 | if (installedModules[moduleId]) return installedModules[moduleId].exports; 4 | var module = installedModules[moduleId] = { 5 | exports: {}, 6 | id: moduleId, 7 | loaded: !1 8 | }; 9 | return modules[moduleId].call(module.exports, module, module.exports, __webpack_require__), 10 | module.loaded = !0, module.exports; 11 | } 12 | var installedModules = {}; 13 | return __webpack_require__.m = modules, __webpack_require__.c = installedModules, 14 | __webpack_require__.p = "", __webpack_require__(0); 15 | }([ function(module, exports) { 16 | "use strict"; 17 | function createPanelIfReactLoaded() { 18 | panelCreated || chrome.devtools.inspectedWindow.eval("!!(\n Object.keys(window.__REACT_DEVTOOLS_GLOBAL_HOOK__._renderers).length || window.React\n )", function(pageHasReact, err) { 19 | pageHasReact && !panelCreated && (clearInterval(loadCheckInterval), panelCreated = !0, 20 | chrome.devtools.panels.create("React", "", "panel.html", function(panel) { 21 | var reactPanel = null; 22 | panel.onShown.addListener(function(window) { 23 | window.panel.getNewSelection(), reactPanel = window.panel, reactPanel.resumeTransfer(); 24 | }), panel.onHidden.addListener(function() { 25 | reactPanel && (reactPanel.hideHighlight(), reactPanel.pauseTransfer()); 26 | }); 27 | })); 28 | }); 29 | } 30 | var panelCreated = !1; 31 | chrome.devtools.network.onNavigated.addListener(function() { 32 | createPanelIfReactLoaded(); 33 | }); 34 | var loadCheckInterval = setInterval(function() { 35 | createPanelIfReactLoaded(); 36 | }, 1e3); 37 | createPanelIfReactLoaded(); 38 | } ]); -------------------------------------------------------------------------------- /devtools/firefox/unpacked/icons/128-deadcode.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VoliJS/React-Type-R/8d157b9afd76850f680c677d62437e4516191b77/devtools/firefox/unpacked/icons/128-deadcode.png -------------------------------------------------------------------------------- /devtools/firefox/unpacked/icons/128-development.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VoliJS/React-Type-R/8d157b9afd76850f680c677d62437e4516191b77/devtools/firefox/unpacked/icons/128-development.png -------------------------------------------------------------------------------- /devtools/firefox/unpacked/icons/128-disabled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VoliJS/React-Type-R/8d157b9afd76850f680c677d62437e4516191b77/devtools/firefox/unpacked/icons/128-disabled.png -------------------------------------------------------------------------------- /devtools/firefox/unpacked/icons/128-outdated.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VoliJS/React-Type-R/8d157b9afd76850f680c677d62437e4516191b77/devtools/firefox/unpacked/icons/128-outdated.png -------------------------------------------------------------------------------- /devtools/firefox/unpacked/icons/128-production.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VoliJS/React-Type-R/8d157b9afd76850f680c677d62437e4516191b77/devtools/firefox/unpacked/icons/128-production.png -------------------------------------------------------------------------------- /devtools/firefox/unpacked/icons/128-unminified.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VoliJS/React-Type-R/8d157b9afd76850f680c677d62437e4516191b77/devtools/firefox/unpacked/icons/128-unminified.png -------------------------------------------------------------------------------- /devtools/firefox/unpacked/icons/16-deadcode.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VoliJS/React-Type-R/8d157b9afd76850f680c677d62437e4516191b77/devtools/firefox/unpacked/icons/16-deadcode.png -------------------------------------------------------------------------------- /devtools/firefox/unpacked/icons/16-development.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VoliJS/React-Type-R/8d157b9afd76850f680c677d62437e4516191b77/devtools/firefox/unpacked/icons/16-development.png -------------------------------------------------------------------------------- /devtools/firefox/unpacked/icons/16-disabled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VoliJS/React-Type-R/8d157b9afd76850f680c677d62437e4516191b77/devtools/firefox/unpacked/icons/16-disabled.png -------------------------------------------------------------------------------- /devtools/firefox/unpacked/icons/16-outdated.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VoliJS/React-Type-R/8d157b9afd76850f680c677d62437e4516191b77/devtools/firefox/unpacked/icons/16-outdated.png -------------------------------------------------------------------------------- /devtools/firefox/unpacked/icons/16-production.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VoliJS/React-Type-R/8d157b9afd76850f680c677d62437e4516191b77/devtools/firefox/unpacked/icons/16-production.png -------------------------------------------------------------------------------- /devtools/firefox/unpacked/icons/16-unminified.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VoliJS/React-Type-R/8d157b9afd76850f680c677d62437e4516191b77/devtools/firefox/unpacked/icons/16-unminified.png -------------------------------------------------------------------------------- /devtools/firefox/unpacked/icons/32-deadcode.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VoliJS/React-Type-R/8d157b9afd76850f680c677d62437e4516191b77/devtools/firefox/unpacked/icons/32-deadcode.png -------------------------------------------------------------------------------- /devtools/firefox/unpacked/icons/32-development.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VoliJS/React-Type-R/8d157b9afd76850f680c677d62437e4516191b77/devtools/firefox/unpacked/icons/32-development.png -------------------------------------------------------------------------------- /devtools/firefox/unpacked/icons/32-disabled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VoliJS/React-Type-R/8d157b9afd76850f680c677d62437e4516191b77/devtools/firefox/unpacked/icons/32-disabled.png -------------------------------------------------------------------------------- /devtools/firefox/unpacked/icons/32-outdated.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VoliJS/React-Type-R/8d157b9afd76850f680c677d62437e4516191b77/devtools/firefox/unpacked/icons/32-outdated.png -------------------------------------------------------------------------------- /devtools/firefox/unpacked/icons/32-production.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VoliJS/React-Type-R/8d157b9afd76850f680c677d62437e4516191b77/devtools/firefox/unpacked/icons/32-production.png -------------------------------------------------------------------------------- /devtools/firefox/unpacked/icons/32-unminified.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VoliJS/React-Type-R/8d157b9afd76850f680c677d62437e4516191b77/devtools/firefox/unpacked/icons/32-unminified.png -------------------------------------------------------------------------------- /devtools/firefox/unpacked/icons/48-deadcode.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VoliJS/React-Type-R/8d157b9afd76850f680c677d62437e4516191b77/devtools/firefox/unpacked/icons/48-deadcode.png -------------------------------------------------------------------------------- /devtools/firefox/unpacked/icons/48-development.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VoliJS/React-Type-R/8d157b9afd76850f680c677d62437e4516191b77/devtools/firefox/unpacked/icons/48-development.png -------------------------------------------------------------------------------- /devtools/firefox/unpacked/icons/48-disabled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VoliJS/React-Type-R/8d157b9afd76850f680c677d62437e4516191b77/devtools/firefox/unpacked/icons/48-disabled.png -------------------------------------------------------------------------------- /devtools/firefox/unpacked/icons/48-outdated.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VoliJS/React-Type-R/8d157b9afd76850f680c677d62437e4516191b77/devtools/firefox/unpacked/icons/48-outdated.png -------------------------------------------------------------------------------- /devtools/firefox/unpacked/icons/48-production.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VoliJS/React-Type-R/8d157b9afd76850f680c677d62437e4516191b77/devtools/firefox/unpacked/icons/48-production.png -------------------------------------------------------------------------------- /devtools/firefox/unpacked/icons/48-unminified.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VoliJS/React-Type-R/8d157b9afd76850f680c677d62437e4516191b77/devtools/firefox/unpacked/icons/48-unminified.png -------------------------------------------------------------------------------- /devtools/firefox/unpacked/icons/deadcode.svg: -------------------------------------------------------------------------------- 1 | development780780 -------------------------------------------------------------------------------- /devtools/firefox/unpacked/icons/development.svg: -------------------------------------------------------------------------------- 1 | development780780 -------------------------------------------------------------------------------- /devtools/firefox/unpacked/icons/disabled.svg: -------------------------------------------------------------------------------- 1 | disabled -------------------------------------------------------------------------------- /devtools/firefox/unpacked/icons/outdated.svg: -------------------------------------------------------------------------------- 1 | outdated -------------------------------------------------------------------------------- /devtools/firefox/unpacked/icons/production.svg: -------------------------------------------------------------------------------- 1 | production -------------------------------------------------------------------------------- /devtools/firefox/unpacked/main.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /devtools/firefox/unpacked/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "manifest_version": 2, 3 | "name": "React Developer Tools", 4 | "description": "Adds React debugging tools to the Firefox Developer Tools.", 5 | "version": "2.5.2", 6 | 7 | "applications": { 8 | "gecko": { 9 | "id": "@react-devtools", 10 | "strict_min_version": "54.0" 11 | } 12 | }, 13 | 14 | "icons": { 15 | "16": "icons/16-production.png", 16 | "32": "icons/32-production.png", 17 | "48": "icons/48-production.png", 18 | "128": "icons/128-production.png" 19 | }, 20 | 21 | "browser_action": { 22 | "default_icon": { 23 | "16": "icons/16-disabled.png", 24 | "32": "icons/32-disabled.png", 25 | "48": "icons/48-disabled.png", 26 | "128": "icons/128-disabled.png" 27 | }, 28 | 29 | "default_popup": "popups/disabled.html", 30 | "browser_style": true 31 | }, 32 | 33 | "devtools_page": "main.html", 34 | 35 | "content_security_policy": "script-src 'self' 'unsafe-eval'; object-src 'self'", 36 | "web_accessible_resources": [ "main.html", "panel.html", "build/backend.js"], 37 | 38 | "background": { 39 | "scripts": [ "build/background.js" ], 40 | "persistent": false 41 | }, 42 | 43 | "permissions": [ 44 | "file:///*", 45 | "http://*/*", 46 | "https://*/*" 47 | ], 48 | 49 | "content_scripts": [ 50 | { 51 | "matches": [""], 52 | "js": ["build/inject.js"], 53 | "run_at": "document_start" 54 | } 55 | ] 56 | } -------------------------------------------------------------------------------- /devtools/firefox/unpacked/panel.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 26 | 27 | 28 | 29 |
Unable to find React on the page.
30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /devtools/firefox/unpacked/popups/deadcode.html: -------------------------------------------------------------------------------- 1 | 2 | 17 |

18 | This page includes an extra development build of React. 🚧 19 |

20 |

21 | The React build on this page includes both development and production versions because dead code elimination has not been applied correctly. 22 |
23 |
24 | This makes its size larger, and causes React to run slower. 25 |
26 |
27 | Make sure to set up dead code elimination before deployment. 28 |

29 |
30 |

31 | Open the developer tools, and the React tab will appear to the right. 32 |

33 | -------------------------------------------------------------------------------- /devtools/firefox/unpacked/popups/development.html: -------------------------------------------------------------------------------- 1 | 2 | 17 |

18 | This page is using the development build of React. 🚧 19 |

20 |

21 | Note that the development build is not suitable for production. 22 |
23 | Make sure to use the production build before deployment. 24 |

25 |
26 |

27 | Open the developer tools, and the React tab will appear to the right. 28 |

29 | -------------------------------------------------------------------------------- /devtools/firefox/unpacked/popups/disabled.html: -------------------------------------------------------------------------------- 1 | 2 | 17 |

18 | This page doesn’t appear to be using React. 19 |
20 | If this seems wrong, follow the troubleshooting instructions. 21 |

22 | -------------------------------------------------------------------------------- /devtools/firefox/unpacked/popups/outdated.html: -------------------------------------------------------------------------------- 1 | 2 | 17 |

18 | This page is using an outdated version of React. ⌛ 19 |

20 |

21 | We recommend updating React to ensure that you receive important bugfixes and performance improvements. 22 |
23 |
24 | You can find the upgrade instructions on the React blog. 25 |

26 |
27 |

28 | Open the developer tools, and the React tab will appear to the right. 29 |

30 | -------------------------------------------------------------------------------- /devtools/firefox/unpacked/popups/production.html: -------------------------------------------------------------------------------- 1 | 2 | 17 |

18 | This page is using the production build of React. ✅ 19 |
20 | Open the developer tools, and the React tab will appear to the right. 21 |

22 | -------------------------------------------------------------------------------- /devtools/firefox/unpacked/popups/shared.js: -------------------------------------------------------------------------------- 1 | /* globals chrome */ 2 | 3 | document.addEventListener('DOMContentLoaded', function() { 4 | // Make links work 5 | var links = document.getElementsByTagName('a'); 6 | for (var i = 0; i < links.length; i++) { 7 | (function() { 8 | var ln = links[i]; 9 | var location = ln.href; 10 | ln.onclick = function() { 11 | chrome.tabs.create({active: true, url: location}); 12 | }; 13 | })(); 14 | } 15 | 16 | // Work around https://bugs.chromium.org/p/chromium/issues/detail?id=428044 17 | document.body.style.opacity = 0; 18 | document.body.style.transition = 'opacity ease-out .4s'; 19 | requestAnimationFrame(function() { 20 | document.body.style.opacity = 1; 21 | }); 22 | }); 23 | -------------------------------------------------------------------------------- /devtools/firefox/unpacked/popups/unminified.html: -------------------------------------------------------------------------------- 1 | 2 | 17 |

18 | This page is using an unminified build of React. 🚧 19 |

20 |

21 | The React build on this page appears to be unminified. 22 |
23 | This makes its size larger, and causes React to run slower. 24 |
25 |
26 | Make sure to set up minification before deployment. 27 |

28 |
29 |

30 | Open the developer tools, and the React tab will appear to the right. 31 |

32 | -------------------------------------------------------------------------------- /docs/chapters/record.md: -------------------------------------------------------------------------------- 1 | # Record and Collection 2 | 3 | React-MVx relies of [Type-R](https://volicon.github.io/Type-R/) framework to manage a multi-layer application state. 4 | 5 | - [Record](https://volicon.github.io/Type-R/#record) class is used to manage component's state. 6 | - The subset of the [Record attributes type annotation](https://volicon.github.io/Type-R/#definition) is used to define props and context. 7 | - [Store](https://volicon.github.io/Type-R/#store) class is used to represent component's store (also called "local store"), which is typically used in the root component of SPA page associated with a route. The state of the children components uses upper component's stores to resolve id-references. 8 | - Type-R [global store](https://volicon.github.io/Type-R/#-static-store-global) may be used as a store for the data shared by application pages. This store is used to resolve id-references in case if local stores lookup failed. 9 | 10 | -------------------------------------------------------------------------------- /docs/chapters/releasenotes.md: -------------------------------------------------------------------------------- 1 | # Release Notes 2 | 3 | ## 2.0.0 4 | 5 | - Bug fixes: 6 | - Fixed problems with deep inheritance from the React.Component 7 | - Mixins now works well with inheritance. 8 | - Breaking changes: 9 | - *React lifecycle hook methods for the subclass are called automatically*. 10 | - Other: 11 | - `{ ...link.props }` for ad-hoc data binding makes `tags.jsx` wrappers obsolete. 12 | - Type-R v2.0 is required. 13 | - New universal API for generating links (`linkAt()`) 14 | - First-class component stores support. -------------------------------------------------------------------------------- /docs/examples/babel-boilerplate/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets":["react", ["es2015", {"loose": true}] ], 3 | "plugins":[ 4 | "transform-decorators-legacy", 5 | "transform-object-rest-spread", 6 | "add-module-exports", 7 | "transform-class-properties" 8 | ], 9 | 10 | "env": { 11 | "production": { 12 | "plugins": [ 13 | "transform-react-constant-elements", 14 | "transform-react-inline-elements" 15 | ] 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /docs/examples/babel-boilerplate/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Webpack Babel ReactMVC Boilerplate 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /docs/examples/babel-boilerplate/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "dependencies": {}, 4 | "devDependencies": { 5 | "babel-cli": "*", 6 | "babel-core": "*", 7 | "babel-loader": "*", 8 | "babel-plugin-add-module-exports": "*", 9 | "babel-plugin-transform-class-properties": "*", 10 | "babel-plugin-transform-decorators-legacy": "*", 11 | "babel-plugin-transform-object-rest-spread": "*", 12 | "babel-plugin-transform-react-constant-elements": "*", 13 | "babel-plugin-transform-react-inline-elements": "*", 14 | "babel-preset-es2015": "*", 15 | "babel-preset-react": "*", 16 | "babel-runtime": "*", 17 | "css-loader": "*", 18 | "prop-types": "*", 19 | "react": "^16.1.1", 20 | "react-dom": "^16.1.1", 21 | "react-mvx": "^2.0.0-rc900", 22 | "source-map-loader": "*", 23 | "style-loader": "*", 24 | "type-r": "^2.0.0", 25 | "webpack": "^3.8.1" 26 | }, 27 | "scripts": { 28 | "test": "echo \"Error: no test specified\" && exit 1", 29 | "build": "node_modules/.bin/webpack", 30 | "watch": "node_modules/.bin/webpack --progress --colors --watch" 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /docs/examples/babel-boilerplate/src/index.jsx: -------------------------------------------------------------------------------- 1 | import React, { define } from 'react-mvx' 2 | import ReactDOM from 'react-dom' 3 | import { Record } from 'type-r' 4 | 5 | import './styles.css' 6 | 7 | @define class Item extends Record { 8 | static attributes = { 9 | text : String 10 | } 11 | } 12 | 13 | @define class Application extends React.Component { 14 | static state = { 15 | items : Item.Collection 16 | }; 17 | 18 | render(){ 19 | const { state } = this; 20 | 21 | return ( 22 |
23 | 26 | 27 | { state.items.map( item => ( 28 | 29 | ))} 30 |
31 | ); 32 | } 33 | } 34 | 35 | const ItemView = ({ item }) => ( 36 | 37 | ); 38 | 39 | ReactDOM.render( , document.getElementById( 'react-application' ) ); -------------------------------------------------------------------------------- /docs/examples/babel-boilerplate/src/styles.css: -------------------------------------------------------------------------------- 1 | input { 2 | margin : 1em; 3 | border-radius: 2px; 4 | } -------------------------------------------------------------------------------- /docs/examples/babel-boilerplate/webpack.config.js: -------------------------------------------------------------------------------- 1 | var webpack = require( 'webpack' ), 2 | path = require( 'path' ); 3 | 4 | var config = { 5 | entry : { 6 | app : './src/index.jsx' 7 | }, 8 | 9 | output : { 10 | // export itself to a global var 11 | path : __dirname + '/dist', 12 | publicPath : '/dist/', 13 | filename : '[name].js' 14 | }, 15 | 16 | devtool : 'source-map', 17 | 18 | resolve : { 19 | modules : [ 'node_modules', 'src' ] 20 | }, 21 | 22 | module : { 23 | rules : [ 24 | { 25 | test : /\.css$/, 26 | use : [ 27 | { 28 | loader: "style-loader" 29 | }, 30 | { 31 | loader: "css-loader", 32 | options: { 33 | modules: true 34 | } 35 | } 36 | ] 37 | }, 38 | { 39 | test : /\.jsx?$/, 40 | exclude : /(node_modules|lib)/, 41 | loader : 'babel-loader' 42 | }, 43 | { 44 | test: /\.js$/, 45 | use: ["source-map-loader"], 46 | enforce: "pre" 47 | } 48 | ] 49 | } 50 | }; 51 | 52 | module.exports = config; -------------------------------------------------------------------------------- /docs/examples/checklistTree/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets":["react", ["es2015", {"loose": true}] ], 3 | "plugins":[ 4 | "transform-decorators-legacy", 5 | "transform-object-rest-spread", 6 | "add-module-exports", 7 | "transform-class-properties" 8 | ], 9 | 10 | "env": { 11 | "production": { 12 | "plugins": [ 13 | "transform-react-constant-elements", 14 | "transform-react-inline-elements" 15 | ] 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /docs/examples/checklistTree/README.md: -------------------------------------------------------------------------------- 1 | # Hiearchical Checklist. 2 | 3 | Classic hierarchical checklist example, which you could often see in installers. 4 | This is checklist with a rule. Item is checked, if all children are checked. 5 | 6 | ![Screenshot](./screenshot.png) 7 | 8 | 59 SLOC for jsx components, 28 for the model definition. 9 | 10 | This example demonstrates unidirectional data flow with mutable state and pure render optimisation. And different features of the NestedReact state management. 11 | 12 | - Declarative definition of mutable observable state. `static state = { element : ConstructorFunction }`. 13 | - Two-way data binding with advanced value links. `const links = model.linkAll( 'checked', 'name' )`. 14 | - Simplified React props spec. `static props = { name : ConstructorFunction, name2 : Constructor.value( defaultValue ) }` 15 | - Declarative `pureRender` for mutable data and value links. `static pureRender = true`. 16 | - Recursive state definitions. Model can mention itself in its attribute specs, thus, it's possible to define 17 | (potentially) infinite recursive data structures. 18 | - Change watchers. It's possible to attach 'watchers' to any attribute, which would be called on value change. 19 | - Transactional updates. Any change made to the model from the watcher is being added to the current transaction, 20 | resulting in the single 'change' event per transaction. Look at the render count in the example - you've got one 21 | render no matter how many checkboxes was flipped. 22 | 23 | 24 | -------------------------------------------------------------------------------- /docs/examples/checklistTree/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | React-R Checklist Tree 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /docs/examples/checklistTree/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "dependencies": {}, 4 | "devDependencies": { 5 | "babel-cli": "*", 6 | "babel-core": "*", 7 | "babel-loader": "*", 8 | "babel-plugin-add-module-exports": "*", 9 | "babel-plugin-transform-class-properties": "*", 10 | "babel-plugin-transform-decorators-legacy": "*", 11 | "babel-plugin-transform-object-rest-spread": "*", 12 | "babel-plugin-transform-react-constant-elements": "*", 13 | "babel-plugin-transform-react-inline-elements": "*", 14 | "babel-preset-es2015": "*", 15 | "babel-preset-react": "*", 16 | "babel-runtime": "*", 17 | "classnames": "*", 18 | "css-loader": "*", 19 | "prop-types": "*", 20 | "react": "^16.2.0", 21 | "react-dom": "^16.2.0", 22 | "react-mvx": "^2.0.4", 23 | "source-map-loader": "*", 24 | "style-loader": "^0.19.1", 25 | "type-r": "^2.0.5", 26 | "webpack": "^3.10.0" 27 | }, 28 | "scripts": { 29 | "test": "echo \"Error: no test specified\" && exit 1", 30 | "build": "node_modules/.bin/webpack", 31 | "watch": "node_modules/.bin/webpack --progress --colors --watch" 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /docs/examples/checklistTree/screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VoliJS/React-Type-R/8d157b9afd76850f680c677d62437e4516191b77/docs/examples/checklistTree/screenshot.png -------------------------------------------------------------------------------- /docs/examples/checklistTree/src/model.js: -------------------------------------------------------------------------------- 1 | // Data objects are defined in nestedtypes package. 2 | import { Record, define } from 'type-r' 3 | 4 | @define class Checklist extends Record.Collection { 5 | get checked(){ return this.every( item => item.checked ); } 6 | set checked( checked ){ 7 | if( checked !== this.checked ){ 8 | this.updateEach( item => { item.checked = checked } ); 9 | } 10 | } 11 | } 12 | 13 | @define 14 | export class ChecklistItem extends Record { 15 | static Collection = Checklist; 16 | 17 | static attributes = { // <- Here's an attribute spec. Think of it as a type spec. 18 | name : String, 19 | created : Date, 20 | checked : Boolean.has.watcher( 'checkedWatcher' ), 21 | subitems : Checklist.has.watcher( 'subitemsWatcher' ) 22 | }; 23 | 24 | checkedWatcher( checked ){ this.subitems.checked = checked; } 25 | 26 | subitemsWatcher( subitems ){ 27 | if( subitems.length ){ 28 | this.checked = this.subitems.checked; 29 | } 30 | } 31 | 32 | remove(){ this.collection.remove( this ); } 33 | } -------------------------------------------------------------------------------- /docs/examples/checklistTree/src/styles.css: -------------------------------------------------------------------------------- 1 | .checkbox { 2 | display: inline-block; 3 | width: 10px; 4 | height: 10px; 5 | border: solid; 6 | border-width: 1px; 7 | margin: 3px; 8 | vertical-align: middle; 9 | } 10 | 11 | .children { 12 | margin-left: 1em; 13 | } 14 | 15 | .checkbox.selected { 16 | background-color: black; 17 | } 18 | 19 | input { 20 | border: none; 21 | border-bottom: solid; 22 | border-width: 1px; 23 | margin: 3px; 24 | margin-left : 10px; 25 | } 26 | 27 | input:focus { 28 | outline: none; 29 | border-width: 2px; 30 | } 31 | 32 | button { 33 | border-radius: 3px; 34 | background-color: white; 35 | } 36 | 37 | .created { 38 | margin : 3px; 39 | font-size: 11px; 40 | } -------------------------------------------------------------------------------- /docs/examples/checklistTree/webpack.config.js: -------------------------------------------------------------------------------- 1 | var webpack = require( 'webpack' ), 2 | path = require( 'path' ); 3 | 4 | var config = { 5 | entry : { 6 | app : './src/index.jsx' 7 | }, 8 | 9 | output : { 10 | // export itself to a global var 11 | path : __dirname + '/dist', 12 | publicPath : '/dist/', 13 | filename : '[name].js' 14 | }, 15 | 16 | devtool : 'source-map', 17 | 18 | resolve : { 19 | modules : [ 'node_modules', 'src' ], 20 | // alias : { //use `npm run deploy:examples` in main project 21 | // 'react-mvx' : path.resolve(__dirname, '../..' ) 22 | // } 23 | }, 24 | 25 | module : { 26 | rules : [ 27 | { 28 | test : /\.css$/, 29 | use : [ 30 | { 31 | loader: "style-loader" 32 | }, 33 | { 34 | loader: "css-loader" 35 | } 36 | ] 37 | }, 38 | { 39 | test : /\.jsx?$/, 40 | exclude : /(node_modules|lib)/, 41 | loader : 'babel-loader' 42 | }, 43 | { 44 | test: /\.js$/, 45 | use: ["source-map-loader"], 46 | enforce: "pre" 47 | } 48 | ] 49 | } 50 | }; 51 | 52 | module.exports = config; -------------------------------------------------------------------------------- /docs/examples/flux-comparison/application.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VoliJS/React-Type-R/8d157b9afd76850f680c677d62437e4516191b77/docs/examples/flux-comparison/application.png -------------------------------------------------------------------------------- /docs/examples/flux-comparison/cart.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VoliJS/React-Type-R/8d157b9afd76850f680c677d62437e4516191b77/docs/examples/flux-comparison/cart.png -------------------------------------------------------------------------------- /docs/examples/flux-comparison/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | NestedReact Anti-Flux Sample 6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /docs/examples/flux-comparison/js/app.js: -------------------------------------------------------------------------------- 1 | import React from 'nestedreact' 2 | import App from './components/App.jsx' 3 | 4 | React.render( 5 | React.createElement( App, null ), 6 | document.getElementById( 'non-flux-app' ) 7 | ); 8 | -------------------------------------------------------------------------------- /docs/examples/flux-comparison/js/components/App.jsx: -------------------------------------------------------------------------------- 1 | import React, { define } from 'react-mvx' 2 | 3 | import ProductsContainer from './ProductsContainer.jsx' 4 | import CartContainer from './CartContainer.jsx' 5 | 6 | import Cart from '../models/Cart' 7 | import Product from '../models/Product' 8 | 9 | @define 10 | export default class App extends React.Component { 11 | // Declare application's state 12 | // UI will be updated automatically on every state, 13 | // deep changes will be detected too. 14 | static state = { 15 | cart : Cart, 16 | products : Product.Collection 17 | } 18 | 19 | componentWillMount(){ 20 | // fetch data on application start... 21 | this.state.products.fetch(); 22 | } 23 | 24 | render(){ 25 | const { state } = this; 26 | return ( 27 |
28 | state.cart.add( product ) }/> 30 | 31 | 32 |
33 | ); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /docs/examples/flux-comparison/js/components/CartContainer.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react-mvx' 2 | import CCart from '../../../common/components/Cart.jsx' 3 | 4 | const CartContainer = ( { cart } ) => ( 5 | cart.checkout() }/> // But likely for us, cart is not an array. 8 | ); 9 | 10 | export default CartContainer; 11 | -------------------------------------------------------------------------------- /docs/examples/flux-comparison/js/components/ProductsContainer.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react-mvx' 2 | import CProductItem from '../../../common/components/ProductItem.jsx' 3 | import CProductsList from '../../../common/components/ProductsList.jsx' 4 | 5 | 6 | const ProductsContainer = ( { products, addToCart } ) =>( 7 | 8 | { products.map( product => ( 9 | 12 | ) )} 13 | 14 | ); 15 | 16 | export default ProductsContainer; 17 | -------------------------------------------------------------------------------- /docs/examples/flux-comparison/js/models/Cart.js: -------------------------------------------------------------------------------- 1 | import { define, Collection } from 'type-r' 2 | import Product from './Product' 3 | import shop from '../../../common/api/shop' 4 | 5 | @define 6 | export default class Cart extends Collection { 7 | // Cart is a collection of products... 8 | model : Product, 9 | 10 | // ... which you can checkout. 11 | checkout(){ 12 | shop.buyProducts( this.toJSON(), () => this.reset() ); 13 | } 14 | } -------------------------------------------------------------------------------- /docs/examples/flux-comparison/js/models/Product.js: -------------------------------------------------------------------------------- 1 | import { define, Record } from 'type-r' 2 | import shop from '../../../common/api/shop' 3 | 4 | @define 5 | export default class Product extends Record { 6 | static attributes = { 7 | image : String, 8 | title : String, 9 | price : Number, 10 | inventory : Number 11 | }; 12 | 13 | static collection = { 14 | fetch(){ 15 | shop.getProducts( products => this.reset( products, { parse : true } ) ); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /docs/examples/flux-comparison/product.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VoliJS/React-Type-R/8d157b9afd76850f680c677d62437e4516191b77/docs/examples/flux-comparison/product.png -------------------------------------------------------------------------------- /docs/examples/flux-comparison/sloc-comparison.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VoliJS/React-Type-R/8d157b9afd76850f680c677d62437e4516191b77/docs/examples/flux-comparison/sloc-comparison.png -------------------------------------------------------------------------------- /docs/examples/flux-comparison/unidirectional-data-flow.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VoliJS/React-Type-R/8d157b9afd76850f680c677d62437e4516191b77/docs/examples/flux-comparison/unidirectional-data-flow.jpg -------------------------------------------------------------------------------- /docs/examples/todomvc/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets":["react", ["es2015", {"loose": true}] ], 3 | "plugins":[ 4 | "transform-decorators-legacy", 5 | "transform-object-rest-spread", 6 | "add-module-exports", 7 | "transform-class-properties" 8 | ], 9 | 10 | "env": { 11 | "production": { 12 | "plugins": [ 13 | "transform-react-constant-elements", 14 | "transform-react-inline-elements" 15 | ] 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /docs/examples/todomvc/SLOC-comparison.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VoliJS/React-Type-R/8d157b9afd76850f680c677d62437e4516191b77/docs/examples/todomvc/SLOC-comparison.jpg -------------------------------------------------------------------------------- /docs/examples/todomvc/css/app.css: -------------------------------------------------------------------------------- 1 | .something { 2 | background: black; 3 | } 4 | -------------------------------------------------------------------------------- /docs/examples/todomvc/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | NestedReact • TodoMVC 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /docs/examples/todomvc/js/addtodo.jsx: -------------------------------------------------------------------------------- 1 | import React, { define } from 'react-mvx' 2 | 3 | @define 4 | export default class AddTodo extends React.Component { 5 | static props = { 6 | onEnter : Function.value( function(){} ) 7 | } 8 | 9 | static state = { 10 | desc : String 11 | } 12 | 13 | render(){ 14 | return ( 15 |
16 |

todos

17 | 18 | this.onKeyDown( e ) } 23 | /> 24 |
25 | ); 26 | } 27 | 28 | onKeyDown( { keyCode } ){ 29 | if( keyCode === 13 ){ 30 | let { state, props } = this; 31 | 32 | state.desc && props.onEnter( state.desc ); 33 | state.desc = ""; 34 | } 35 | } 36 | } -------------------------------------------------------------------------------- /docs/examples/todomvc/js/filter.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react-mvx' 2 | 3 | const Filter = ( { count, filterLink, onClear } ) => ( 4 |
5 | 6 | { count } item left 7 | 8 | 9 |
    10 | 12 | All 13 | 14 | 16 | Active 17 | 18 | 20 | Completed 21 | 22 |
23 | 24 | 28 |
29 | ); 30 | 31 | export default Filter; 32 | 33 | const Radio = ( { checkedLink, children, ...props } ) => ( 34 |
  • 35 | checkedLink.set( true ) } 37 | { ...props }> 38 | { children } 39 | 40 |
  • 41 | ); 42 | -------------------------------------------------------------------------------- /docs/examples/todomvc/js/main.jsx: -------------------------------------------------------------------------------- 1 | import '../css/app.css' 2 | import React, { define } from 'react-mvx' 3 | import { Record } from 'type-r' 4 | import ReactDOM from 'react-dom' 5 | import {ToDo} from './model.js' 6 | import TodoList from './todolist.jsx' 7 | import Filter from './filter.jsx' 8 | import AddTodo from './addtodo.jsx' 9 | 10 | import { localStorageIO } from 'type-r/endpoints/localStorage' 11 | 12 | // Declare component state 13 | @define class AppState extends Record { 14 | static endpoint = localStorageIO( '/react-mvx/examples' ); 15 | 16 | static attributes = { 17 | id : 'todoMVC', 18 | todos : ToDo.Collection, 19 | filterDone : Boolean.value( null ) // null | true | false, initialized with null. 20 | } 21 | } 22 | 23 | @define class App extends React.Component { 24 | static State = AppState; 25 | 26 | componentWillMount(){ 27 | this.state.fetch(); 28 | window.onunload = () => this.state.save(); 29 | } 30 | 31 | render(){ 32 | const { todos, filterDone } = this.state, 33 | hasTodos = Boolean( todos.length ); 34 | 35 | return ( 36 |
    37 |
    38 | todos.add({ desc : desc }) }/> 39 | 40 | { hasTodos && } 42 | 43 | { hasTodos && todos.clearCompleted() } 46 | />} 47 |
    48 | 49 | 55 |
    56 | ); 57 | } 58 | } 59 | 60 | ReactDOM.render( , document.getElementById( 'app-mount-root' ) ); 61 | 62 | -------------------------------------------------------------------------------- /docs/examples/todomvc/js/model.js: -------------------------------------------------------------------------------- 1 | import { Record, define } from 'type-r' 2 | 3 | @define class ToDoCollection extends Record.Collection { 4 | clearCompleted(){ 5 | this.remove( this.filter( todo => todo.done ) ); 6 | } 7 | 8 | get allDone(){ 9 | return this.every( todo => todo.done ); 10 | } 11 | 12 | set allDone( val ){ 13 | this.updateEach( todo => todo.done = val ); 14 | } 15 | 16 | get activeCount(){ 17 | return this.filter( todo => !todo.done ).length; 18 | } 19 | } 20 | 21 | @define 22 | export class ToDo extends Record { 23 | static Collection = ToDoCollection; 24 | static attributes = { 25 | done : Boolean, 26 | desc : String 27 | } 28 | 29 | remove(){ 30 | this.collection.remove( this ); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /docs/examples/todomvc/js/todolist.jsx: -------------------------------------------------------------------------------- 1 | import React, { define } from 'react-mvx' 2 | import cx from 'classnames' 3 | import { ToDo } from './model' 4 | 5 | @define export default 6 | class TodoList extends React.Component { 7 | static props = { 8 | todos : ToDo.Collection, 9 | filterDone : Boolean 10 | } 11 | 12 | static state = { 13 | editing : ToDo.from( '^props.todos' ) 14 | } 15 | 16 | static pureRender = true 17 | 18 | render(){ 19 | const { todos, filterDone } = this.props, 20 | filtered = filterDone === null ? 21 | todos.models : 22 | todos.filter( todo => todo.done === filterDone ), 23 | editingLink = this.state.linkAt( 'editing' ); 24 | 25 | return ( 26 |
    27 | 31 | 32 | 35 | 36 |
      37 | { filtered.map( todo => ( 38 | 41 | ) )} 42 |
    43 |
    44 | ); 45 | } 46 | } 47 | 48 | function clearOnEnter( x, e ){ 49 | if( e.keyCode === 13 ) return null; 50 | } 51 | 52 | const TodoItem = ( { todo, editingLink } ) =>{ 53 | const editing = editingLink.value === todo, 54 | className = cx( { 55 | 'completed' : todo.done, 56 | 'view' : !todo.done, 57 | 'editing' : editing 58 | } ); 59 | 60 | return ( 61 |
  • 62 |
    63 | 66 | 67 | 70 | 71 |
    74 | 75 | { editing && null ) } 79 | onKeyDown={ editingLink.action( clearOnEnter ) }/> } 80 |
  • 81 | ); 82 | }; 83 | -------------------------------------------------------------------------------- /docs/examples/todomvc/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "dependencies": { 4 | "todomvc-app-css": "^2.0.0", 5 | "todomvc-common": "^1.0.0" 6 | }, 7 | "devDependencies": { 8 | "babel-cli": "*", 9 | "babel-core": "*", 10 | "babel-loader": "*", 11 | "babel-plugin-add-module-exports": "*", 12 | "babel-plugin-transform-class-properties": "*", 13 | "babel-plugin-transform-decorators-legacy": "*", 14 | "babel-plugin-transform-object-rest-spread": "*", 15 | "babel-plugin-transform-react-constant-elements": "*", 16 | "babel-plugin-transform-react-inline-elements": "*", 17 | "babel-preset-es2015": "*", 18 | "babel-preset-react": "*", 19 | "babel-runtime": "*", 20 | "classnames": "*", 21 | "css-loader": "*", 22 | "react-modal": "^3.1.2", 23 | "source-map-loader": "^0.2.3", 24 | "react": "*", 25 | "react-dom": "*", 26 | "react-mvx": "^2.0.0-00", 27 | "prop-types": "*", 28 | "type-r": "^2.0.0-00", 29 | "style-loader": "*", 30 | "webpack": "^3.8.1" 31 | }, 32 | "scripts": { 33 | "test": "echo \"Error: no test specified\" && exit 1", 34 | "build": "node_modules/.bin/webpack", 35 | "watch": "node_modules/.bin/webpack --progress --colors --watch" 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /docs/examples/todomvc/pure-components.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VoliJS/React-Type-R/8d157b9afd76850f680c677d62437e4516191b77/docs/examples/todomvc/pure-components.jpg -------------------------------------------------------------------------------- /docs/examples/todomvc/webpack.config.js: -------------------------------------------------------------------------------- 1 | var webpack = require( 'webpack' ), 2 | path = require( 'path' ); 3 | 4 | var config = { 5 | entry : { 6 | app : './js/main.jsx' 7 | }, 8 | 9 | output : { 10 | // export itself to a global var 11 | path : __dirname + '/dist', 12 | publicPath : '/dist/', 13 | filename : '[name].js' 14 | }, 15 | 16 | devtool : 'source-map', 17 | 18 | resolve : { 19 | modules : [ 'node_modules', 'src' ], 20 | }, 21 | 22 | module : { 23 | rules : [ 24 | { 25 | test : /\.css$/, 26 | use : [ 27 | { 28 | loader: "style-loader" 29 | }, 30 | { 31 | loader: "css-loader", 32 | options: { 33 | modules: true 34 | } 35 | } 36 | ] 37 | }, 38 | { 39 | test : /\.jsx?$/, 40 | exclude : /(node_modules|lib)/, 41 | loader : 'babel-loader' 42 | }, 43 | { 44 | test: /\.js$/, 45 | use: ["source-map-loader"], 46 | enforce: "pre" 47 | } 48 | ] 49 | } 50 | }; 51 | 52 | module.exports = config; -------------------------------------------------------------------------------- /docs/examples/userslist/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets":["react", ["es2015", {"loose": true}] ], 3 | "plugins":[ 4 | "transform-decorators-legacy", 5 | "transform-object-rest-spread", 6 | "add-module-exports", 7 | "transform-class-properties" 8 | ], 9 | 10 | "env": { 11 | "production": { 12 | "plugins": [ 13 | "transform-react-constant-elements", 14 | "transform-react-inline-elements" 15 | ] 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /docs/examples/userslist/README.md: -------------------------------------------------------------------------------- 1 | # UsersList Example 2 | 3 | Here's the UsersList application example, written originally for NestedLink. 4 | 5 | It's changed to use NestedReact. Feel the difference. 6 | 7 | NestedLink data binding is so powerful that there are no any difference 8 | in size, so expressiveness is roughly the same. 9 | 10 | But. Check out how much less magical NestedReact solution feels - compare the code. 11 | 12 | In fact, there's an incredible amount of dirty magic involved, 13 | just to make you feel that there are no any magic at all :). 14 | 15 | That's NestedReact. Relax, and write in natural way, no tricks are required. 16 | -------------------------------------------------------------------------------- /docs/examples/userslist/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | NestedReact • TodoMVC 7 | 8 | 9 | 10 |
    11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /docs/examples/userslist/main.css: -------------------------------------------------------------------------------- 1 | .invalid { 2 | border-color: red; 3 | } 4 | 5 | .invalid.required { 6 | border-color: yellow; 7 | } 8 | 9 | .checkbox,.radio { 10 | margin: 3px; 11 | display: inline-block; 12 | width: 10px; 13 | height : 10px; 14 | border: solid; 15 | border-width: 1px; 16 | } 17 | 18 | .selected { 19 | background-color: black; 20 | } 21 | 22 | label { 23 | display: block; 24 | margin: 5px; 25 | } 26 | 27 | input { 28 | margin: 3px; 29 | } 30 | 31 | 32 | .users-row>div { 33 | display: inline-block; 34 | width : 15em; 35 | } 36 | 37 | .validation-error { 38 | display: inline-block; 39 | color: red; 40 | } 41 | 42 | label>div { 43 | display: inline-block; 44 | } 45 | -------------------------------------------------------------------------------- /docs/examples/userslist/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "dependencies": { 4 | "todomvc-app-css": "^2.0.0", 5 | "todomvc-common": "^1.0.0" 6 | }, 7 | "devDependencies": { 8 | "babel-cli": "*", 9 | "babel-core": "*", 10 | "babel-loader": "*", 11 | "babel-plugin-add-module-exports": "*", 12 | "babel-plugin-transform-class-properties": "*", 13 | "babel-plugin-transform-decorators-legacy": "*", 14 | "babel-plugin-transform-object-rest-spread": "*", 15 | "babel-plugin-transform-react-constant-elements": "*", 16 | "babel-plugin-transform-react-inline-elements": "*", 17 | "babel-preset-es2015": "*", 18 | "babel-preset-react": "*", 19 | "babel-runtime": "*", 20 | "classnames": "*", 21 | "css-loader": "*", 22 | "prop-types": "*", 23 | "react": "*", 24 | "react-dom": "*", 25 | "react-modal": "^3.1.2", 26 | "react-mvx": "^2.0.0-rc900", 27 | "source-map-loader": "^0.2.3", 28 | "style-loader": "*", 29 | "type-r": "^2.0.1", 30 | "webpack": "^3.8.1" 31 | }, 32 | "scripts": { 33 | "test": "echo \"Error: no test specified\" && exit 1", 34 | "build": "node_modules/.bin/webpack", 35 | "watch": "node_modules/.bin/webpack --progress --colors --watch" 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /docs/examples/userslist/webpack.config.js: -------------------------------------------------------------------------------- 1 | var webpack = require( 'webpack' ), 2 | path = require( 'path' ); 3 | 4 | var config = { 5 | entry : { 6 | app : './main.jsx' 7 | }, 8 | 9 | output : { 10 | // export itself to a global var 11 | path : __dirname + '/dist', 12 | publicPath : '/dist/', 13 | filename : '[name].js' 14 | }, 15 | 16 | devtool : 'source-map', 17 | 18 | resolve : { 19 | modules : [ 'node_modules', 'src' ], 20 | }, 21 | 22 | module : { 23 | rules : [ 24 | { 25 | test : /\.css$/, 26 | use : [ 27 | { 28 | loader: "style-loader" 29 | }, 30 | { 31 | loader: "css-loader", 32 | options: { 33 | modules: true 34 | } 35 | } 36 | ] 37 | }, 38 | { 39 | test : /\.jsx?$/, 40 | exclude : /(node_modules|lib)/, 41 | loader : 'babel-loader' 42 | }, 43 | { 44 | test: /\.js$/, 45 | use: ["source-map-loader"], 46 | enforce: "pre" 47 | } 48 | ] 49 | } 50 | }; 51 | 52 | module.exports = config; -------------------------------------------------------------------------------- /docs/images/logo-dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VoliJS/React-Type-R/8d157b9afd76850f680c677d62437e4516191b77/docs/images/logo-dark.png -------------------------------------------------------------------------------- /docs/images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VoliJS/React-Type-R/8d157b9afd76850f680c677d62437e4516191b77/docs/images/logo.png -------------------------------------------------------------------------------- /docs/images/navbar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VoliJS/React-Type-R/8d157b9afd76850f680c677d62437e4516191b77/docs/images/navbar.png -------------------------------------------------------------------------------- /docs/images/overview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VoliJS/React-Type-R/8d157b9afd76850f680c677d62437e4516191b77/docs/images/overview.png -------------------------------------------------------------------------------- /docs/images/volicon_verizon_dm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VoliJS/React-Type-R/8d157b9afd76850f680c677d62437e4516191b77/docs/images/volicon_verizon_dm.png -------------------------------------------------------------------------------- /docs/lib/fonts/icomoon.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VoliJS/React-Type-R/8d157b9afd76850f680c677d62437e4516191b77/docs/lib/fonts/icomoon.eot -------------------------------------------------------------------------------- /docs/lib/fonts/icomoon.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VoliJS/React-Type-R/8d157b9afd76850f680c677d62437e4516191b77/docs/lib/fonts/icomoon.ttf -------------------------------------------------------------------------------- /docs/lib/fonts/icomoon.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VoliJS/React-Type-R/8d157b9afd76850f680c677d62437e4516191b77/docs/lib/fonts/icomoon.woff -------------------------------------------------------------------------------- /docs/lib/fonts/slate.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VoliJS/React-Type-R/8d157b9afd76850f680c677d62437e4516191b77/docs/lib/fonts/slate.eot -------------------------------------------------------------------------------- /docs/lib/fonts/slate.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Generated by IcoMoon 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /docs/lib/fonts/slate.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VoliJS/React-Type-R/8d157b9afd76850f680c677d62437e4516191b77/docs/lib/fonts/slate.ttf -------------------------------------------------------------------------------- /docs/lib/fonts/slate.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VoliJS/React-Type-R/8d157b9afd76850f680c677d62437e4516191b77/docs/lib/fonts/slate.woff -------------------------------------------------------------------------------- /docs/lib/fonts/slate.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VoliJS/React-Type-R/8d157b9afd76850f680c677d62437e4516191b77/docs/lib/fonts/slate.woff2 -------------------------------------------------------------------------------- /docs/lib/javascripts/all_nosearch.js: -------------------------------------------------------------------------------- 1 | //= require ./lib/_energize 2 | //= require ./app/_lang 3 | //= require ./app/_toc 4 | -------------------------------------------------------------------------------- /docs/lib/javascripts/app/_search.js: -------------------------------------------------------------------------------- 1 | //= require ../lib/_lunr 2 | //= require ../lib/_jquery.highlight 3 | (function () { 4 | 'use strict'; 5 | 6 | var content, searchResults; 7 | var highlightOpts = { element: 'span', className: 'search-highlight' }; 8 | 9 | var index = new lunr.Index(); 10 | 11 | index.ref('id'); 12 | index.field('title', { boost: 10 }); 13 | index.field('body'); 14 | index.pipeline.add(lunr.trimmer, lunr.stopWordFilter); 15 | 16 | $(populate); 17 | $(bind); 18 | 19 | function populate() { 20 | $('h1, h2').each(function() { 21 | var title = $(this); 22 | var body = title.nextUntil('h1, h2'); 23 | index.add({ 24 | id: title.prop('id'), 25 | title: title.text(), 26 | body: body.text() 27 | }); 28 | }); 29 | } 30 | 31 | function bind() { 32 | content = $('.content'); 33 | searchResults = $('.search-results'); 34 | 35 | $('#input-search').on('keyup', search); 36 | } 37 | 38 | function search(event) { 39 | unhighlight(); 40 | searchResults.addClass('visible'); 41 | 42 | // ESC clears the field 43 | if (event.keyCode === 27) this.value = ''; 44 | 45 | if (this.value) { 46 | var results = index.search(this.value).filter(function(r) { 47 | return r.score > 0.0001; 48 | }); 49 | 50 | if (results.length) { 51 | searchResults.empty(); 52 | $.each(results, function (index, result) { 53 | var elem = document.getElementById(result.ref); 54 | searchResults.append("
  • " + $(elem).text() + "
  • "); 55 | }); 56 | highlight.call(this); 57 | } else { 58 | searchResults.html('
  • '); 59 | $('.search-results li').text('No Results Found for "' + this.value + '"'); 60 | } 61 | } else { 62 | unhighlight(); 63 | searchResults.removeClass('visible'); 64 | } 65 | } 66 | 67 | function highlight() { 68 | if (this.value) content.highlight(this.value, highlightOpts); 69 | } 70 | 71 | function unhighlight() { 72 | content.unhighlight(highlightOpts); 73 | } 74 | })(); 75 | -------------------------------------------------------------------------------- /docs/lib/javascripts/app/_toc.js: -------------------------------------------------------------------------------- 1 | //= require ../lib/_jquery_ui 2 | //= require ../lib/_jquery.tocify 3 | //= require ../lib/_imagesloaded.min 4 | (function (global) { 5 | 'use strict'; 6 | 7 | var closeToc = function() { 8 | $(".tocify-wrapper").removeClass('open'); 9 | $("#nav-button").removeClass('open'); 10 | }; 11 | 12 | var makeToc = function() { 13 | global.toc = $("#toc").tocify({ 14 | selectors: 'h1, h2, h3', 15 | extendPage: false, 16 | theme: 'none', 17 | smoothScroll: false, 18 | showEffectSpeed: 0, 19 | hideEffectSpeed: 180, 20 | ignoreSelector: '.toc-ignore', 21 | highlightOffset: 60, 22 | scrollTo: -1, 23 | scrollHistory: true, 24 | hashGenerator: function (text, element) { 25 | return element.prop('id'); 26 | } 27 | }).data('toc-tocify'); 28 | 29 | $("#nav-button").click(function() { 30 | $(".tocify-wrapper").toggleClass('open'); 31 | $("#nav-button").toggleClass('open'); 32 | return false; 33 | }); 34 | 35 | $(".page-wrapper").click(closeToc); 36 | $(".tocify-item").click(closeToc); 37 | }; 38 | 39 | // Hack to make already open sections to start opened, 40 | // instead of displaying an ugly animation 41 | function animate() { 42 | setTimeout(function() { 43 | toc.setOption('showEffectSpeed', 180); 44 | }, 50); 45 | } 46 | 47 | $(function() { 48 | makeToc(); 49 | animate(); 50 | $('.content').imagesLoaded( function() { 51 | global.toc.calculateHeights(); 52 | }); 53 | }); 54 | })(window); 55 | -------------------------------------------------------------------------------- /docs/lib/layouts/layout.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | {{title}} 8 | 9 | 10 | 11 | 12 | 13 | 14 | 32 | 33 | 34 | 35 | 44 | 45 | 46 | 47 | 48 | 49 | NAV 50 | 51 | 52 | 53 |
    54 |
    55 | 56 |
    57 |
    React-MVx 2.0
    58 |
    React MVVM framework
    59 |
    60 | 61 |
    62 |
    63 | {{#each language_tabs}} 64 | {{this.text}} 65 | {{/each}} 66 |
    67 | 70 |
      71 |
      72 |
      73 | 78 |
      79 |
      80 |
      81 | {{{html content}}} 82 |
      83 |
      84 | 85 | 86 | -------------------------------------------------------------------------------- /docs/lib/stylesheets/default.css: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Orginal Style from ethanschoonover.com/solarized (c) Jeremy Hull 4 | 5 | */ 6 | 7 | .hljs { 8 | display: block; 9 | overflow-x: auto; 10 | padding: 0.5em; 11 | background: #002b36; 12 | color: #839496; 13 | -webkit-text-size-adjust: none; 14 | } 15 | 16 | .hljs-comment, 17 | .diff .hljs-header, 18 | .hljs-doctype, 19 | .hljs-pi, 20 | .lisp .hljs-string { 21 | color: #586e75; 22 | } 23 | 24 | /* Solarized Green */ 25 | .hljs-keyword, 26 | .hljs-winutils, 27 | .method, 28 | .hljs-addition, 29 | .css .hljs-tag, 30 | .hljs-request, 31 | .hljs-status, 32 | .nginx .hljs-title { 33 | color: #859900; 34 | } 35 | 36 | /* Solarized Cyan */ 37 | .hljs-number, 38 | .hljs-command, 39 | .hljs-string, 40 | .hljs-tag .hljs-value, 41 | .hljs-rule .hljs-value, 42 | .hljs-doctag, 43 | .tex .hljs-formula, 44 | .hljs-regexp, 45 | .hljs-hexcolor, 46 | .hljs-link_url { 47 | color: #2aa198; 48 | } 49 | 50 | /* Solarized Blue */ 51 | .hljs-title, 52 | .hljs-localvars, 53 | .hljs-chunk, 54 | .hljs-decorator, 55 | .hljs-built_in, 56 | .hljs-identifier, 57 | .vhdl .hljs-literal, 58 | .hljs-id, 59 | .css .hljs-function, 60 | .hljs-name { 61 | color: #268bd2; 62 | } 63 | 64 | /* Solarized Yellow */ 65 | .hljs-attribute, 66 | .hljs-variable, 67 | .lisp .hljs-body, 68 | .smalltalk .hljs-number, 69 | .hljs-constant, 70 | .hljs-class .hljs-title, 71 | .hljs-parent, 72 | .hljs-type, 73 | .hljs-link_reference { 74 | color: #b58900; 75 | } 76 | 77 | /* Solarized Orange */ 78 | .hljs-preprocessor, 79 | .hljs-preprocessor .hljs-keyword, 80 | .hljs-pragma, 81 | .hljs-shebang, 82 | .hljs-symbol, 83 | .hljs-symbol .hljs-string, 84 | .diff .hljs-change, 85 | .hljs-special, 86 | .hljs-attr_selector, 87 | .hljs-subst, 88 | .hljs-cdata, 89 | .css .hljs-pseudo, 90 | .hljs-header { 91 | color: #cb4b16; 92 | } 93 | 94 | /* Solarized Red */ 95 | .hljs-deletion, 96 | .hljs-important { 97 | color: #dc322f; 98 | } 99 | 100 | /* Solarized Violet */ 101 | .hljs-link_label { 102 | color: #6c71c4; 103 | } 104 | 105 | .tex .hljs-formula { 106 | background: #073642; 107 | } -------------------------------------------------------------------------------- /docs/lib/stylesheets/icon-font.css: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family: 'icomoon'; 3 | src: url("../fonts/icomoon.eot"); 4 | src: url("../fonts/icomoon.eot?#iefix") format("embedded-opentype"), url("../fonts/icomoon.ttf") format("truetype"), url("../fonts/icomoon.woff") format("woff"), url("../fonts/icomoon.svg#icomoon") format("svg"); 5 | font-weight: normal; 6 | font-style: normal 7 | } -------------------------------------------------------------------------------- /docs/lib/stylesheets/normalize.css: -------------------------------------------------------------------------------- 1 | /*! normalize.css v2.0.1 | MIT License | git.io/normalize */ 2 | article, aside, details, figcaption, figure, footer, header, hgroup, nav, section, summary { 3 | display: block 4 | } 5 | 6 | audio, canvas, video { 7 | display: inline-block 8 | } 9 | 10 | audio:not([controls]) { 11 | display: none; 12 | height: 0 13 | } 14 | 15 | [hidden] { 16 | display: none 17 | } 18 | 19 | html { 20 | font-family: sans-serif; 21 | -webkit-text-size-adjust: 100%; 22 | -ms-text-size-adjust: 100% 23 | } 24 | 25 | body { 26 | margin: 0 27 | } 28 | 29 | a:focus { 30 | outline: thin dotted 31 | } 32 | 33 | a:active, a:hover { 34 | outline: 0 35 | } 36 | 37 | h1 { 38 | font-size: 2em 39 | } 40 | 41 | abbr[title] { 42 | border-bottom: 1px dotted 43 | } 44 | 45 | b, strong { 46 | font-weight: bold 47 | } 48 | 49 | dfn { 50 | font-style: italic 51 | } 52 | 53 | mark { 54 | background: #ff0; 55 | color: #000 56 | } 57 | 58 | code, kbd, pre, samp { 59 | font-family: monospace, serif; 60 | font-size: 1em 61 | } 62 | 63 | pre { 64 | white-space: pre; 65 | white-space: pre-wrap; 66 | word-wrap: break-word 67 | } 68 | 69 | q { 70 | quotes: "\201C" "\201D" "\2018" "\2019" 71 | } 72 | 73 | small { 74 | font-size: 80% 75 | } 76 | 77 | sub, sup { 78 | font-size: 75%; 79 | line-height: 0; 80 | position: relative; 81 | vertical-align: baseline 82 | } 83 | 84 | sup { 85 | top: -0.5em 86 | } 87 | 88 | sub { 89 | bottom: -0.25em 90 | } 91 | 92 | img { 93 | border: 0 94 | } 95 | 96 | svg:not(:root) { 97 | overflow: hidden 98 | } 99 | 100 | figure { 101 | margin: 0 102 | } 103 | 104 | fieldset { 105 | border: 1px solid #c0c0c0; 106 | margin: 0 2px; 107 | padding: 0.35em 0.625em 0.75em 108 | } 109 | 110 | legend { 111 | border: 0; 112 | padding: 0 113 | } 114 | 115 | button, input, select, textarea { 116 | font-family: inherit; 117 | font-size: 100%; 118 | margin: 0 119 | } 120 | 121 | button, input { 122 | line-height: normal 123 | } 124 | 125 | button, html input[type="button"], input[type="reset"], input[type="submit"] { 126 | -webkit-appearance: button; 127 | cursor: pointer 128 | } 129 | 130 | button[disabled], input[disabled] { 131 | cursor: default 132 | } 133 | 134 | input[type="checkbox"], input[type="radio"] { 135 | box-sizing: border-box; 136 | padding: 0 137 | } 138 | 139 | input[type="search"] { 140 | -webkit-appearance: textfield; 141 | -moz-box-sizing: content-box; 142 | -webkit-box-sizing: content-box; 143 | box-sizing: content-box 144 | } 145 | 146 | input[type="search"]::-webkit-search-cancel-button, input[type="search"]::-webkit-search-decoration { 147 | -webkit-appearance: none 148 | } 149 | 150 | button::-moz-focus-inner, input::-moz-focus-inner { 151 | border: 0; 152 | padding: 0 153 | } 154 | 155 | textarea { 156 | overflow: auto; 157 | vertical-align: top 158 | } 159 | 160 | table { 161 | border-collapse: collapse; 162 | border-spacing: 0 163 | } -------------------------------------------------------------------------------- /docs/lib/stylesheets/syntax.css: -------------------------------------------------------------------------------- 1 | .highlight table td { 2 | padding: 5px 3 | } 4 | 5 | .highlight table pre { 6 | margin: 0 7 | } 8 | 9 | .highlight, .highlight .w { 10 | color: #f8f8f2; 11 | background-color: #272822 12 | } 13 | 14 | .highlight .err { 15 | color: #151515; 16 | background-color: #ac4142 17 | } 18 | 19 | .highlight .c, .highlight .cd, .highlight .cm, .highlight .c1, .highlight .cs { 20 | color: #505050 21 | } 22 | 23 | .highlight .cp { 24 | color: #f4bf75 25 | } 26 | 27 | .highlight .nt { 28 | color: #f4bf75 29 | } 30 | 31 | .highlight .o, .highlight .ow { 32 | color: #d0d0d0 33 | } 34 | 35 | .highlight .p, .highlight .pi { 36 | color: #d0d0d0 37 | } 38 | 39 | .highlight .gi { 40 | color: #90a959 41 | } 42 | 43 | .highlight .gd { 44 | color: #ac4142 45 | } 46 | 47 | .highlight .gh { 48 | color: #6a9fb5; 49 | background-color: #151515; 50 | font-weight: bold 51 | } 52 | 53 | .highlight .k, .highlight .kn, .highlight .kp, .highlight .kr, .highlight .kv { 54 | color: #aa759f 55 | } 56 | 57 | .highlight .kc { 58 | color: #d28445 59 | } 60 | 61 | .highlight .kt { 62 | color: #d28445 63 | } 64 | 65 | .highlight .kd { 66 | color: #d28445 67 | } 68 | 69 | .highlight .s, .highlight .sb, .highlight .sc, .highlight .sd, .highlight .s2, .highlight .sh, .highlight .sx, .highlight .s1 { 70 | color: #90a959 71 | } 72 | 73 | .highlight .sr { 74 | color: #75b5aa 75 | } 76 | 77 | .highlight .si { 78 | color: #8f5536 79 | } 80 | 81 | .highlight .se { 82 | color: #8f5536 83 | } 84 | 85 | .highlight .nn { 86 | color: #f4bf75 87 | } 88 | 89 | .highlight .nc { 90 | color: #f4bf75 91 | } 92 | 93 | .highlight .no { 94 | color: #f4bf75 95 | } 96 | 97 | .highlight .na { 98 | color: #6a9fb5 99 | } 100 | 101 | .highlight .m, .highlight .mf, .highlight .mh, .highlight .mi, .highlight .il, .highlight .mo, .highlight .mb, .highlight .mx { 102 | color: #90a959 103 | } 104 | 105 | .highlight .ss { 106 | color: #90a959 107 | } 108 | 109 | .highlight .c, .highlight .cm, .highlight .c1, .highlight .cs { 110 | color: #909090 111 | } 112 | 113 | .highlight, .highlight .w { 114 | background-color: #292929 115 | } -------------------------------------------------------------------------------- /docs/lib/stylesheets/variables.css: -------------------------------------------------------------------------------- 1 | .context h4 { 2 | font-size: 12px; 3 | background-color: #ebf3f7; 4 | text-transform: uppercase; 5 | font-family: sans-serif; 6 | } 7 | -------------------------------------------------------------------------------- /examples/babel-boilerplate/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets":["react", ["es2015", {"loose": true}] ], 3 | "plugins":[ 4 | "transform-decorators-legacy", 5 | "transform-object-rest-spread", 6 | "add-module-exports", 7 | "transform-class-properties" 8 | ], 9 | 10 | "env": { 11 | "production": { 12 | "plugins": [ 13 | "transform-react-constant-elements", 14 | "transform-react-inline-elements" 15 | ] 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /examples/babel-boilerplate/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Webpack Babel ReactMVC Boilerplate 7 | 8 | 9 | 10 |
      11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /examples/babel-boilerplate/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "dependencies": {}, 4 | "devDependencies": { 5 | "babel-cli": "*", 6 | "babel-core": "*", 7 | "babel-loader": "*", 8 | "babel-plugin-add-module-exports": "*", 9 | "babel-plugin-transform-class-properties": "*", 10 | "babel-plugin-transform-decorators-legacy": "*", 11 | "babel-plugin-transform-object-rest-spread": "*", 12 | "babel-plugin-transform-react-constant-elements": "*", 13 | "babel-plugin-transform-react-inline-elements": "*", 14 | "babel-preset-es2015": "*", 15 | "babel-preset-react": "*", 16 | "babel-runtime": "*", 17 | "css-loader": "*", 18 | "prop-types": "*", 19 | "react": "^16.1.1", 20 | "react-dom": "^16.1.1", 21 | "react-mvx": "^2.0.0-rc900", 22 | "source-map-loader": "*", 23 | "style-loader": "*", 24 | "type-r": "^2.0.0", 25 | "webpack": "^3.8.1" 26 | }, 27 | "scripts": { 28 | "test": "echo \"Error: no test specified\" && exit 1", 29 | "build": "node_modules/.bin/webpack", 30 | "watch": "node_modules/.bin/webpack --progress --colors --watch" 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /examples/babel-boilerplate/src/index.jsx: -------------------------------------------------------------------------------- 1 | import React, { define } from 'react-mvx' 2 | import ReactDOM from 'react-dom' 3 | import { Record } from 'type-r' 4 | 5 | import './styles.css' 6 | 7 | @define class Item extends Record { 8 | static attributes = { 9 | text : String 10 | } 11 | } 12 | 13 | @define class Application extends React.Component { 14 | static state = { 15 | items : Item.Collection 16 | }; 17 | 18 | render(){ 19 | const { state } = this; 20 | 21 | return ( 22 |
      23 | 26 | 27 | { state.items.map( item => ( 28 | 29 | ))} 30 |
      31 | ); 32 | } 33 | } 34 | 35 | const ItemView = ({ item }) => ( 36 | 37 | ); 38 | 39 | ReactDOM.render( , document.getElementById( 'react-application' ) ); -------------------------------------------------------------------------------- /examples/babel-boilerplate/src/styles.css: -------------------------------------------------------------------------------- 1 | input { 2 | margin : 1em; 3 | border-radius: 2px; 4 | } -------------------------------------------------------------------------------- /examples/babel-boilerplate/webpack.config.js: -------------------------------------------------------------------------------- 1 | var webpack = require( 'webpack' ), 2 | path = require( 'path' ); 3 | 4 | var config = { 5 | entry : { 6 | app : './src/index.jsx' 7 | }, 8 | 9 | output : { 10 | // export itself to a global var 11 | path : __dirname + '/dist', 12 | publicPath : '/dist/', 13 | filename : '[name].js' 14 | }, 15 | 16 | devtool : 'source-map', 17 | 18 | resolve : { 19 | modules : [ 'node_modules', 'src' ] 20 | }, 21 | 22 | module : { 23 | rules : [ 24 | { 25 | test : /\.css$/, 26 | use : [ 27 | { 28 | loader: "style-loader" 29 | }, 30 | { 31 | loader: "css-loader", 32 | options: { 33 | modules: true 34 | } 35 | } 36 | ] 37 | }, 38 | { 39 | test : /\.jsx?$/, 40 | exclude : /(node_modules|lib)/, 41 | loader : 'babel-loader' 42 | }, 43 | { 44 | test: /\.js$/, 45 | use: ["source-map-loader"], 46 | enforce: "pre" 47 | } 48 | ] 49 | } 50 | }; 51 | 52 | module.exports = config; -------------------------------------------------------------------------------- /examples/checklistTree/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets":["react", ["es2015", {"loose": true}] ], 3 | "plugins":[ 4 | "transform-decorators-legacy", 5 | "transform-object-rest-spread", 6 | "add-module-exports", 7 | "transform-class-properties" 8 | ], 9 | 10 | "env": { 11 | "production": { 12 | "plugins": [ 13 | "transform-react-constant-elements", 14 | "transform-react-inline-elements" 15 | ] 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /examples/checklistTree/README.md: -------------------------------------------------------------------------------- 1 | # Hiearchical Checklist. 2 | 3 | Classic hierarchical checklist example, which you could often see in installers. 4 | This is checklist with a rule. Item is checked, if all children are checked. 5 | 6 | ![Screenshot](./screenshot.png) 7 | 8 | 59 SLOC for jsx components, 28 for the model definition. 9 | 10 | This example demonstrates unidirectional data flow with mutable state and pure render optimisation. And different features of the NestedReact state management. 11 | 12 | - Declarative definition of mutable observable state. `static state = { element : ConstructorFunction }`. 13 | - Two-way data binding with advanced value links. `const links = model.linkAll( 'checked', 'name' )`. 14 | - Simplified React props spec. `static props = { name : ConstructorFunction, name2 : Constructor.value( defaultValue ) }` 15 | - Declarative `pureRender` for mutable data and value links. `static pureRender = true`. 16 | - Recursive state definitions. Model can mention itself in its attribute specs, thus, it's possible to define 17 | (potentially) infinite recursive data structures. 18 | - Change watchers. It's possible to attach 'watchers' to any attribute, which would be called on value change. 19 | - Transactional updates. Any change made to the model from the watcher is being added to the current transaction, 20 | resulting in the single 'change' event per transaction. Look at the render count in the example - you've got one 21 | render no matter how many checkboxes was flipped. 22 | 23 | 24 | -------------------------------------------------------------------------------- /examples/checklistTree/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | React-R Checklist Tree 7 | 8 | 9 | 10 |
      11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /examples/checklistTree/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "dependencies": {}, 4 | "devDependencies": { 5 | "babel-cli": "*", 6 | "babel-core": "*", 7 | "babel-loader": "*", 8 | "babel-plugin-add-module-exports": "*", 9 | "babel-plugin-transform-class-properties": "*", 10 | "babel-plugin-transform-decorators-legacy": "*", 11 | "babel-plugin-transform-object-rest-spread": "*", 12 | "babel-plugin-transform-react-constant-elements": "*", 13 | "babel-plugin-transform-react-inline-elements": "*", 14 | "babel-preset-es2015": "*", 15 | "babel-preset-react": "*", 16 | "babel-runtime": "*", 17 | "classnames": "*", 18 | "css-loader": "*", 19 | "react-mvx": "^2.0.0-00", 20 | "react": "*", 21 | "react-dom": "*", 22 | "prop-types": "*", 23 | "source-map-loader": "*", 24 | "style-loader": "*", 25 | "type-r": "^2.0.1", 26 | "webpack": "^3.8.1" 27 | }, 28 | "scripts": { 29 | "test": "echo \"Error: no test specified\" && exit 1", 30 | "build": "node_modules/.bin/webpack", 31 | "watch": "node_modules/.bin/webpack --progress --colors --watch" 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /examples/checklistTree/screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VoliJS/React-Type-R/8d157b9afd76850f680c677d62437e4516191b77/examples/checklistTree/screenshot.png -------------------------------------------------------------------------------- /examples/checklistTree/src/model.js: -------------------------------------------------------------------------------- 1 | // Data objects are defined in nestedtypes package. 2 | import { Record, define } from 'type-r' 3 | 4 | @define class Checklist extends Record.Collection { 5 | get checked(){ return this.every( item => item.checked ); } 6 | set checked( checked ){ 7 | if( checked !== this.checked ){ 8 | this.updateEach( item => { item.checked = checked } ); 9 | } 10 | } 11 | } 12 | 13 | @define 14 | export class ChecklistItem extends Record { 15 | static Collection = Checklist; 16 | 17 | static attributes = { // <- Here's an attribute spec. Think of it as a type spec. 18 | name : String, 19 | created : Date, 20 | checked : Boolean.has.watcher( 'checkedWatcher' ), 21 | subitems : Checklist.has.watcher( 'subitemsWatcher' ) 22 | }; 23 | 24 | checkedWatcher( checked ){ this.subitems.checked = checked; } 25 | 26 | subitemsWatcher( subitems ){ 27 | if( subitems.length ){ 28 | this.checked = this.subitems.checked; 29 | } 30 | } 31 | 32 | remove(){ this.collection.remove( this ); } 33 | } -------------------------------------------------------------------------------- /examples/checklistTree/src/styles.css: -------------------------------------------------------------------------------- 1 | .checkbox { 2 | display: inline-block; 3 | width: 10px; 4 | height: 10px; 5 | border: solid; 6 | border-width: 1px; 7 | margin: 3px; 8 | vertical-align: middle; 9 | } 10 | 11 | .children { 12 | margin-left: 1em; 13 | } 14 | 15 | .checkbox.selected { 16 | background-color: black; 17 | } 18 | 19 | input { 20 | border: none; 21 | border-bottom: solid; 22 | border-width: 1px; 23 | margin: 3px; 24 | margin-left : 10px; 25 | } 26 | 27 | input:focus { 28 | outline: none; 29 | border-width: 2px; 30 | } 31 | 32 | button { 33 | border-radius: 3px; 34 | background-color: white; 35 | } 36 | 37 | .created { 38 | margin : 3px; 39 | font-size: 11px; 40 | } -------------------------------------------------------------------------------- /examples/checklistTree/webpack.config.js: -------------------------------------------------------------------------------- 1 | var webpack = require( 'webpack' ), 2 | path = require( 'path' ); 3 | 4 | var config = { 5 | entry : { 6 | app : './src/index.jsx' 7 | }, 8 | 9 | output : { 10 | // export itself to a global var 11 | path : __dirname + '/dist', 12 | publicPath : '/dist/', 13 | filename : '[name].js' 14 | }, 15 | 16 | devtool : 'source-map', 17 | 18 | resolve : { 19 | modules : [ 'node_modules', 'src' ], 20 | // alias : { //use `npm run deploy:examples` in main project 21 | // 'react-mvx' : path.resolve(__dirname, '../..' ) 22 | // } 23 | }, 24 | 25 | module : { 26 | rules : [ 27 | { 28 | test : /\.css$/, 29 | use : [ 30 | { 31 | loader: "style-loader" 32 | }, 33 | { 34 | loader: "css-loader" 35 | } 36 | ] 37 | }, 38 | { 39 | test : /\.jsx?$/, 40 | exclude : /(node_modules|lib)/, 41 | loader : 'babel-loader' 42 | }, 43 | { 44 | test: /\.js$/, 45 | use: ["source-map-loader"], 46 | enforce: "pre" 47 | } 48 | ] 49 | } 50 | }; 51 | 52 | module.exports = config; -------------------------------------------------------------------------------- /examples/flux-comparison/application.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VoliJS/React-Type-R/8d157b9afd76850f680c677d62437e4516191b77/examples/flux-comparison/application.png -------------------------------------------------------------------------------- /examples/flux-comparison/cart.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VoliJS/React-Type-R/8d157b9afd76850f680c677d62437e4516191b77/examples/flux-comparison/cart.png -------------------------------------------------------------------------------- /examples/flux-comparison/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | NestedReact Anti-Flux Sample 6 | 7 | 8 | 9 | 10 | 11 | 12 |
      13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /examples/flux-comparison/js/app.js: -------------------------------------------------------------------------------- 1 | import React from 'nestedreact' 2 | import App from './components/App.jsx' 3 | 4 | React.render( 5 | React.createElement( App, null ), 6 | document.getElementById( 'non-flux-app' ) 7 | ); 8 | -------------------------------------------------------------------------------- /examples/flux-comparison/js/components/App.jsx: -------------------------------------------------------------------------------- 1 | import React, { define } from 'react-mvx' 2 | 3 | import ProductsContainer from './ProductsContainer.jsx' 4 | import CartContainer from './CartContainer.jsx' 5 | 6 | import Cart from '../models/Cart' 7 | import Product from '../models/Product' 8 | 9 | @define 10 | export default class App extends React.Component { 11 | // Declare application's state 12 | // UI will be updated automatically on every state, 13 | // deep changes will be detected too. 14 | static state = { 15 | cart : Cart, 16 | products : Product.Collection 17 | } 18 | 19 | componentWillMount(){ 20 | // fetch data on application start... 21 | this.state.products.fetch(); 22 | } 23 | 24 | render(){ 25 | const { state } = this; 26 | return ( 27 |
      28 | state.cart.add( product ) }/> 30 | 31 | 32 |
      33 | ); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /examples/flux-comparison/js/components/CartContainer.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react-mvx' 2 | import CCart from '../../../common/components/Cart.jsx' 3 | 4 | const CartContainer = ( { cart } ) => ( 5 | cart.checkout() }/> // But likely for us, cart is not an array. 8 | ); 9 | 10 | export default CartContainer; 11 | -------------------------------------------------------------------------------- /examples/flux-comparison/js/components/ProductsContainer.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react-mvx' 2 | import CProductItem from '../../../common/components/ProductItem.jsx' 3 | import CProductsList from '../../../common/components/ProductsList.jsx' 4 | 5 | 6 | const ProductsContainer = ( { products, addToCart } ) =>( 7 | 8 | { products.map( product => ( 9 | 12 | ) )} 13 | 14 | ); 15 | 16 | export default ProductsContainer; 17 | -------------------------------------------------------------------------------- /examples/flux-comparison/js/models/Cart.js: -------------------------------------------------------------------------------- 1 | import { define, Collection } from 'type-r' 2 | import Product from './Product' 3 | import shop from '../../../common/api/shop' 4 | 5 | @define 6 | export default class Cart extends Collection { 7 | // Cart is a collection of products... 8 | model : Product, 9 | 10 | // ... which you can checkout. 11 | checkout(){ 12 | shop.buyProducts( this.toJSON(), () => this.reset() ); 13 | } 14 | } -------------------------------------------------------------------------------- /examples/flux-comparison/js/models/Product.js: -------------------------------------------------------------------------------- 1 | import { define, Record } from 'type-r' 2 | import shop from '../../../common/api/shop' 3 | 4 | @define 5 | export default class Product extends Record { 6 | static attributes = { 7 | image : String, 8 | title : String, 9 | price : Number, 10 | inventory : Number 11 | }; 12 | 13 | static collection = { 14 | fetch(){ 15 | shop.getProducts( products => this.reset( products, { parse : true } ) ); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /examples/flux-comparison/product.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VoliJS/React-Type-R/8d157b9afd76850f680c677d62437e4516191b77/examples/flux-comparison/product.png -------------------------------------------------------------------------------- /examples/flux-comparison/sloc-comparison.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VoliJS/React-Type-R/8d157b9afd76850f680c677d62437e4516191b77/examples/flux-comparison/sloc-comparison.png -------------------------------------------------------------------------------- /examples/flux-comparison/unidirectional-data-flow.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VoliJS/React-Type-R/8d157b9afd76850f680c677d62437e4516191b77/examples/flux-comparison/unidirectional-data-flow.jpg -------------------------------------------------------------------------------- /examples/todomvc/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets":["react", ["es2015", {"loose": true}] ], 3 | "plugins":[ 4 | "transform-decorators-legacy", 5 | "transform-object-rest-spread", 6 | "add-module-exports", 7 | "transform-class-properties" 8 | ], 9 | 10 | "env": { 11 | "production": { 12 | "plugins": [ 13 | "transform-react-constant-elements", 14 | "transform-react-inline-elements" 15 | ] 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /examples/todomvc/SLOC-comparison.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VoliJS/React-Type-R/8d157b9afd76850f680c677d62437e4516191b77/examples/todomvc/SLOC-comparison.jpg -------------------------------------------------------------------------------- /examples/todomvc/css/app.css: -------------------------------------------------------------------------------- 1 | .something { 2 | background: black; 3 | } 4 | -------------------------------------------------------------------------------- /examples/todomvc/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | NestedReact • TodoMVC 7 | 8 | 9 | 10 | 11 | 12 |
      13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /examples/todomvc/js/addtodo.jsx: -------------------------------------------------------------------------------- 1 | import React, { define } from 'react-mvx' 2 | 3 | @define 4 | export default class AddTodo extends React.Component { 5 | static props = { 6 | onEnter : Function.value( function(){} ) 7 | } 8 | 9 | static state = { 10 | desc : String 11 | } 12 | 13 | render(){ 14 | return ( 15 |
      16 |

      todos

      17 | 18 | this.onKeyDown( e ) } 23 | /> 24 |
      25 | ); 26 | } 27 | 28 | onKeyDown( { keyCode } ){ 29 | if( keyCode === 13 ){ 30 | let { state, props } = this; 31 | 32 | state.desc && props.onEnter( state.desc ); 33 | state.desc = ""; 34 | } 35 | } 36 | } -------------------------------------------------------------------------------- /examples/todomvc/js/filter.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react-mvx' 2 | 3 | const Filter = ( { count, filterLink, onClear } ) => ( 4 |
      5 | 6 | { count } item left 7 | 8 | 9 |
        10 | 12 | All 13 | 14 | 16 | Active 17 | 18 | 20 | Completed 21 | 22 |
      23 | 24 | 28 |
      29 | ); 30 | 31 | export default Filter; 32 | 33 | const Radio = ( { checkedLink, children, ...props } ) => ( 34 |
    • 35 | checkedLink.set( true ) } 37 | { ...props }> 38 | { children } 39 | 40 |
    • 41 | ); 42 | -------------------------------------------------------------------------------- /examples/todomvc/js/main.jsx: -------------------------------------------------------------------------------- 1 | import '../css/app.css' 2 | import React, { define } from 'react-mvx' 3 | import { Record } from 'type-r' 4 | import ReactDOM from 'react-dom' 5 | import {ToDo} from './model.js' 6 | import TodoList from './todolist.jsx' 7 | import Filter from './filter.jsx' 8 | import AddTodo from './addtodo.jsx' 9 | 10 | import { localStorageIO } from 'type-r/endpoints/localStorage' 11 | 12 | // Declare component state 13 | @define class AppState extends Record { 14 | static endpoint = localStorageIO( '/react-mvx/examples' ); 15 | 16 | static attributes = { 17 | id : 'todoMVC', 18 | todos : ToDo.Collection, 19 | filterDone : Boolean.value( null ) // null | true | false, initialized with null. 20 | } 21 | } 22 | 23 | @define class App extends React.Component { 24 | static State = AppState; 25 | 26 | componentWillMount(){ 27 | this.state.fetch(); 28 | window.onunload = () => this.state.save(); 29 | } 30 | 31 | render(){ 32 | const { todos, filterDone } = this.state, 33 | hasTodos = Boolean( todos.length ); 34 | 35 | return ( 36 |
      37 |
      38 | todos.add({ desc : desc }) }/> 39 | 40 | { hasTodos && } 42 | 43 | { hasTodos && todos.clearCompleted() } 46 | />} 47 |
      48 | 49 | 55 |
      56 | ); 57 | } 58 | } 59 | 60 | ReactDOM.render( , document.getElementById( 'app-mount-root' ) ); 61 | 62 | -------------------------------------------------------------------------------- /examples/todomvc/js/model.js: -------------------------------------------------------------------------------- 1 | import { Record, define } from 'type-r' 2 | 3 | @define class ToDoCollection extends Record.Collection { 4 | clearCompleted(){ 5 | this.remove( this.filter( todo => todo.done ) ); 6 | } 7 | 8 | get allDone(){ 9 | return this.every( todo => todo.done ); 10 | } 11 | 12 | set allDone( val ){ 13 | this.updateEach( todo => todo.done = val ); 14 | } 15 | 16 | get activeCount(){ 17 | return this.filter( todo => !todo.done ).length; 18 | } 19 | } 20 | 21 | @define 22 | export class ToDo extends Record { 23 | static Collection = ToDoCollection; 24 | static attributes = { 25 | done : Boolean, 26 | desc : String 27 | } 28 | 29 | remove(){ 30 | this.collection.remove( this ); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /examples/todomvc/js/todolist.jsx: -------------------------------------------------------------------------------- 1 | import React, { define } from 'react-mvx' 2 | import cx from 'classnames' 3 | import { ToDo } from './model' 4 | 5 | @define export default 6 | class TodoList extends React.Component { 7 | static props = { 8 | todos : ToDo.Collection, 9 | filterDone : Boolean 10 | } 11 | 12 | static state = { 13 | editing : ToDo.from( '^props.todos' ) 14 | } 15 | 16 | static pureRender = true 17 | 18 | render(){ 19 | const { todos, filterDone } = this.props, 20 | filtered = filterDone === null ? 21 | todos.models : 22 | todos.filter( todo => todo.done === filterDone ), 23 | editingLink = this.state.linkAt( 'editing' ); 24 | 25 | return ( 26 |
      27 | 31 | 32 | 35 | 36 |
        37 | { filtered.map( todo => ( 38 | 41 | ) )} 42 |
      43 |
      44 | ); 45 | } 46 | } 47 | 48 | function clearOnEnter( x, e ){ 49 | if( e.keyCode === 13 ) return null; 50 | } 51 | 52 | const TodoItem = ( { todo, editingLink } ) =>{ 53 | const editing = editingLink.value === todo, 54 | className = cx( { 55 | 'completed' : todo.done, 56 | 'view' : !todo.done, 57 | 'editing' : editing 58 | } ); 59 | 60 | return ( 61 |
    • 62 |
      63 | 66 | 67 | 70 | 71 |
      74 | 75 | { editing && null ) } 79 | onKeyDown={ editingLink.action( clearOnEnter ) }/> } 80 |
    • 81 | ); 82 | }; 83 | -------------------------------------------------------------------------------- /examples/todomvc/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "dependencies": { 4 | "todomvc-app-css": "^2.0.0", 5 | "todomvc-common": "^1.0.0" 6 | }, 7 | "devDependencies": { 8 | "babel-cli": "*", 9 | "babel-core": "*", 10 | "babel-loader": "*", 11 | "babel-plugin-add-module-exports": "*", 12 | "babel-plugin-transform-class-properties": "*", 13 | "babel-plugin-transform-decorators-legacy": "*", 14 | "babel-plugin-transform-object-rest-spread": "*", 15 | "babel-plugin-transform-react-constant-elements": "*", 16 | "babel-plugin-transform-react-inline-elements": "*", 17 | "babel-preset-es2015": "*", 18 | "babel-preset-react": "*", 19 | "babel-runtime": "*", 20 | "classnames": "*", 21 | "css-loader": "*", 22 | "react-modal": "^3.1.2", 23 | "source-map-loader": "^0.2.3", 24 | "react": "*", 25 | "react-dom": "*", 26 | "react-mvx": "^2.0.0-00", 27 | "prop-types": "*", 28 | "type-r": "^2.0.0-00", 29 | "style-loader": "*", 30 | "webpack": "^3.8.1" 31 | }, 32 | "scripts": { 33 | "test": "echo \"Error: no test specified\" && exit 1", 34 | "build": "node_modules/.bin/webpack", 35 | "watch": "node_modules/.bin/webpack --progress --colors --watch" 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /examples/todomvc/pure-components.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VoliJS/React-Type-R/8d157b9afd76850f680c677d62437e4516191b77/examples/todomvc/pure-components.jpg -------------------------------------------------------------------------------- /examples/todomvc/webpack.config.js: -------------------------------------------------------------------------------- 1 | var webpack = require( 'webpack' ), 2 | path = require( 'path' ); 3 | 4 | var config = { 5 | entry : { 6 | app : './js/main.jsx' 7 | }, 8 | 9 | output : { 10 | // export itself to a global var 11 | path : __dirname + '/dist', 12 | publicPath : '/dist/', 13 | filename : '[name].js' 14 | }, 15 | 16 | devtool : 'source-map', 17 | 18 | resolve : { 19 | modules : [ 'node_modules', 'src' ], 20 | }, 21 | 22 | module : { 23 | rules : [ 24 | { 25 | test : /\.css$/, 26 | use : [ 27 | { 28 | loader: "style-loader" 29 | }, 30 | { 31 | loader: "css-loader", 32 | options: { 33 | modules: true 34 | } 35 | } 36 | ] 37 | }, 38 | { 39 | test : /\.jsx?$/, 40 | exclude : /(node_modules|lib)/, 41 | loader : 'babel-loader' 42 | }, 43 | { 44 | test: /\.js$/, 45 | use: ["source-map-loader"], 46 | enforce: "pre" 47 | } 48 | ] 49 | } 50 | }; 51 | 52 | module.exports = config; -------------------------------------------------------------------------------- /examples/userslist/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets":["react", ["es2015", {"loose": true}] ], 3 | "plugins":[ 4 | "transform-decorators-legacy", 5 | "transform-object-rest-spread", 6 | "add-module-exports", 7 | "transform-class-properties" 8 | ], 9 | 10 | "env": { 11 | "production": { 12 | "plugins": [ 13 | "transform-react-constant-elements", 14 | "transform-react-inline-elements" 15 | ] 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /examples/userslist/README.md: -------------------------------------------------------------------------------- 1 | # UsersList Example 2 | 3 | Here's the UsersList application example, written originally for NestedLink. 4 | 5 | It's changed to use NestedReact. Feel the difference. 6 | 7 | NestedLink data binding is so powerful that there are no any difference 8 | in size, so expressiveness is roughly the same. 9 | 10 | But. Check out how much less magical NestedReact solution feels - compare the code. 11 | 12 | In fact, there's an incredible amount of dirty magic involved, 13 | just to make you feel that there are no any magic at all :). 14 | 15 | That's NestedReact. Relax, and write in natural way, no tricks are required. 16 | -------------------------------------------------------------------------------- /examples/userslist/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | NestedReact • TodoMVC 7 | 8 | 9 | 10 |
      11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /examples/userslist/main.css: -------------------------------------------------------------------------------- 1 | .invalid { 2 | border-color: red; 3 | } 4 | 5 | .invalid.required { 6 | border-color: yellow; 7 | } 8 | 9 | .checkbox,.radio { 10 | margin: 3px; 11 | display: inline-block; 12 | width: 10px; 13 | height : 10px; 14 | border: solid; 15 | border-width: 1px; 16 | } 17 | 18 | .selected { 19 | background-color: black; 20 | } 21 | 22 | label { 23 | display: block; 24 | margin: 5px; 25 | } 26 | 27 | input { 28 | margin: 3px; 29 | } 30 | 31 | 32 | .users-row>div { 33 | display: inline-block; 34 | width : 15em; 35 | } 36 | 37 | .validation-error { 38 | display: inline-block; 39 | color: red; 40 | } 41 | 42 | label>div { 43 | display: inline-block; 44 | } 45 | -------------------------------------------------------------------------------- /examples/userslist/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "dependencies": { 4 | "todomvc-app-css": "^2.0.0", 5 | "todomvc-common": "^1.0.0" 6 | }, 7 | "devDependencies": { 8 | "babel-cli": "*", 9 | "babel-core": "*", 10 | "babel-loader": "*", 11 | "babel-plugin-add-module-exports": "*", 12 | "babel-plugin-transform-class-properties": "*", 13 | "babel-plugin-transform-decorators-legacy": "*", 14 | "babel-plugin-transform-object-rest-spread": "*", 15 | "babel-plugin-transform-react-constant-elements": "*", 16 | "babel-plugin-transform-react-inline-elements": "*", 17 | "babel-preset-es2015": "*", 18 | "babel-preset-react": "*", 19 | "babel-runtime": "*", 20 | "classnames": "*", 21 | "css-loader": "*", 22 | "prop-types": "*", 23 | "react": "*", 24 | "react-dom": "*", 25 | "react-modal": "^3.1.2", 26 | "react-mvx": "^2.0.0-rc900", 27 | "source-map-loader": "^0.2.3", 28 | "style-loader": "*", 29 | "type-r": "^2.0.1", 30 | "webpack": "^3.8.1" 31 | }, 32 | "scripts": { 33 | "test": "echo \"Error: no test specified\" && exit 1", 34 | "build": "node_modules/.bin/webpack", 35 | "watch": "node_modules/.bin/webpack --progress --colors --watch" 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /examples/userslist/webpack.config.js: -------------------------------------------------------------------------------- 1 | var webpack = require( 'webpack' ), 2 | path = require( 'path' ); 3 | 4 | var config = { 5 | entry : { 6 | app : './main.jsx' 7 | }, 8 | 9 | output : { 10 | // export itself to a global var 11 | path : __dirname + '/dist', 12 | publicPath : '/dist/', 13 | filename : '[name].js' 14 | }, 15 | 16 | devtool : 'source-map', 17 | 18 | resolve : { 19 | modules : [ 'node_modules', 'src' ], 20 | }, 21 | 22 | module : { 23 | rules : [ 24 | { 25 | test : /\.css$/, 26 | use : [ 27 | { 28 | loader: "style-loader" 29 | }, 30 | { 31 | loader: "css-loader", 32 | options: { 33 | modules: true 34 | } 35 | } 36 | ] 37 | }, 38 | { 39 | test : /\.jsx?$/, 40 | exclude : /(node_modules|lib)/, 41 | loader : 'babel-loader' 42 | }, 43 | { 44 | test: /\.js$/, 45 | use: ["source-map-loader"], 46 | enforce: "pre" 47 | } 48 | ] 49 | } 50 | }; 51 | 52 | module.exports = config; -------------------------------------------------------------------------------- /lib/component.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * React-Type-R component base class. Overrides React component. 3 | */ 4 | import * as React from 'react'; 5 | import { Messenger, Record, Store } from 'type-r'; 6 | import onDefine, { TypeSpecs } from './define'; 7 | import Link from './link'; 8 | export declare class Component extends React.Component { 9 | cid: string; 10 | static state?: TypeSpecs | typeof Record; 11 | static store?: TypeSpecs | typeof Store; 12 | static props?: TypeSpecs; 13 | static context?: TypeSpecs; 14 | static childContext?: TypeSpecs; 15 | static pureRender?: boolean; 16 | private static propTypes; 17 | private static defaultProps; 18 | private static contextTypes; 19 | private static childContextTypes; 20 | private PropsChangeTokens; 21 | static extend: (spec: object, statics?: object) => Component; 22 | linkAt(key: string): Link; 23 | linkAll(...keys: string[]): { 24 | [key: string]: Link; 25 | }; 26 | linkPath(path: string): Link; 27 | readonly links: any; 28 | static onDefine: typeof onDefine; 29 | readonly state: S; 30 | readonly store?: Store; 31 | constructor(props?: any, context?: any); 32 | _initializeState(): void; 33 | assignToState(x: any, key: string): void; 34 | setState(attrs: object | ((state: S, props: P) => object)): void; 35 | isMounted: () => boolean; 36 | componentWillUnmount(): void; 37 | /** 38 | * Performs transactional update for both props and state. 39 | * Suppress updates during the transaction, and force update aftewards. 40 | * Wrapping the sequence of changes in a transactions guarantees that 41 | * React component will be updated _after_ all the changes to the 42 | * both props and local state are applied. 43 | */ 44 | transaction(fun: (state?: Record) => void): void; 45 | asyncUpdate(): void; 46 | } 47 | export interface Component extends Messenger { 48 | } 49 | -------------------------------------------------------------------------------- /lib/component.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"component.js","sourceRoot":"","sources":["../src/component.ts"],"names":[],"mappings":"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"} -------------------------------------------------------------------------------- /lib/define/common.d.ts: -------------------------------------------------------------------------------- 1 | import { ComponentClass as ReactComponentClass, Component } from 'react'; 2 | import { MixableConstructor, Messenger } from 'type-r'; 3 | export interface ComponentClass extends ReactComponentClass, MixableConstructor { 4 | prototype: Proto & ComponentProto; 5 | } 6 | export declare type ComponentProto = Component & Messenger; 7 | -------------------------------------------------------------------------------- /lib/define/common.js: -------------------------------------------------------------------------------- 1 | //# sourceMappingURL=common.js.map -------------------------------------------------------------------------------- /lib/define/common.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"common.js","sourceRoot":"","sources":["../../src/define/common.ts"],"names":[],"mappings":""} -------------------------------------------------------------------------------- /lib/define/context.d.ts: -------------------------------------------------------------------------------- 1 | import { TypeSpecs } from './typeSpecs'; 2 | import { ComponentClass } from './common'; 3 | export interface ContextDefinition { 4 | context: TypeSpecs; 5 | childContext: TypeSpecs; 6 | } 7 | export interface ContextProto { 8 | _context: TypeSpecs; 9 | _childContext: TypeSpecs; 10 | } 11 | export default function onDefine(this: ComponentClass, { context, childContext }: ContextDefinition, BaseClass: ComponentClass): void; 12 | -------------------------------------------------------------------------------- /lib/define/context.js: -------------------------------------------------------------------------------- 1 | import { compileSpecs } from './typeSpecs'; 2 | import { tools } from 'type-r'; 3 | export default function onDefine(_a, BaseClass) { 4 | var context = _a.context, childContext = _a.childContext; 5 | var prototype = this.prototype; 6 | if (context) { 7 | // Merge in inherited members... 8 | prototype._context = tools.defaults(context, BaseClass.prototype._context || {}); 9 | // Compile to propTypes... 10 | this.contextTypes = compileSpecs(context).propTypes; 11 | } 12 | if (childContext) { 13 | prototype._childContext = tools.defaults(childContext, BaseClass.prototype._childContext); 14 | this.childContextTypes = compileSpecs(childContext).propTypes; 15 | } 16 | } 17 | //# sourceMappingURL=context.js.map -------------------------------------------------------------------------------- /lib/define/context.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"context.js","sourceRoot":"","sources":["../../src/define/context.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAa,MAAM,aAAa,CAAA;AACrD,OAAO,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAA;AAa9B,MAAM,CAAC,OAAO,UAAU,QAAQ,CAAuC,EAA6C,EAAE,SAAwC;QAArF,oBAAO,EAAE,8BAAY;IAClF,IAAA,0BAAS,CAAU;IAE3B,IAAI,OAAO,EAAE;QACT,gCAAgC;QAChC,SAAS,CAAC,QAAQ,GAAG,KAAK,CAAC,QAAQ,CAAE,OAAO,EAAE,SAAS,CAAC,SAAS,CAAC,QAAQ,IAAI,EAAE,CAAE,CAAC;QAEnF,0BAA0B;QAC1B,IAAI,CAAC,YAAY,GAAG,YAAY,CAAE,OAAO,CAAE,CAAC,SAAS,CAAC;KACzD;IAED,IAAI,YAAY,EAAE;QACd,SAAS,CAAC,aAAa,GAAG,KAAK,CAAC,QAAQ,CAAE,YAAY,EAAE,SAAS,CAAC,SAAS,CAAC,aAAa,CAAE,CAAC;QAC5F,IAAI,CAAC,iBAAiB,GAAG,YAAY,CAAE,YAAY,CAAE,CAAC,SAAS,CAAC;KACnE;AACL,CAAC"} -------------------------------------------------------------------------------- /lib/define/index.d.ts: -------------------------------------------------------------------------------- 1 | import { ComponentClass } from './common'; 2 | import { StoreDefinition, StoreProto } from './store'; 3 | import { StateDefinition, StateProto } from './state'; 4 | import { ContextDefinition, ContextProto } from './context'; 5 | import { PropsDefinition, PropsProto } from './props'; 6 | export interface ComponentDefinition extends StoreDefinition, StateDefinition, ContextDefinition, PropsDefinition { 7 | } 8 | export interface ComponentProto extends StoreProto, StateProto, ContextProto, PropsProto { 9 | } 10 | export default function onDefine(this: ComponentClass, definition: ComponentDefinition, BaseClass: ComponentClass): void; 11 | export { Node, Element, TypeSpecs } from './typeSpecs'; 12 | export { EmptyPropsChangeTokensCtor } from './pureRender'; 13 | -------------------------------------------------------------------------------- /lib/define/index.js: -------------------------------------------------------------------------------- 1 | import { Messenger } from 'type-r'; 2 | import onDefineStore from './store'; 3 | import onDefineState from './state'; 4 | import onDefineContext from './context'; 5 | import onDefineProps from './props'; 6 | export default function onDefine(definition, BaseClass) { 7 | // Initialize mixins placeholder... 8 | onDefineStore.call(this, definition, BaseClass); 9 | onDefineState.call(this, definition, BaseClass); 10 | onDefineContext.call(this, definition, BaseClass); 11 | onDefineProps.call(this, definition, BaseClass); 12 | Messenger.onDefine.call(this, definition, BaseClass); 13 | } 14 | ; 15 | export { Node, Element } from './typeSpecs'; 16 | export { EmptyPropsChangeTokensCtor } from './pureRender'; 17 | //# sourceMappingURL=index.js.map -------------------------------------------------------------------------------- /lib/define/index.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/define/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAA;AAElC,OAAO,aAA8C,MAAM,SAAS,CAAA;AACpE,OAAO,aAA8C,MAAM,SAAS,CAAA;AACpE,OAAO,eAAoD,MAAM,WAAW,CAAA;AAC5E,OAAO,aAA8C,MAAM,SAAS,CAAA;AAKpE,MAAM,CAAC,OAAO,UAAU,QAAQ,CAAyC,UAAgC,EAAE,SAA0C;IACjJ,mCAAmC;IACnC,aAAa,CAAC,IAAI,CAAE,IAAI,EAAE,UAAU,EAAE,SAAS,CAAE,CAAC;IAClD,aAAa,CAAC,IAAI,CAAE,IAAI,EAAE,UAAU,EAAE,SAAS,CAAE,CAAC;IAClD,eAAe,CAAC,IAAI,CAAE,IAAI,EAAE,UAAU,EAAE,SAAS,CAAE,CAAC;IACpD,aAAa,CAAC,IAAI,CAAE,IAAI,EAAE,UAAU,EAAE,SAAS,CAAE,CAAC;IAElD,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAE,IAAI,EAAE,UAAU,EAAE,SAAS,CAAE,CAAC;AAC3D,CAAC;AAAA,CAAC;AAEF,OAAO,EAAE,IAAI,EAAE,OAAO,EAAa,MAAM,aAAa,CAAA;AACtD,OAAO,EAAE,0BAA0B,EAAE,MAAM,cAAc,CAAA"} -------------------------------------------------------------------------------- /lib/define/props.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Handle props specification and everything which is related: 3 | * - local listening to props changes 4 | * - pure render mixin 5 | */ 6 | import { TypeSpecs } from './typeSpecs'; 7 | import { ComponentClass } from './common'; 8 | export interface PropsDefinition { 9 | pureRender?: boolean; 10 | props: TypeSpecs; 11 | } 12 | export interface PropsProto { 13 | pureRender?: boolean; 14 | _props?: TypeSpecs; 15 | _watchers?: any; 16 | _changeHandlers?: any; 17 | PropsChangeTokens?: any; 18 | } 19 | export default function onDefine(this: ComponentClass, { props, pureRender }: PropsDefinition, BaseClass: ComponentClass): void; 20 | -------------------------------------------------------------------------------- /lib/define/props.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Handle props specification and everything which is related: 3 | * - local listening to props changes 4 | * - pure render mixin 5 | */ 6 | import { compileSpecs } from './typeSpecs'; 7 | import { PureRenderMixin, createChangeTokensConstructor } from './pureRender'; 8 | import { tools } from 'type-r'; 9 | export default function onDefine(_a, BaseClass) { 10 | var props = _a.props, pureRender = _a.pureRender; 11 | var prototype = this.prototype; 12 | // process props spec... 13 | if (props) { 14 | // Merge with inherited members... 15 | prototype._props = tools.defaults(props, BaseClass.prototype._props || {}); 16 | var _b = compileSpecs(props), propTypes = _b.propTypes, defaults = _b.defaults, watchers = _b.watchers, changeHandlers = _b.changeHandlers; 17 | this.propTypes = propTypes; 18 | if (defaults) 19 | this.defaultProps = defaults; 20 | if (watchers) { 21 | prototype._watchers = watchers; 22 | this.mixins.merge([WatchersMixin]); 23 | } 24 | if (changeHandlers) { 25 | prototype._changeHandlers = changeHandlers; 26 | this.mixins.merge([ChangeHandlersMixin]); 27 | } 28 | if (prototype.pureRender) { 29 | prototype.PropsChangeTokens = createChangeTokensConstructor(props); 30 | } 31 | } 32 | if (pureRender) { 33 | this.mixins.merge([PureRenderMixin]); 34 | } 35 | } 36 | /** 37 | * ChangeHandlers are fired in sequence upon props replacement. 38 | * Fires _after_ UI is updated. Used for managing events subscriptions. 39 | */ 40 | var ChangeHandlersMixin = { 41 | componentDidMount: function () { 42 | handlePropsChanges(this, {}, this.props); 43 | }, 44 | componentDidUpdate: function (prev) { 45 | handlePropsChanges(this, prev, this.props); 46 | }, 47 | componentWillUnmount: function () { 48 | handlePropsChanges(this, this.props, {}); 49 | } 50 | }; 51 | function handlePropsChanges(component, prev, next) { 52 | var _changeHandlers = component._changeHandlers; 53 | for (var name_1 in _changeHandlers) { 54 | if (prev[name_1] !== next[name_1]) { 55 | for (var _i = 0, _a = _changeHandlers[name_1]; _i < _a.length; _i++) { 56 | var handler = _a[_i]; 57 | handler(next[name_1], prev[name_1], component); 58 | } 59 | } 60 | } 61 | } 62 | /** 63 | * Watchers works on props replacement and fires _before_ any change will be applied and UI is updated. 64 | * Fired in componentWillMount as well, which makes it a nice way to sync state from props. 65 | */ 66 | var WatchersMixin = { 67 | componentWillReceiveProps: function (next) { 68 | var _a = this, _watchers = _a._watchers, props = _a.props; 69 | for (var name_2 in _watchers) { 70 | if (next[name_2] !== props[name_2]) { 71 | _watchers[name_2].call(this, next[name_2], name_2); 72 | } 73 | } 74 | }, 75 | componentWillMount: function () { 76 | var _a = this, _watchers = _a._watchers, props = _a.props; 77 | for (var name_3 in _watchers) { 78 | _watchers[name_3].call(this, props[name_3], name_3); 79 | } 80 | } 81 | }; 82 | //# sourceMappingURL=props.js.map -------------------------------------------------------------------------------- /lib/define/props.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"props.js","sourceRoot":"","sources":["../../src/define/props.ts"],"names":[],"mappings":"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"} -------------------------------------------------------------------------------- /lib/define/pureRender.d.ts: -------------------------------------------------------------------------------- 1 | export declare function createChangeTokensConstructor(props: any): Function; 2 | export declare const EmptyPropsChangeTokensCtor: Function; 3 | export declare const PureRenderMixin: { 4 | shouldComponentUpdate(nextProps: any): any; 5 | componentDidMount: typeof updateChangeTokens; 6 | componentDidUpdate: typeof updateChangeTokens; 7 | }; 8 | declare function updateChangeTokens(): void; 9 | export {}; 10 | -------------------------------------------------------------------------------- /lib/define/pureRender.js: -------------------------------------------------------------------------------- 1 | export function createChangeTokensConstructor(props) { 2 | var propNames = Object.keys(props); 3 | var PropsChangeTokens = new Function('p', 's', "\n var v;\n this._s = s && s._changeToken;\n " + propNames.map(function (name) { return "\n this." + name + " = ( ( v = p." + name + ") && v._changeToken ) || v;\n "; }).join('') + "\n "); 4 | PropsChangeTokens.prototype._hasChanges = new Function('p', 's', "\n var v;\n return ( ( s && s._changeToken ) !== this._s ) " + propNames.map(function (name) { return " ||\n this." + name + " !== ( ( ( v = p." + name + ") && v._changeToken ) || v )\n "; }).join('') + ";\n "); 5 | return PropsChangeTokens; 6 | } 7 | ; 8 | export var EmptyPropsChangeTokensCtor = createChangeTokensConstructor({}); 9 | export var PureRenderMixin = { 10 | shouldComponentUpdate: function (nextProps) { 11 | return this._propsChangeTokens._hasChanges(nextProps, this.state); 12 | }, 13 | componentDidMount: updateChangeTokens, 14 | componentDidUpdate: updateChangeTokens 15 | }; 16 | function updateChangeTokens() { 17 | this._propsChangeTokens = new this.PropsChangeTokens(this.props, this.state); 18 | } 19 | //# sourceMappingURL=pureRender.js.map -------------------------------------------------------------------------------- /lib/define/pureRender.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"pureRender.js","sourceRoot":"","sources":["../../src/define/pureRender.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,6BAA6B,CAAE,KAAK;IAChD,IAAM,SAAS,GAAG,MAAM,CAAC,IAAI,CAAE,KAAK,CAAE,CAAC;IAEvC,IAAM,iBAAiB,GAAG,IAAI,QAAQ,CAAE,GAAG,EAAE,GAAG,EAAE,uEAG3C,SAAS,CAAC,GAAG,CAAE,UAAA,IAAI,IAAI,OAAA,wBACd,IAAI,qBAAkB,IAAI,0CACrC,EAFyB,CAEzB,CAAC,CAAC,IAAI,CAAE,EAAE,CAAE,WAChB,CAAC,CAAC;IAEH,iBAAiB,CAAC,SAAS,CAAC,WAAW,GAAG,IAAI,QAAQ,CAAE,GAAG,EAAE,GAAG,EAAE,8EAEZ,SAAS,CAAC,GAAG,CAAE,UAAA,IAAI,IAAI,OAAA,2BAC7D,IAAI,yBAAsB,IAAI,2CACzC,EAFwE,CAExE,CAAC,CAAC,IAAI,CAAE,EAAE,CAAE,YAChB,CAAC,CAAC;IAEH,OAAO,iBAAiB,CAAC;AAC7B,CAAC;AAAA,CAAC;AAEF,MAAM,CAAC,IAAM,0BAA0B,GAAG,6BAA6B,CAAC,EAAE,CAAC,CAAC;AAE5E,MAAM,CAAC,IAAM,eAAe,GAAG;IAC3B,qBAAqB,YAAE,SAAS;QAC5B,OAAO,IAAI,CAAC,kBAAkB,CAAC,WAAW,CAAE,SAAS,EAAE,IAAI,CAAC,KAAK,CAAE,CAAC;IACxE,CAAC;IAED,iBAAiB,EAAG,kBAAkB;IACtC,kBAAkB,EAAG,kBAAkB;CAC1C,CAAA;AAED,SAAS,kBAAkB;IACvB,IAAI,CAAC,kBAAkB,GAAG,IAAI,IAAI,CAAC,iBAAiB,CAAE,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,KAAK,CAAE,CAAC;AACnF,CAAC"} -------------------------------------------------------------------------------- /lib/define/state.d.ts: -------------------------------------------------------------------------------- 1 | /***************** 2 | * State 3 | */ 4 | import { Record, Store } from 'type-r'; 5 | import { ComponentClass } from './common'; 6 | export interface StateDefinition { 7 | state?: object | typeof Record; 8 | State?: typeof Record; 9 | } 10 | export interface StateProto { 11 | State?: typeof Record; 12 | } 13 | export default function process(this: ComponentClass, definition: StateDefinition, BaseComponentClass: ComponentClass): void; 14 | export declare const StateMixin: { 15 | _initializeState(): void; 16 | context: { 17 | _nestedStore: typeof Store; 18 | }; 19 | getStore(): any; 20 | componentWillUnmount(): void; 21 | }; 22 | export declare const UpdateOnNestedChangesMixin: { 23 | _onChildrenChange(): void; 24 | componentDidMount(): void; 25 | }; 26 | -------------------------------------------------------------------------------- /lib/define/state.js: -------------------------------------------------------------------------------- 1 | import * as tslib_1 from "tslib"; 2 | /***************** 3 | * State 4 | */ 5 | import { define, Record, Store } from 'type-r'; 6 | export default function process(definition, BaseComponentClass) { 7 | var prototype = this.prototype; 8 | var state = definition.state, State = definition.State; 9 | if (typeof state === 'function') { 10 | State = state; 11 | state = void 0; 12 | } 13 | if (state) { 14 | var BaseClass = State || prototype.State || Record; 15 | var ComponentState = /** @class */ (function (_super) { 16 | tslib_1.__extends(ComponentState, _super); 17 | function ComponentState() { 18 | return _super !== null && _super.apply(this, arguments) || this; 19 | } 20 | ComponentState.attributes = state; 21 | ComponentState = tslib_1.__decorate([ 22 | define 23 | ], ComponentState); 24 | return ComponentState; 25 | }(BaseClass)); 26 | prototype.State = ComponentState; 27 | } 28 | else if (State) { 29 | prototype.State = State; 30 | } 31 | if (state || State) { 32 | this.mixins.merge([StateMixin, UpdateOnNestedChangesMixin]); 33 | } 34 | } 35 | export var StateMixin = { 36 | //state : null, 37 | _initializeState: function () { 38 | // props.__keepState is used to workaround issues in Backbone intergation layer 39 | var state = this.state = this.props.__keepState || new this.State(); 40 | // Take ownership on state... 41 | state._owner = this; 42 | state._ownerKey = 'state'; 43 | }, 44 | context: { 45 | _nestedStore: Store 46 | }, 47 | // reference global store to fix model's store locator 48 | getStore: function () { 49 | // Attempt to get the store from the context first. Then - fallback to the state's default store. 50 | // TBD: Need to figure out a good way of managing local stores. 51 | var context, state; 52 | return ((context = this.context) && context._nestedStore) || 53 | ((state = this.state) && state._defaultStore) || Store.global; 54 | }, 55 | componentWillUnmount: function () { 56 | var state = this.state; 57 | state._owner = state._ownerKey = void 0; 58 | this._preventDispose /* hack for component-view to preserve the state */ || state.dispose(); 59 | this.state = void 0; 60 | } 61 | }; 62 | export var UpdateOnNestedChangesMixin = { 63 | _onChildrenChange: function () { }, 64 | componentDidMount: function () { 65 | this._onChildrenChange = this.asyncUpdate; 66 | } 67 | }; 68 | //# sourceMappingURL=state.js.map -------------------------------------------------------------------------------- /lib/define/state.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"state.js","sourceRoot":"","sources":["../../src/define/state.ts"],"names":[],"mappings":";AAAA;;GAEG;AACH,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAA;AAY9C,MAAM,CAAC,OAAO,UAAU,OAAO,CAAqC,UAA4B,EAAE,kBAA+C;IACrI,IAAA,0BAAS,CAAU;IAErB,IAAA,wBAAK,EAAE,wBAAK,CAAgB;IAElC,IAAI,OAAO,KAAK,KAAK,UAAU,EAAE;QAC7B,KAAK,GAAG,KAAsB,CAAC;QAC/B,KAAK,GAAG,KAAK,CAAC,CAAC;KAClB;IAED,IAAI,KAAK,EAAE;QACP,IAAM,SAAS,GAAG,KAAK,IAAI,SAAS,CAAC,KAAK,IAAI,MAAM,CAAC;QAE7C;YAA6B,0CAAS;YAAtC;;YAER,CAAC;YADU,yBAAU,GAAG,KAAK,CAAC;YADhB,cAAc;gBAA3B,MAAM;eAAO,cAAc,CAE3B;YAAD,qBAAC;SAAA,AAFO,CAA6B,SAAS,GAE7C;QAED,SAAS,CAAC,KAAK,GAAG,cAAc,CAAC;KACpC;SACI,IAAI,KAAK,EAAE;QACZ,SAAS,CAAC,KAAK,GAAG,KAAK,CAAC;KAC3B;IAED,IAAI,KAAK,IAAI,KAAK,EAAE;QAChB,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAE,UAAU,EAAE,0BAA0B,CAAE,CAAC,CAAC;KACjE;AACL,CAAC;AAED,MAAM,CAAC,IAAM,UAAU,GAAG;IACtB,eAAe;IAEf,gBAAgB;QACZ,+EAA+E;QAC/E,IAAM,KAAK,GAAG,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,WAAW,IAAI,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;QAEtE,6BAA6B;QAC7B,KAAK,CAAC,MAAM,GAAG,IAAI,CAAC;QACpB,KAAK,CAAC,SAAS,GAAG,OAAO,CAAC;IAC9B,CAAC;IAED,OAAO,EAAG;QACN,YAAY,EAAG,KAAK;KACvB;IAED,sDAAsD;IACtD,QAAQ;QACJ,iGAAiG;QACjG,+DAA+D;QAC/D,IAAI,OAAO,EAAE,KAAK,CAAC;QAEnB,OAAQ,CAAE,CAAE,OAAO,GAAG,IAAI,CAAC,OAAO,CAAE,IAAI,OAAO,CAAC,YAAY,CAAE;YACtD,CAAE,CAAE,KAAK,GAAG,IAAI,CAAC,KAAK,CAAE,IAAI,KAAK,CAAC,aAAa,CAAE,IAAI,KAAK,CAAC,MAAM,CAAC;IAC9E,CAAC;IAED,oBAAoB;QACR,IAAA,kBAAK,CAAU;QACvB,KAAK,CAAC,MAAM,GAAG,KAAK,CAAC,SAAS,GAAG,KAAK,CAAC,CAAC;QACxC,IAAI,CAAC,eAAe,CAAC,mDAAmD,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;QAC5F,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC,CAAC;IACxB,CAAC;CACJ,CAAC;AAEF,MAAM,CAAC,IAAM,0BAA0B,GAAG;IACtC,iBAAiB,gBAAG,CAAC;IAErB,iBAAiB;QACb,IAAI,CAAC,iBAAiB,GAAG,IAAI,CAAC,WAAW,CAAC;IAC9C,CAAC;CACJ,CAAC"} -------------------------------------------------------------------------------- /lib/define/store.d.ts: -------------------------------------------------------------------------------- 1 | import { Store } from 'type-r'; 2 | import { ComponentClass } from './common'; 3 | export interface StoreDefinition { 4 | store?: typeof Store | Store | object; 5 | Store?: typeof Store; 6 | } 7 | export interface StoreProto { 8 | store?: Store; 9 | Store?: typeof Store; 10 | } 11 | export default function onDefine(this: ComponentClass, definition: StoreDefinition, BaseClass: ComponentClass): void; 12 | -------------------------------------------------------------------------------- /lib/define/store.js: -------------------------------------------------------------------------------- 1 | import * as tslib_1 from "tslib"; 2 | import { define, Store } from 'type-r'; 3 | import { StateMixin, UpdateOnNestedChangesMixin } from './state'; 4 | export default function onDefine(definition, BaseClass) { 5 | var store = definition.store, StoreClass = definition.Store; 6 | if (store && store instanceof Store) { 7 | // Direct reference to an existing store. Put it to the prototype. 8 | this.prototype.store = store; 9 | this.mixins.merge([ExternalStoreMixin, ExposeStoreMixin]); 10 | } 11 | else if (store || definition.Store) { 12 | if (typeof store === 'function') { 13 | StoreClass = store; 14 | store = void 0; 15 | } 16 | if (store) { 17 | var BaseClass_1 = StoreClass || this.prototype.Store || Store; 18 | var InternalStore = /** @class */ (function (_super) { 19 | tslib_1.__extends(InternalStore, _super); 20 | function InternalStore() { 21 | return _super !== null && _super.apply(this, arguments) || this; 22 | } 23 | InternalStore.attrbutes = store; 24 | InternalStore = tslib_1.__decorate([ 25 | define 26 | ], InternalStore); 27 | return InternalStore; 28 | }(BaseClass_1)); 29 | ; 30 | this.prototype.Store = InternalStore; 31 | } 32 | else if (StoreClass) { 33 | this.prototype.Store = StoreClass; 34 | } 35 | this.mixins.merge([InternalStoreMixin, UpdateOnNestedChangesMixin, ExposeStoreMixin]); 36 | } 37 | } 38 | /** 39 | * Attached whenever the store declaration of any form is present in the component. 40 | */ 41 | var ExposeStoreMixin = { 42 | childContext: { 43 | _nestedStore: Store 44 | }, 45 | getChildContext: function () { 46 | return { _nestedStore: this.store }; 47 | }, 48 | getStore: function () { 49 | return this.store; 50 | }, 51 | // Will be called by the store when the lookup will fail. 52 | get: function (key) { 53 | // Ask upper store. 54 | var store = StateMixin.getStore.call(this); 55 | return store && store.get(key); 56 | } 57 | }; 58 | /** 59 | * External store must just track the changes and trigger render. 60 | * TBD: don't use it yet. 61 | */ 62 | var ExternalStoreMixin = { 63 | componentDidMount: function () { 64 | // Start UI updates on state changes. 65 | this.listenTo(this.store, 'change', this.asyncUpdate); 66 | } 67 | }; 68 | var InternalStoreMixin = { 69 | componentWillMount: function () { 70 | var store = this.store = new this.Store(); 71 | store._owner = this; 72 | store._ownerKey = 'store'; 73 | }, 74 | componentWillUnmount: function () { 75 | this.store._ownerKey = this.store._owner = void 0; 76 | this.store.dispose(); 77 | this.store = void 0; 78 | } 79 | }; 80 | //# sourceMappingURL=store.js.map -------------------------------------------------------------------------------- /lib/define/store.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"store.js","sourceRoot":"","sources":["../../src/define/store.ts"],"names":[],"mappings":";AAAA,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAA;AACtC,OAAO,EAAE,UAAU,EAAE,0BAA0B,EAAE,MAAM,SAAS,CAAA;AAahE,MAAM,CAAC,OAAO,UAAU,QAAQ,CAAqC,UAA4B,EAAE,SAAsC;IAC/H,IAAA,wBAAK,EAAE,6BAAkB,CAAgB;IAE/C,IAAI,KAAK,IAAI,KAAK,YAAY,KAAK,EAAE;QACjC,kEAAkE;QAClE,IAAI,CAAC,SAAS,CAAC,KAAK,GAAG,KAAK,CAAC;QAC7B,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAE,kBAAkB,EAAE,gBAAgB,CAAE,CAAC,CAAC;KAC/D;SACI,IAAI,KAAK,IAAI,UAAU,CAAC,KAAK,EAAG;QACjC,IAAI,OAAO,KAAK,KAAK,UAAU,EAAE;YAC7B,UAAU,GAAG,KAAqB,CAAC;YACnC,KAAK,GAAG,KAAK,CAAC,CAAC;SAClB;QAED,IAAI,KAAK,EAAE;YACP,IAAM,WAAS,GAAG,UAAU,IAAI,IAAI,CAAC,SAAS,CAAC,KAAK,IAAI,KAAK,CAAC;YACtD;gBAA4B,yCAAS;gBAArC;;gBAER,CAAC;gBADU,uBAAS,GAAG,KAAK,CAAC;gBADf,aAAa;oBAA1B,MAAM;mBAAO,aAAa,CAE1B;gBAAD,oBAAC;aAAA,AAFO,CAA4B,WAAS,GAE5C;YAAA,CAAC;YAEF,IAAI,CAAC,SAAS,CAAC,KAAK,GAAG,aAAa,CAAC;SACxC;aACI,IAAI,UAAU,EAAE;YACjB,IAAI,CAAC,SAAS,CAAC,KAAK,GAAG,UAAU,CAAC;SACrC;QAED,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAE,kBAAkB,EAAE,0BAA0B,EAAE,gBAAgB,CAAE,CAAC,CAAC;KAC3F;AACL,CAAC;AAED;;GAEG;AACH,IAAM,gBAAgB,GAAG;IACrB,YAAY,EAAG;QACX,YAAY,EAAG,KAAK;KACvB;IAED,eAAe;QACX,OAAO,EAAE,YAAY,EAAG,IAAI,CAAC,KAAK,EAAE,CAAC;IACzC,CAAC;IAED,QAAQ;QACJ,OAAO,IAAI,CAAC,KAAK,CAAC;IACtB,CAAC;IAED,yDAAyD;IACzD,GAAG,YAAE,GAAG;QACJ,mBAAmB;QACnB,IAAM,KAAK,GAAG,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAE,IAAI,CAAE,CAAC;QAC/C,OAAO,KAAK,IAAI,KAAK,CAAC,GAAG,CAAE,GAAG,CAAE,CAAC;IACrC,CAAC;CACJ,CAAC;AAEF;;;GAGG;AACH,IAAM,kBAAkB,GAAG;IACvB,iBAAiB;QACb,qCAAqC;QACrC,IAAI,CAAC,QAAQ,CAAE,IAAI,CAAC,KAAK,EAAE,QAAQ,EAAE,IAAI,CAAC,WAAW,CAAE,CAAC;IAC5D,CAAC;CACJ,CAAC;AAEF,IAAM,kBAAkB,GAAG;IACvB,kBAAkB;QACd,IAAI,KAAK,GAAG,IAAI,CAAC,KAAK,GAAG,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;QAC1C,KAAK,CAAC,MAAM,GAAG,IAAI,CAAC;QACpB,KAAK,CAAC,SAAS,GAAG,OAAO,CAAC;IAC9B,CAAC;IAED,oBAAoB;QAChB,IAAI,CAAC,KAAK,CAAC,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,KAAK,CAAC,CAAC;QAClD,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC;QACrB,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC,CAAC;IACxB,CAAC;CACJ,CAAC"} -------------------------------------------------------------------------------- /lib/define/typeSpecs.d.ts: -------------------------------------------------------------------------------- 1 | import { ChangeHandler } from 'type-r'; 2 | import { ComponentProto } from './common'; 3 | export interface TypeSpecs { 4 | [name: string]: object | Function; 5 | } 6 | export declare function compileSpecs(props: TypeSpecs): { 7 | propTypes: {}; 8 | defaults: any; 9 | watchers: { 10 | [name: string]: PropWatcher; 11 | }; 12 | changeHandlers: { 13 | [name: string]: ChangeHandler[]; 14 | }; 15 | }; 16 | declare type PropWatcher = (this: ComponentProto, propValue: any, propName: string) => void; 17 | export declare class Node { 18 | } 19 | export declare class Element { 20 | } 21 | export {}; 22 | -------------------------------------------------------------------------------- /lib/define/typeSpecs.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"typeSpecs.js","sourceRoot":"","sources":["../../src/define/typeSpecs.ts"],"names":[],"mappings":"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"} -------------------------------------------------------------------------------- /lib/index.d.ts: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import { ChainableAttributeSpec, define, mixinRules, mixins } from 'type-r'; 3 | import { Component } from './component'; 4 | import { Element, Node } from './define'; 5 | import Link from './link'; 6 | interface ReactMVx { 7 | default: ReactMVx; 8 | define: typeof define; 9 | mixins: typeof mixins; 10 | mixinRules: typeof mixinRules; 11 | Component: typeof Component; 12 | Link: typeof Link; 13 | Node: ChainableAttributeSpec; 14 | Element: ChainableAttributeSpec; 15 | assignToState(key: string): any; 16 | } 17 | declare const ReactMVx: ReactMVx & typeof React; 18 | declare const assignToState: (key: string) => (prop: any) => void; 19 | export default ReactMVx; 20 | export { define, mixins, Node, Element, Link, Component, assignToState }; 21 | -------------------------------------------------------------------------------- /lib/index.js: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import { define, mixins, type } from 'type-r'; 3 | import { Component } from './component'; 4 | import { Element, Node } from './define'; 5 | import Link from './link'; 6 | // extend React namespace 7 | var ReactMVx = Object.create(React); 8 | // Make it compatible with ES6 module format. 9 | ReactMVx.default = ReactMVx; 10 | // listenToProps, listenToState, model, attributes, Model 11 | ReactMVx.define = define; 12 | ReactMVx.mixins = mixins; 13 | ReactMVx.Node = type(Node).value(null); 14 | ReactMVx.Element = type(Element).value(null); 15 | ReactMVx.Link = Link; 16 | ReactMVx.Component = Component; 17 | var assignToState = ReactMVx.assignToState = function (key) { 18 | return function (prop) { 19 | var _a; 20 | var source = prop && prop instanceof Link ? prop.value : prop; 21 | this.state.assignFrom((_a = {}, _a[key] = source, _a)); 22 | if (source && source._changeToken) { 23 | this.state[key]._changeToken = source._changeToken; 24 | } 25 | }; 26 | }; 27 | export default ReactMVx; 28 | export { define, mixins, Node, Element, Link, Component, assignToState }; 29 | //# sourceMappingURL=index.js.map -------------------------------------------------------------------------------- /lib/index.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAA0B,MAAM,EAAc,MAAM,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAClF,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,IAAI,MAAM,QAAQ,CAAC;AAuB1B,yBAAyB;AACzB,IAAM,QAAQ,GAA6B,MAAM,CAAC,MAAM,CAAE,KAAK,CAAE,CAAC;AAElE,6CAA6C;AAC7C,QAAQ,CAAC,OAAO,GAAG,QAAQ,CAAC;AAC5B,yDAAyD;AACzD,QAAQ,CAAC,MAAM,GAAG,MAAM,CAAC;AACzB,QAAQ,CAAC,MAAM,GAAG,MAAM,CAAC;AAEzB,QAAQ,CAAC,IAAI,GAAG,IAAI,CAAE,IAAI,CAAE,CAAC,KAAK,CAAE,IAAI,CAAE,CAAC;AAC3C,QAAQ,CAAC,OAAO,GAAG,IAAI,CAAE,OAAO,CAAE,CAAC,KAAK,CAAE,IAAI,CAAE,CAAC;AACjD,QAAQ,CAAC,IAAI,GAAG,IAAI,CAAC;AAErB,QAAQ,CAAC,SAAS,GAAG,SAAgB,CAAC;AACtC,IAAM,aAAa,GAAG,QAAQ,CAAC,aAAa,GAAG,UAAA,GAAG;IAC9C,OAAO,UAAU,IAAI;;QACjB,IAAM,MAAM,GAAG,IAAI,IAAI,IAAI,YAAY,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC;QAChE,IAAI,CAAC,KAAK,CAAC,UAAU,WAAG,GAAE,GAAG,IAAK,MAAM,MAAG,CAAC;QAC5C,IAAI,MAAM,IAAI,MAAM,CAAC,YAAY,EAAE;YAC/B,IAAI,CAAC,KAAK,CAAE,GAAG,CAAE,CAAC,YAAY,GAAG,MAAM,CAAC,YAAY,CAAC;SACxD;IACL,CAAC,CAAA;AACL,CAAC,CAAA;AAED,eAAe,QAAQ,CAAC;AACxB,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,aAAa,EAAE,CAAA"} -------------------------------------------------------------------------------- /lib/link.d.ts: -------------------------------------------------------------------------------- 1 | import { Link } from 'valuelink/lib/link'; 2 | export default Link; 3 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-mvx", 3 | "version": "3.0.0", 4 | "repository": { 5 | "type": "git", 6 | "url": "https://github.com/gaperton/React-MVx.git" 7 | }, 8 | "description": "Type-R bindings for React", 9 | "main": "./dist/index.js", 10 | "module": "./lib/index.js", 11 | "jsnext:main": "./lib/index.js", 12 | "types": "./lib/index.d.ts", 13 | "files": [ 14 | "dist", 15 | "lib", 16 | "src", 17 | "tags.jsx", 18 | "tags.js" 19 | ], 20 | "scripts": { 21 | "test": "echo \"Error: no test specified\" && exit 1", 22 | "compile": "./node_modules/.bin/tsc && ./node_modules/.bin/rollup --config && cp ./node_modules/valuelink/tags.* .", 23 | "deploy:example": "bash -c 'target=$0/node_modules/react-mvx && mkdir -p $target && cp -R ./dist/ $target && cp ./tags.js* $target'", 24 | "deploy:examples": "for exmpl in `ls -d ./examples/*`; do npm run deploy:example $exmpl; done", 25 | "build": "yarn && npm run compile", 26 | "docs": "node docs/build.js" 27 | }, 28 | "keywords": [ 29 | "react", 30 | "mvc", 31 | "model", 32 | "state", 33 | "mvvm" 34 | ], 35 | "author": "Vlad Balin", 36 | "license": "MIT", 37 | "peerDependencies": { 38 | "prop-types": "*", 39 | "react": "*", 40 | "type-r": "^3.0.0" 41 | }, 42 | "dependencies": { 43 | "tslib": "*", 44 | "valuelink": "^1.0.0" 45 | }, 46 | "devDependencies": { 47 | "@types/prop-types": "^15.5.2", 48 | "@types/react": "^16.7.13", 49 | "handlebars": "*", 50 | "highlight.js": "^9.12.0", 51 | "marked": "^0.3.19", 52 | "prop-types": "*", 53 | "react": "*", 54 | "rollup": "^0.50.1", 55 | "rollup-plugin-node-resolve": "^3.3.0", 56 | "rollup-plugin-uglify": "^2.0.1", 57 | "type-r": "^3.0.0", 58 | "typescript": "*" 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /rollup.config.js: -------------------------------------------------------------------------------- 1 | import resolve from 'rollup-plugin-node-resolve'; 2 | import uglify from 'rollup-plugin-uglify'; 3 | 4 | export default { 5 | input : 'lib/index.js', 6 | 7 | output : { 8 | file : 'dist/index.js', 9 | format : 'umd', 10 | name : 'ReactMVx', 11 | exports: 'named', 12 | globals: { 13 | react: 'React', 14 | 'type-r': 'Nested', 15 | 'prop-types': 'PropTypes' //just to silence warning. Actually does not matter. window.PropTypes is undefined, same result as using webpack 16 | } 17 | }, 18 | plugins: [ 19 | resolve(), //for support of `import X from "directory"` rather than verbose `import X from "directory/index"` 20 | uglify() 21 | ], 22 | sourcemap: true, 23 | external: [ 24 | 'react', 25 | 'type-r', 26 | 'prop-types', 27 | 'valuelink' 28 | ] 29 | }; -------------------------------------------------------------------------------- /src/define/common.ts: -------------------------------------------------------------------------------- 1 | import { 2 | ComponentClass as ReactComponentClass, 3 | Component 4 | } from 'react' 5 | 6 | import { MixableConstructor, Messenger } from 'type-r' 7 | 8 | export interface ComponentClass extends ReactComponentClass, MixableConstructor { 9 | prototype : Proto & ComponentProto 10 | } 11 | 12 | export type ComponentProto = Component & Messenger -------------------------------------------------------------------------------- /src/define/context.ts: -------------------------------------------------------------------------------- 1 | import { compileSpecs, TypeSpecs } from './typeSpecs' 2 | import { tools } from 'type-r' 3 | import { ComponentClass } from './common' 4 | 5 | export interface ContextDefinition { 6 | context : TypeSpecs 7 | childContext : TypeSpecs 8 | } 9 | 10 | export interface ContextProto { 11 | _context : TypeSpecs 12 | _childContext : TypeSpecs 13 | } 14 | 15 | export default function onDefine( this : ComponentClass, { context, childContext } : ContextDefinition, BaseClass : ComponentClass ){ 16 | const { prototype } = this; 17 | 18 | if( context ){ 19 | // Merge in inherited members... 20 | prototype._context = tools.defaults( context, BaseClass.prototype._context || {} ); 21 | 22 | // Compile to propTypes... 23 | this.contextTypes = compileSpecs( context ).propTypes; 24 | } 25 | 26 | if( childContext ){ 27 | prototype._childContext = tools.defaults( childContext, BaseClass.prototype._childContext ); 28 | this.childContextTypes = compileSpecs( childContext ).propTypes; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/define/index.ts: -------------------------------------------------------------------------------- 1 | import { ComponentClass } from './common' 2 | import { Messenger } from 'type-r' 3 | 4 | import onDefineStore, { StoreDefinition, StoreProto } from './store' 5 | import onDefineState, { StateDefinition, StateProto } from './state' 6 | import onDefineContext, { ContextDefinition, ContextProto } from './context' 7 | import onDefineProps, { PropsDefinition, PropsProto } from './props' 8 | 9 | export interface ComponentDefinition extends StoreDefinition, StateDefinition, ContextDefinition, PropsDefinition {} 10 | export interface ComponentProto extends StoreProto, StateProto, ContextProto, PropsProto {} 11 | 12 | export default function onDefine( this : ComponentClass, definition : ComponentDefinition, BaseClass : ComponentClass ){ 13 | // Initialize mixins placeholder... 14 | onDefineStore.call( this, definition, BaseClass ); 15 | onDefineState.call( this, definition, BaseClass ); 16 | onDefineContext.call( this, definition, BaseClass ); 17 | onDefineProps.call( this, definition, BaseClass ); 18 | 19 | Messenger.onDefine.call( this, definition, BaseClass ); 20 | }; 21 | 22 | export { Node, Element, TypeSpecs } from './typeSpecs' 23 | export { EmptyPropsChangeTokensCtor } from './pureRender' -------------------------------------------------------------------------------- /src/define/pureRender.ts: -------------------------------------------------------------------------------- 1 | export function createChangeTokensConstructor( props ) { 2 | const propNames = Object.keys( props ); 3 | 4 | const PropsChangeTokens = new Function( 'p', 's', ` 5 | var v; 6 | this._s = s && s._changeToken; 7 | ${ propNames.map( name => ` 8 | this.${ name } = ( ( v = p.${ name }) && v._changeToken ) || v; 9 | `).join( '' )} 10 | `); 11 | 12 | PropsChangeTokens.prototype._hasChanges = new Function( 'p', 's', ` 13 | var v; 14 | return ( ( s && s._changeToken ) !== this._s ) ${ propNames.map( name => ` || 15 | this.${ name } !== ( ( ( v = p.${ name }) && v._changeToken ) || v ) 16 | `).join( '' )}; 17 | `); 18 | 19 | return PropsChangeTokens; 20 | }; 21 | 22 | export const EmptyPropsChangeTokensCtor = createChangeTokensConstructor({}); 23 | 24 | export const PureRenderMixin = { 25 | shouldComponentUpdate( nextProps ){ 26 | return this._propsChangeTokens._hasChanges( nextProps, this.state ); 27 | }, 28 | 29 | componentDidMount : updateChangeTokens, 30 | componentDidUpdate : updateChangeTokens 31 | } 32 | 33 | function updateChangeTokens(){ 34 | this._propsChangeTokens = new this.PropsChangeTokens( this.props, this.state ); 35 | } -------------------------------------------------------------------------------- /src/define/state.ts: -------------------------------------------------------------------------------- 1 | /***************** 2 | * State 3 | */ 4 | import { define, Record, Store } from 'type-r' 5 | import { ComponentClass } from './common' 6 | 7 | export interface StateDefinition { 8 | state? : object | typeof Record 9 | State? : typeof Record 10 | } 11 | 12 | export interface StateProto { 13 | State? : typeof Record 14 | } 15 | 16 | export default function process( this : ComponentClass, definition : StateDefinition, BaseComponentClass : ComponentClass ){ 17 | const { prototype } = this; 18 | 19 | let { state, State } = definition; 20 | 21 | if( typeof state === 'function' ){ 22 | State = state as typeof Record; 23 | state = void 0; 24 | } 25 | 26 | if( state ){ 27 | const BaseClass = State || prototype.State || Record; 28 | 29 | @define class ComponentState extends BaseClass { 30 | static attributes = state; 31 | } 32 | 33 | prototype.State = ComponentState; 34 | } 35 | else if( State ){ 36 | prototype.State = State; 37 | } 38 | 39 | if( state || State ){ 40 | this.mixins.merge([ StateMixin, UpdateOnNestedChangesMixin ]); 41 | } 42 | } 43 | 44 | export const StateMixin = { 45 | //state : null, 46 | 47 | _initializeState(){ 48 | // props.__keepState is used to workaround issues in Backbone intergation layer 49 | const state = this.state = this.props.__keepState || new this.State(); 50 | 51 | // Take ownership on state... 52 | state._owner = this; 53 | state._ownerKey = 'state'; 54 | }, 55 | 56 | context : { 57 | _nestedStore : Store 58 | }, 59 | 60 | // reference global store to fix model's store locator 61 | getStore(){ 62 | // Attempt to get the store from the context first. Then - fallback to the state's default store. 63 | // TBD: Need to figure out a good way of managing local stores. 64 | let context, state; 65 | 66 | return ( ( context = this.context ) && context._nestedStore ) || 67 | ( ( state = this.state ) && state._defaultStore ) || Store.global; 68 | }, 69 | 70 | componentWillUnmount(){ 71 | const { state } = this; 72 | state._owner = state._ownerKey = void 0; 73 | this._preventDispose /* hack for component-view to preserve the state */ || state.dispose(); 74 | this.state = void 0; 75 | } 76 | }; 77 | 78 | export const UpdateOnNestedChangesMixin = { 79 | _onChildrenChange(){}, 80 | 81 | componentDidMount(){ 82 | this._onChildrenChange = this.asyncUpdate; 83 | } 84 | }; -------------------------------------------------------------------------------- /src/define/store.ts: -------------------------------------------------------------------------------- 1 | import { define, Store } from 'type-r' 2 | import { StateMixin, UpdateOnNestedChangesMixin } from './state' 3 | import { ComponentClass } from './common' 4 | 5 | export interface StoreDefinition { 6 | store? : typeof Store | Store | object 7 | Store? : typeof Store 8 | } 9 | 10 | export interface StoreProto { 11 | store? : Store 12 | Store? : typeof Store 13 | } 14 | 15 | export default function onDefine( this : ComponentClass, definition : StoreDefinition, BaseClass : ComponentClass ){ 16 | let { store, Store : StoreClass } = definition; 17 | 18 | if( store && store instanceof Store ){ 19 | // Direct reference to an existing store. Put it to the prototype. 20 | this.prototype.store = store; 21 | this.mixins.merge([ ExternalStoreMixin, ExposeStoreMixin ]); 22 | } 23 | else if( store || definition.Store ) { 24 | if( typeof store === 'function' ){ 25 | StoreClass = store as typeof Store; 26 | store = void 0; 27 | } 28 | 29 | if( store ){ 30 | const BaseClass = StoreClass || this.prototype.Store || Store; 31 | @define class InternalStore extends BaseClass { 32 | static attrbutes = store; 33 | }; 34 | 35 | this.prototype.Store = InternalStore; 36 | } 37 | else if( StoreClass ){ 38 | this.prototype.Store = StoreClass; 39 | } 40 | 41 | this.mixins.merge([ InternalStoreMixin, UpdateOnNestedChangesMixin, ExposeStoreMixin ]); 42 | } 43 | } 44 | 45 | /** 46 | * Attached whenever the store declaration of any form is present in the component. 47 | */ 48 | const ExposeStoreMixin = { 49 | childContext : { 50 | _nestedStore : Store 51 | }, 52 | 53 | getChildContext(){ 54 | return { _nestedStore : this.store }; 55 | }, 56 | 57 | getStore(){ 58 | return this.store; 59 | }, 60 | 61 | // Will be called by the store when the lookup will fail. 62 | get( key ){ 63 | // Ask upper store. 64 | const store = StateMixin.getStore.call( this ); 65 | return store && store.get( key ); 66 | } 67 | }; 68 | 69 | /** 70 | * External store must just track the changes and trigger render. 71 | * TBD: don't use it yet. 72 | */ 73 | const ExternalStoreMixin = { 74 | componentDidMount(){ 75 | // Start UI updates on state changes. 76 | this.listenTo( this.store, 'change', this.asyncUpdate ); 77 | } 78 | }; 79 | 80 | const InternalStoreMixin = { 81 | componentWillMount(){ 82 | var store = this.store = new this.Store(); 83 | store._owner = this; 84 | store._ownerKey = 'store'; 85 | }, 86 | 87 | componentWillUnmount(){ 88 | this.store._ownerKey = this.store._owner = void 0; 89 | this.store.dispose(); 90 | this.store = void 0; 91 | } 92 | }; 93 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import { ChainableAttributeSpec, define, mixinRules, mixins, type } from 'type-r'; 3 | import { Component } from './component'; 4 | import { Element, Node } from './define'; 5 | import Link from './link'; 6 | 7 | interface ReactMVx { 8 | // It's ES6 module 9 | default : ReactMVx 10 | 11 | // MixtureJS decorators... 12 | define : typeof define 13 | mixins : typeof mixins 14 | mixinRules : typeof mixinRules 15 | 16 | // Overriden components 17 | Component : typeof Component 18 | 19 | // additional ReactMVx types 20 | Link : typeof Link 21 | Node : ChainableAttributeSpec 22 | Element : ChainableAttributeSpec 23 | 24 | // Helper methods 25 | assignToState( key : string ) 26 | } 27 | 28 | // extend React namespace 29 | const ReactMVx : ReactMVx & typeof React = Object.create( React ); 30 | 31 | // Make it compatible with ES6 module format. 32 | ReactMVx.default = ReactMVx; 33 | // listenToProps, listenToState, model, attributes, Model 34 | ReactMVx.define = define; 35 | ReactMVx.mixins = mixins; 36 | 37 | ReactMVx.Node = type( Node ).value( null ); 38 | ReactMVx.Element = type( Element ).value( null ); 39 | ReactMVx.Link = Link; 40 | 41 | ReactMVx.Component = Component as any; 42 | const assignToState = ReactMVx.assignToState = key => { 43 | return function( prop ){ 44 | const source = prop && prop instanceof Link ? prop.value : prop; 45 | this.state.assignFrom({ [ key ] : source }); 46 | if( source && source._changeToken ){ 47 | this.state[ key ]._changeToken = source._changeToken; 48 | } 49 | } 50 | } 51 | 52 | export default ReactMVx; 53 | export { define, mixins, Node, Element, Link, Component, assignToState } 54 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "alwaysStrict": true, 4 | "moduleResolution": "node", 5 | "importHelpers": true, 6 | "lib": ["dom", "es2015"], 7 | "noEmitHelpers": true, 8 | "outDir": "lib", 9 | "declaration": true, 10 | "target": "es5", 11 | "module": "es6", 12 | "sourceMap": true, 13 | "jsx": "react", 14 | "baseUrl": "./", 15 | "experimentalDecorators": true, 16 | "paths": { 17 | "tslib" : ["node_modules/tslib/tslib.d.ts"] 18 | } 19 | }, 20 | "files":[ 21 | "./src/index.ts" 22 | ] 23 | } --------------------------------------------------------------------------------