├── .babelrc ├── .eslintrc ├── .gitignore ├── .npmignore ├── .travis.yml ├── LICENSE ├── README.md ├── package.json ├── preact-photon.js ├── preact-photon.js.map ├── src └── index.js └── test └── index.js /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "loose": "all", 3 | "modules": "umd", 4 | "sourceMaps": true, 5 | "nonStandard": true, 6 | "compact": true, 7 | "comments": false, 8 | "jsxPragma": "h" 9 | } 10 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "parser": "babel-eslint" 3 | } 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /dist 2 | /node_modules 3 | /npm-debug.log 4 | .DS_Store 5 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | .babelrc 2 | .eslintrc 3 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - 4 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Jason Miller 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # preact-photon 2 | 3 | [![NPM](http://img.shields.io/npm/v/preact-photon.svg?style=flat)](https://www.npmjs.org/package/preact-photon) 4 | [![travis-ci](https://travis-ci.org/developit/preact-photon.svg?branch=master)](https://travis-ci.org/developit/preact-photon) 5 | 6 | 7 | A little wrapper around [photon] to make it cake to use via [preact] _(or React `*`)_. 8 | 9 | This requires that you already have the [photon] CSS included in your app. 10 | 11 | ## What does it look like? 12 | 13 | Well, this: **[Preact + Photon = <3](http://codepen.io/developit/pen/ZbajXQ?editors=001)** _(@ [CodePen](http://codepen.io/developit/pen/ZbajXQ?editors=001) or [JSFiddle](https://jsfiddle.net/developit/g5qnLnue/))_ 14 | 15 | 16 | 17 | 18 | --- 19 | 20 | 21 | ## Usage 22 | 23 | ```js 24 | import { h, render } from 'preact'; 25 | import { Header, Title, Footer, Button } from 'preact-photon'; 26 | 27 | /** Example app component */ 28 | const App = () => ( 29 |
30 |
31 | Great App 32 | 33 |
34 | 35 |
36 | Hello there. 37 |
38 | 39 | 42 |
43 | ); 44 | 45 | render(, document.body); 46 | ``` 47 | 48 | ## Quick Start App 49 | 50 | See [preact-photon-electron-quick-start](https://github.com/alexkrolick/preact-photon-electron-quick-start) for a batteries-included starter app. 51 | 52 | --- 53 | 54 | ## License 55 | 56 | [MIT] 57 | 58 | --- 59 | 60 | `*` ... though I haven't tested it. 61 | 62 | [photon]: https://github.com/connors/photon 63 | [preact]: https://github.com/developit/preact 64 | [MIT]: http://choosealicense.com/licenses/mit 65 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "preact-photon", 3 | "version": "1.3.0", 4 | "description": "Preact + Photon = <3", 5 | "main": "preact-photon.js", 6 | "scripts": { 7 | "build": "babel -f $npm_package_main -s -o $npm_package_main < src/index.js", 8 | "test": "eslint src test && mocha --compilers js:babel/register test/**/*.js", 9 | "prepublish": "npm run build", 10 | "release": "npm run build && git commit -am $npm_package_version && git tag $npm_package_version && git push && git push --tags && npm publish" 11 | }, 12 | "keywords": [ 13 | "preact", 14 | "photon", 15 | "electron" 16 | ], 17 | "repository": { 18 | "type": "git", 19 | "url": "https://github.com/developit/preact-photon.git" 20 | }, 21 | "author": "Jason Miller ", 22 | "license": "MIT", 23 | "bugs": { 24 | "url": "https://github.com/developit/preact-photon/issues" 25 | }, 26 | "homepage": "https://github.com/developit/preact-photon", 27 | "implicitDependencies": { 28 | "photon": "git+https://github.com/connors/photon.git#v0.1-alpha" 29 | }, 30 | "peerDependencies": { 31 | "preact": "*" 32 | }, 33 | "devDependencies": { 34 | "babel": "^5.8.23", 35 | "babel-eslint": "^7.0.0", 36 | "chai": "^3.5.0", 37 | "eslint": "^3.1.0", 38 | "mocha": "^3.0.0", 39 | "preact": "^7.2.0", 40 | "preact-render-to-string": "^3.0.0" 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /preact-photon.js: -------------------------------------------------------------------------------- 1 | (function(global,factory){if(typeof define === 'function' && define.amd){define(['exports','preact'],factory);}else if(typeof exports !== 'undefined'){factory(exports,require('preact'));}else {var mod={exports:{}};factory(mod.exports,global.preact);global.preactPhoton = mod.exports;}})(this,function(exports,_preact){'use strict';exports.__esModule = true;var _extends=Object.assign || function(target){for(var i=1;i < arguments.length;i++) {var source=arguments[i];for(var key in source) {if(Object.prototype.hasOwnProperty.call(source,key)){target[key] = source[key];}}}return target;};function _objectWithoutProperties(obj,keys){var target={};for(var i in obj) {if(keys.indexOf(i) >= 0)continue;if(!Object.prototype.hasOwnProperty.call(obj,i))continue;target[i] = obj[i];}return target;}var EMPTY={};var component=function component(render){return function(){var props=arguments.length <= 0 || arguments[0] === undefined?EMPTY:arguments[0];return render(props);};};var c=function c(){var _ref;for(var _len=arguments.length,args=Array(_len),_key=0;_key < _len;_key++) {args[_key] = arguments[_key];}return (_ref = []).concat.apply(_ref,args.filter(function(x){return x;})).join(' ');};var componentNode=function componentNode(Name,classes){return component(function(_ref2){var children=_ref2.children;var props=_objectWithoutProperties(_ref2,['children']);return _preact.h(Name,_extends({},props,{'class':c(props['class'],classes)}),children);});};var Header=componentNode('header',['toolbar toolbar-header']);exports.Header = Header;var Footer=componentNode('footer',['toolbar toolbar-footer']);exports.Footer = Footer;var Title=componentNode('h1','title');exports.Title = Title;var ButtonGroup=componentNode('div','btn-group');exports.ButtonGroup = ButtonGroup;var Button=component(function(_ref3){var className=_ref3['class'];var children=_ref3.children;var icon=_ref3.icon;var type=_ref3.type;var primary=_ref3.primary;var dropdown=_ref3.dropdown;var mini=_ref3.mini;var large=_ref3.large;var form=_ref3.form;var props=_objectWithoutProperties(_ref3,['class','children','icon','type','primary','dropdown','mini','large','form']);return _preact.h('button',_extends({},props,{'class':c(className,'btn btn-' + (type || (primary?'primary':'default')),dropdown && 'btn-dropdown',large && 'btn-large',mini && 'btn-mini',form && 'btn-form')}),icon?_preact.h(Icon,{name:icon,text:children && children.length?true:null}):null,children);});exports.Button = Button;var Icon=component(function(_ref4){var className=_ref4['class'];var text=_ref4.text;var name=_ref4.name;var children=_ref4.children;var props=_objectWithoutProperties(_ref4,['class','text','name','children']);return _preact.h('span',_extends({},props,{'class':c(className,'icon icon-' + name,text && 'icon-text')}),children);});exports.Icon = Icon;var TabGroup=componentNode('div','tab-group');exports.TabGroup = TabGroup;var Tab=component(function(_ref5){var className=_ref5['class'];var close=_ref5.close;var children=_ref5.children;var props=_objectWithoutProperties(_ref5,['class','close','children']);return _preact.h('div',{'class':c(className,'tab-item')},String(close) === 'false'?null:_preact.h(Icon,{name:'cancel','class':'icon-close-tab'}),children);});exports.Tab = Tab;TabGroup.Item = Tab;var NavGroup=componentNode('nav','nav-group');exports.NavGroup = NavGroup;NavGroup.Title = componentNode('h5','nav-group-title');NavGroup.Item = component(function(_ref6){var className=_ref6['class'];var icon=_ref6.icon;var children=_ref6.children;var props=_objectWithoutProperties(_ref6,['class','icon','children']);return _preact.h('span',_extends({},props,{'class':c(className,'nav-group-item')}),icon?_preact.h(Icon,{name:icon}):null,children);});var ListGroup=componentNode('ul','list-group');exports.ListGroup = ListGroup;ListGroup.Header = componentNode('li','list-group-header');ListGroup.Item = componentNode('li','list-group-item');var Form=componentNode('form');Form.Group = componentNode('div','form-group');Form.CheckBox = component(function(_ref7){var className=_ref7['class'];var name=_ref7.name;var checked=_ref7.checked;var value=_ref7.value;var label=_ref7.label;var children=_ref7.children;var props=_objectWithoutProperties(_ref7,['class','name','checked','value','label','children']);return _preact.h('div',_extends({},props,{'class':c(className,'checkbox')}),_preact.h('label',null,_preact.h('input',{type:'checkbox',name:name,checked:checked,value:value}),label || null,children));});Form.Radio = component(function(_ref8){var className=_ref8['class'];var name=_ref8.name;var checked=_ref8.checked;var value=_ref8.value;var label=_ref8.label;var children=_ref8.children;var props=_objectWithoutProperties(_ref8,['class','name','checked','value','label','children']);return _preact.h('div',_extends({},props,{'class':c(className,'radio')}),_preact.h('label',null,_preact.h('input',{type:'radio',name:name,checked:checked,value:value}),label || null,children));});Form.Actions = componentNode('div','form-actions');var Table=component(function(_ref9){var className=_ref9['class'];var striped=_ref9.striped;var children=_ref9.children;var props=_objectWithoutProperties(_ref9,['class','striped','children']);return _preact.h('table',_extends({},props,{'class':c(className,striped && 'table-striped')}),children);});exports.Table = Table;}); 2 | 3 | //# sourceMappingURL=preact-photon.js.map -------------------------------------------------------------------------------- /preact-photon.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"sources":["preact-photon.js"],"names":[],"mappings":"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","file":"preact-photon.js","sourcesContent":["/** @jsx h */\nimport { h } from 'preact';\n\nconst EMPTY = {};\n\n/** @private */\nlet component = render => (props=EMPTY) => render(props);\n\n/** @private */\nlet c = (...args) => [].concat(...args.filter( x => x )).join(' ');\n\n/** @private */\nlet componentNode = (Name, classes) => component( ({ children, ...props }) => (\n\t{children}\n));\n\n/** App \"footer\" bar, shown at the bottom of a window.\n *\t@class\n */\nexport const Header = componentNode('header', ['toolbar toolbar-header']);\n\n/** App \"header\" bar, shown at the top of a window.\n *\t@class\n */\nexport const Footer = componentNode('footer', ['toolbar toolbar-footer']);\n\n/** Toolbar title.\n *\t@class\n */\nexport const Title = componentNode('h1', 'title');\n\n\n/** Group buttons together.\n *\t@class\n *\t@example\n *\t\n *\t\t\n *\t\t\n *\t\n */\nexport const ButtonGroup = componentNode('div', 'btn-group');\n\n/** Buttons. They are clickable.\n *\t@class\n *\t@param {object} props\n *\t@param {string} [icon]\t\t\t\tIf supplied, shows the given named icon to the left of the button text\n *\t@param {boolean} [primary=false]\tMake the button display as a default action\n *\t@example\n *\t\n *\t@example\n *\t\n *\t@example\n *\t\n *\t@example\n *\t\n *\t@example\n *\t\n *\t@example\n *\t\n *\t@example\n *\t\n *\t@example\n *\t\n */\nexport const Button = component( ({\n\tclass: className,\n\tchildren,\n\ticon,\n\ttype,\n\tprimary,\n\tdropdown,\n\tmini,\n\tlarge,\n\tform,\n\t...props\n}) => (\n\t\n));\n\n\n/** A named icon/glyph from the nice built-in list of icons.\n *\t@class\n *\t@example\n *\t\n */\nexport const Icon = component( ({ class:className, text, name, children, ...props }) => (\n\t{ children }\n));\n\n\n/** Groups tabs together into a horizontal.\n *\t@class\n *\t@example\n *\t\n *\t\tOne\n *\t\tTwo\n *\t\n */\nexport const TabGroup = componentNode('div', 'tab-group');\n\n/** For building MDIs. Has a close button by default, add `close=\"false\"` to turn it off.\n *\t@class\n *\t@example\n *\ttitle\n *\t@example\n *\ttitle\n */\nexport const Tab = component( ({ class:className, close, children, ...props }) => (\n\t
\n\t\t{ String(close)==='false' ? null : }\n\t\t{ children }\n\t
\n));\n\nTabGroup.Item = Tab;\n\n\n/** Group of sidebar navigation items\n *\t@class\n *\t@example\n *\t\n *\t\tFaves\n *\t\tFoo\n *\t\n */\nexport const NavGroup = componentNode('nav', 'nav-group');\n\n/** Title for a group of navigation items.\n *\t@class\n *\t@example\n *\tFaves\n */\nNavGroup.Title = componentNode('h5', 'nav-group-title');\n\n/** A single navigation item with optional icon.\n *\t@class\n *\t@example\n *\tHome\n *\t@example\n *\tDocuments\n */\nNavGroup.Item = component( ({ class:className, icon, children, ...props }) => (\n\t\n\t\t{ icon ? () : null }\n\t\t{ children }\n\t\n));\n\n\n/** Group of list items\n *\t@class\n *\t@example\n *\t\n *\t\t\n *\t\t\t\n *\t\t\n *\t\tFoo\n *\t\n */\nexport const ListGroup = componentNode('ul', 'list-group');\n\n/** Top header item in a list group.\n *\t@class\n *\t@example\n *\t\n *\t\t\n *\t\n */\nListGroup.Header = componentNode('li', 'list-group-header');\n\n/** A single navigation item with optional icon.\n *\t@class\n *\t@example\n *\tHome\n */\nListGroup.Item = componentNode('li', 'list-group-item');\n\n\n/** HTML `
` */\nconst Form = componentNode('form');\n\n/** Basically `
` */\nForm.Group = componentNode('div', 'form-group');\n\n/** Basically `` */\nForm.CheckBox = component( ({ class:className, name, checked, value, label, children, ...props }) => (\n\t
\n\t\t\n\t
\n));\n\n/** Basically `` */\nForm.Radio = component( ({ class:className, name, checked, value, label, children, ...props }) => (\n\t
\n\t\t\n\t
\n));\n\n/** Group buttons at the bottom of a form. */\nForm.Actions = componentNode('div', 'form-actions');\n\n\n/** Just an enhanced `` */\nexport const Table = component( ({ class:className, striped, children, ...props }) => (\n\t
\n\t\t{ children }\n\t
\n));\n\n\n// export class Header extends Component {\n// \trender({ toolbar, title, children }) {\n// \t\treturn (\n// \t\t\t
\n// \t\t\t\t{ title ? (

{ title }

) : null }\n// \t\t\t\t{ children }\n// \t\t\t
\n// \t\t);\n// \t}\n// }\n//\n// export class Button extends Component {\n// \trender({ icon, children }) {\n// \t\treturn (\n// \t\t\t\n// \t\t);\n// \t}\n// }\n"]} -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | /** @jsx h */ 2 | import { h } from 'preact'; 3 | 4 | const EMPTY = {}; 5 | 6 | /** @private */ 7 | let component = render => (props=EMPTY) => render(props); 8 | 9 | /** @private */ 10 | let c = (...args) => [].concat(...args.filter( x => x )).join(' '); 11 | 12 | /** @private */ 13 | let componentNode = (Name, classes) => component( ({ children, ...props }) => ( 14 | {children} 15 | )); 16 | 17 | /** App "footer" bar, shown at the bottom of a window. 18 | * @class 19 | */ 20 | export const Header = componentNode('header', ['toolbar toolbar-header']); 21 | 22 | /** App "header" bar, shown at the top of a window. 23 | * @class 24 | */ 25 | export const Footer = componentNode('footer', ['toolbar toolbar-footer']); 26 | 27 | /** Toolbar title. 28 | * @class 29 | */ 30 | export const Title = componentNode('h1', 'title'); 31 | 32 | 33 | /** Group buttons together. 34 | * @class 35 | * @example 36 | * 37 | * 38 | * 39 | * 40 | */ 41 | export const ButtonGroup = componentNode('div', 'btn-group'); 42 | 43 | /** Buttons. They are clickable. 44 | * @class 45 | * @param {object} props 46 | * @param {string} [icon] If supplied, shows the given named icon to the left of the button text 47 | * @param {boolean} [primary=false] Make the button display as a default action 48 | * @example 49 | * 50 | * @example 51 | * 52 | * @example 53 | * 54 | * @example 55 | * 56 | * @example 57 | * 58 | * @example 59 | * 60 | * @example 61 | * 62 | * @example 63 | * 64 | */ 65 | export const Button = component( ({ 66 | class: className, 67 | children, 68 | icon, 69 | type, 70 | primary, 71 | dropdown, 72 | mini, 73 | large, 74 | form, 75 | ...props 76 | }) => ( 77 | 88 | )); 89 | 90 | 91 | /** A named icon/glyph from the nice built-in list of icons. 92 | * @class 93 | * @example 94 | * 95 | */ 96 | export const Icon = component( ({ class:className, text, name, children, ...props }) => ( 97 | { children } 98 | )); 99 | 100 | 101 | /** Groups tabs together into a horizontal. 102 | * @class 103 | * @example 104 | * 105 | * One 106 | * Two 107 | * 108 | */ 109 | export const TabGroup = componentNode('div', 'tab-group'); 110 | 111 | /** For building MDIs. Has a close button by default, add `close="false"` to turn it off. 112 | * @class 113 | * @example 114 | * title 115 | * @example 116 | * title 117 | */ 118 | export const Tab = component( ({ class:className, close, children, ...props }) => ( 119 |
120 | { String(close)==='false' ? null : } 121 | { children } 122 |
123 | )); 124 | 125 | TabGroup.Item = Tab; 126 | 127 | 128 | /** Group of sidebar navigation items 129 | * @class 130 | * @example 131 | * 132 | * Faves 133 | * Foo 134 | * 135 | */ 136 | export const NavGroup = componentNode('nav', 'nav-group'); 137 | 138 | /** Title for a group of navigation items. 139 | * @class 140 | * @example 141 | * Faves 142 | */ 143 | NavGroup.Title = componentNode('h5', 'nav-group-title'); 144 | 145 | /** A single navigation item with optional icon. 146 | * @class 147 | * @example 148 | * Home 149 | * @example 150 | * Documents 151 | */ 152 | NavGroup.Item = component( ({ class:className, icon, children, ...props }) => ( 153 | 154 | { icon ? () : null } 155 | { children } 156 | 157 | )); 158 | 159 | 160 | /** Group of list items 161 | * @class 162 | * @example 163 | * 164 | * 165 | * 166 | * 167 | * Foo 168 | * 169 | */ 170 | export const ListGroup = componentNode('ul', 'list-group'); 171 | 172 | /** Top header item in a list group. 173 | * @class 174 | * @example 175 | * 176 | * 177 | * 178 | */ 179 | ListGroup.Header = componentNode('li', 'list-group-header'); 180 | 181 | /** A single navigation item with optional icon. 182 | * @class 183 | * @example 184 | * Home 185 | */ 186 | ListGroup.Item = componentNode('li', 'list-group-item'); 187 | 188 | 189 | /** HTML `` */ 190 | const Form = componentNode('form'); 191 | 192 | /** Basically `
` */ 193 | Form.Group = componentNode('div', 'form-group'); 194 | 195 | /** Basically `` */ 196 | Form.CheckBox = component( ({ class:className, name, checked, value, label, children, ...props }) => ( 197 |
198 | 203 |
204 | )); 205 | 206 | /** Basically `` */ 207 | Form.Radio = component( ({ class:className, name, checked, value, label, children, ...props }) => ( 208 |
209 | 214 |
215 | )); 216 | 217 | /** Group buttons at the bottom of a form. */ 218 | Form.Actions = componentNode('div', 'form-actions'); 219 | 220 | 221 | /** Just an enhanced `` */ 222 | export const Table = component( ({ class:className, striped, children, ...props }) => ( 223 |
224 | { children } 225 |
226 | )); 227 | 228 | 229 | // export class Header extends Component { 230 | // render({ toolbar, title, children }) { 231 | // return ( 232 | //
233 | // { title ? (

{ title }

) : null } 234 | // { children } 235 | //
236 | // ); 237 | // } 238 | // } 239 | // 240 | // export class Button extends Component { 241 | // render({ icon, children }) { 242 | // return ( 243 | // 247 | // ); 248 | // } 249 | // } 250 | -------------------------------------------------------------------------------- /test/index.js: -------------------------------------------------------------------------------- 1 | import { expect } from 'chai'; 2 | import { h } from 'preact'; 3 | import render from 'preact-render-to-string'; 4 | import { 5 | Header, 6 | Footer, 7 | Title, 8 | TabGroup, 9 | Tab, 10 | Button 11 | } from '../src'; 12 | 13 | /** @jsx h */ 14 | 15 | describe('preact-photon', () => { 16 | describe('
', () => { 17 | it('should render the correct HTML', () => { 18 | expect(render(
)).to.equal('
'); 19 | }); 20 | 21 | it('should render children', () => { 22 | expect(render(
foo
)).to.equal('
foo
'); 23 | }); 24 | }); 25 | 26 | describe('