nested folders - viewcolor...made with esnextbin
Last active
July 18, 2017 02:39
-
-
Save bloodyKnuckles/264eda790d7211015e7178b445ed14e6 to your computer and use it in GitHub Desktop.
esnextbin sketch
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!doctype html> | |
<html> | |
<head> | |
<meta charset="utf-8"> | |
<title>nested folders - viewcolor</title> | |
<!-- put additional styles and scripts here --> | |
</head> | |
<body> | |
<div id="app"></div> | |
</body> | |
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import {run} from "@cycle/run"; | |
import {makeDOMDriver, div, button, h1, a, input, span} from '@cycle/dom' | |
import onionify, {pick, mix} from 'cycle-onionify' | |
import xs from 'xstream' | |
import isolate from '@cycle/isolate' | |
function FolderApp (sources) { | |
const initReducer$ = xs.of(function initReducer(prevState) { | |
if (typeof prevState === 'undefined') { | |
return {id: 0, color: 'yellow', viewcolor: '?', removable: false, children: []} | |
} else { | |
return prevState | |
} | |
}) | |
const identityLens = { | |
get: state => state, | |
set: (state, childState) => childState | |
}; | |
const headerSinks = isolate(Header, {onion: 'viewcolor'})(sources); | |
const headerVDom = headerSinks.DOM; | |
const childrenSinks = isolate(Folder, {onion: identityLens})(sources) | |
const childrenVDom = childrenSinks.DOM; | |
const childrenReducer$ = childrenSinks.onion; | |
const vdom$ = xs.combine(headerVDom, childrenVDom) | |
.map(([headerVNode, childrenVNode]) => | |
div([ | |
headerVNode, | |
childrenVNode | |
]) | |
); | |
const reducer$ = xs.merge(initReducer$, childrenReducer$); | |
return { | |
DOM: vdom$, | |
onion: reducer$, | |
} | |
} | |
// HEADER | |
function Header(sources) { | |
function headerView(state$) { | |
return state$ | |
.map((state) => h1('color: ' + (state || '?'))) | |
} | |
const state$ = sources.onion.state$ | |
const vdom$ = headerView(state$) | |
return { | |
DOM: vdom$ | |
} | |
} | |
// FOLDER | |
function intent(domSource) { | |
const addChild$ = domSource.select('.add').events('click') | |
.mapTo({type: 'addChild'}) | |
const removeSelf$ = domSource.select('.remove').events('click') | |
.mapTo({type: 'removeSelf'}) | |
const viewColor$ = domSource.select('.view').events('click') | |
.debug(ev => ev.preventDefault()) | |
.mapTo({type: 'viewColor'}) | |
return xs.merge(addChild$, removeSelf$, viewColor$) | |
} | |
function model(action$) { | |
const initReducer$ = xs.of(function initReducer(prevState) { | |
if (typeof prevState === 'undefined') { | |
return {id: 0, color: 'yellow', viewcolor: '?', removable: false, children: []} | |
} else { | |
return prevState | |
} | |
}) | |
const addChildReducer$ = action$ | |
.filter(({type}) => type === 'addChild') | |
.mapTo(function addFolderReducer(state) { | |
const cid = generateId() | |
const color = idToColor(cid) | |
const newChildren = state.children.concat({ | |
id: cid, | |
color: color, | |
viewcolor: undefined, | |
removable: true, | |
children: [], | |
}) | |
return { | |
...state, | |
children: newChildren, | |
} | |
}) | |
const removeSelfReducer$ = action$ | |
.filter(({type}) => type === 'removeSelf') | |
.mapTo(function removeSelfReducer(state) { | |
return undefined | |
}) | |
const viewColorReducer$ = action$ | |
.filter(({type}) => type === 'viewColor') | |
.mapTo(function viewColorReducer (state) { | |
return { | |
...state, | |
viewcolor: state.color | |
} | |
}) | |
return xs.merge(initReducer$, addChildReducer$, removeSelfReducer$, viewColorReducer$) | |
} | |
function view(state$, childrenVDOM$) { | |
return xs.combine(state$, childrenVDOM$) | |
.map(([state, childrenVDOM]) => { | |
const color = state.color | |
const removeButton = state.removable? button('.remove', ['Remove me']): span() | |
const divChildren = state.children? div({}, childrenVDOM): span() | |
return div({style: style(color)}, [ | |
a({attrs: {class: 'view', href: '#'}}, color), | |
button('.add', ['Add Folder']), | |
removeButton, | |
divChildren, | |
]) | |
}) | |
} | |
function Children(sources) { | |
const array$ = sources.onion.state$ | |
const childrenSinks$ = array$.map(array => | |
array.map((item, index) => isolate(Folder, index)(sources)) | |
) | |
const childrenReducer$ = childrenSinks$ | |
.compose(pick('onion')) | |
.compose(mix(xs.merge)) | |
const childrenVDOM$ = childrenSinks$ | |
.compose(pick('DOM')) | |
.compose(mix(xs.combine)) | |
return { | |
DOM: childrenVDOM$, | |
onion: childrenReducer$, | |
} | |
} | |
function Folder(sources) { | |
const cLens = { | |
get: state => state.children, | |
set: (state, children) => ( | |
{...state, children: children, viewcolor: children[0].viewcolor} | |
) | |
} | |
//const childrenSinks = isolate(Children, 'children')(sources) | |
const childrenSinks = isolate(Children, {onion: cLens})(sources) | |
const state$ = sources.onion.state$ | |
const action$ = intent(sources.DOM) | |
const parentReducer$ = model(action$) | |
const vdom$ = view(state$, childrenSinks.DOM) | |
const reducer$ = xs.merge(parentReducer$, childrenSinks.onion) | |
return { | |
DOM: vdom$, | |
onion: reducer$, | |
} | |
} | |
// MAIN | |
run(onionify(FolderApp), { | |
DOM: makeDOMDriver('#app') | |
}) | |
// support functions | |
function generateId() { | |
return Number(String(Math.random()).replace(/0\.0*/, '')) | |
} | |
function idToColor(id) { | |
let hexColor = Math.floor(((id + 1) * 1000) % 16777215).toString(16) | |
while (hexColor.length < 6) { | |
hexColor = '0' + hexColor | |
} | |
return '#' + hexColor | |
} | |
function style(backgroundColor) { | |
return { | |
backgroundColor, | |
padding: '2em', | |
width: 'auto', | |
border: '2px solid black', | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"name": "nested folders - viewcolor", | |
"version": "0.0.0", | |
"dependencies": { | |
"@cycle/run": "3.1.0", | |
"@cycle/dom": "17.4.0", | |
"cycle-onionify": "3.1.0", | |
"xstream": "10.8.0", | |
"@cycle/isolate": "3.0.0", | |
"babel-runtime": "6.23.0" | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'use strict'; | |
var _extends2 = require('babel-runtime/helpers/extends'); | |
var _extends3 = _interopRequireDefault(_extends2); | |
var _slicedToArray2 = require('babel-runtime/helpers/slicedToArray'); | |
var _slicedToArray3 = _interopRequireDefault(_slicedToArray2); | |
var _run = require('@cycle/run'); | |
var _dom = require('@cycle/dom'); | |
var _cycleOnionify = require('cycle-onionify'); | |
var _cycleOnionify2 = _interopRequireDefault(_cycleOnionify); | |
var _xstream = require('xstream'); | |
var _xstream2 = _interopRequireDefault(_xstream); | |
var _isolate = require('@cycle/isolate'); | |
var _isolate2 = _interopRequireDefault(_isolate); | |
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | |
function FolderApp(sources) { | |
var initReducer$ = _xstream2.default.of(function initReducer(prevState) { | |
if (typeof prevState === 'undefined') { | |
return { id: 0, color: 'yellow', viewcolor: '?', removable: false, children: [] }; | |
} else { | |
return prevState; | |
} | |
}); | |
var identityLens = { | |
get: function get(state) { | |
return state; | |
}, | |
set: function set(state, childState) { | |
return childState; | |
} | |
}; | |
var headerSinks = (0, _isolate2.default)(Header, { onion: 'viewcolor' })(sources); | |
var headerVDom = headerSinks.DOM; | |
var childrenSinks = (0, _isolate2.default)(Folder, { onion: identityLens })(sources); | |
var childrenVDom = childrenSinks.DOM; | |
var childrenReducer$ = childrenSinks.onion; | |
var vdom$ = _xstream2.default.combine(headerVDom, childrenVDom).map(function (_ref) { | |
var _ref2 = (0, _slicedToArray3.default)(_ref, 2), | |
headerVNode = _ref2[0], | |
childrenVNode = _ref2[1]; | |
return (0, _dom.div)([headerVNode, childrenVNode]); | |
}); | |
var reducer$ = _xstream2.default.merge(initReducer$, childrenReducer$); | |
return { | |
DOM: vdom$, | |
onion: reducer$ | |
}; | |
} | |
// HEADER | |
function Header(sources) { | |
function headerView(state$) { | |
return state$.map(function (state) { | |
return (0, _dom.h1)('color: ' + (state || '?')); | |
}); | |
} | |
var state$ = sources.onion.state$; | |
var vdom$ = headerView(state$); | |
return { | |
DOM: vdom$ | |
}; | |
} | |
// FOLDER | |
function intent(domSource) { | |
var addChild$ = domSource.select('.add').events('click').mapTo({ type: 'addChild' }); | |
var removeSelf$ = domSource.select('.remove').events('click').mapTo({ type: 'removeSelf' }); | |
var viewColor$ = domSource.select('.view').events('click').debug(function (ev) { | |
return ev.preventDefault(); | |
}).mapTo({ type: 'viewColor' }); | |
return _xstream2.default.merge(addChild$, removeSelf$, viewColor$); | |
} | |
function model(action$) { | |
var initReducer$ = _xstream2.default.of(function initReducer(prevState) { | |
if (typeof prevState === 'undefined') { | |
return { id: 0, color: 'yellow', viewcolor: '?', removable: false, children: [] }; | |
} else { | |
return prevState; | |
} | |
}); | |
var addChildReducer$ = action$.filter(function (_ref3) { | |
var type = _ref3.type; | |
return type === 'addChild'; | |
}).mapTo(function addFolderReducer(state) { | |
var cid = generateId(); | |
var color = idToColor(cid); | |
var newChildren = state.children.concat({ | |
id: cid, | |
color: color, | |
viewcolor: undefined, | |
removable: true, | |
children: [] | |
}); | |
return (0, _extends3.default)({}, state, { | |
children: newChildren | |
}); | |
}); | |
var removeSelfReducer$ = action$.filter(function (_ref4) { | |
var type = _ref4.type; | |
return type === 'removeSelf'; | |
}).mapTo(function removeSelfReducer(state) { | |
return undefined; | |
}); | |
var viewColorReducer$ = action$.filter(function (_ref5) { | |
var type = _ref5.type; | |
return type === 'viewColor'; | |
}).mapTo(function viewColorReducer(state) { | |
return (0, _extends3.default)({}, state, { | |
viewcolor: state.color | |
}); | |
}); | |
return _xstream2.default.merge(initReducer$, addChildReducer$, removeSelfReducer$, viewColorReducer$); | |
} | |
function view(state$, childrenVDOM$) { | |
return _xstream2.default.combine(state$, childrenVDOM$).map(function (_ref6) { | |
var _ref7 = (0, _slicedToArray3.default)(_ref6, 2), | |
state = _ref7[0], | |
childrenVDOM = _ref7[1]; | |
var color = state.color; | |
var removeButton = state.removable ? (0, _dom.button)('.remove', ['Remove me']) : (0, _dom.span)(); | |
var divChildren = state.children ? (0, _dom.div)({}, childrenVDOM) : (0, _dom.span)(); | |
return (0, _dom.div)({ style: style(color) }, [(0, _dom.a)({ attrs: { class: 'view', href: '#' } }, color), (0, _dom.button)('.add', ['Add Folder']), removeButton, divChildren]); | |
}); | |
} | |
function Children(sources) { | |
var array$ = sources.onion.state$; | |
var childrenSinks$ = array$.map(function (array) { | |
return array.map(function (item, index) { | |
return (0, _isolate2.default)(Folder, index)(sources); | |
}); | |
}); | |
var childrenReducer$ = childrenSinks$.compose((0, _cycleOnionify.pick)('onion')).compose((0, _cycleOnionify.mix)(_xstream2.default.merge)); | |
var childrenVDOM$ = childrenSinks$.compose((0, _cycleOnionify.pick)('DOM')).compose((0, _cycleOnionify.mix)(_xstream2.default.combine)); | |
return { | |
DOM: childrenVDOM$, | |
onion: childrenReducer$ | |
}; | |
} | |
function Folder(sources) { | |
var cLens = { | |
get: function get(state) { | |
return state.children; | |
}, | |
set: function set(state, children) { | |
return (0, _extends3.default)({}, state, { children: children, viewcolor: children[0].viewcolor }); | |
} | |
//const childrenSinks = isolate(Children, 'children')(sources) | |
};var childrenSinks = (0, _isolate2.default)(Children, { onion: cLens })(sources); | |
var state$ = sources.onion.state$; | |
var action$ = intent(sources.DOM); | |
var parentReducer$ = model(action$); | |
var vdom$ = view(state$, childrenSinks.DOM); | |
var reducer$ = _xstream2.default.merge(parentReducer$, childrenSinks.onion); | |
return { | |
DOM: vdom$, | |
onion: reducer$ | |
}; | |
} | |
// MAIN | |
(0, _run.run)((0, _cycleOnionify2.default)(FolderApp), { | |
DOM: (0, _dom.makeDOMDriver)('#app') | |
} | |
// support functions | |
);function generateId() { | |
return Number(String(Math.random()).replace(/0\.0*/, '')); | |
} | |
function idToColor(id) { | |
var hexColor = Math.floor((id + 1) * 1000 % 16777215).toString(16); | |
while (hexColor.length < 6) { | |
hexColor = '0' + hexColor; | |
} | |
return '#' + hexColor; | |
} | |
function style(backgroundColor) { | |
return { | |
backgroundColor: backgroundColor, | |
padding: '2em', | |
width: 'auto', | |
border: '2px solid black' | |
}; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment