nested folders - hey...made with esnextbin
Last active
July 6, 2017 14:45
-
-
Save bloodyKnuckles/4fcdf8e118fe06f7401f73fd50068841 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 - hey</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 App (sources) { | |
const vdom$ = Folder(sources).DOM.map(vdom => { | |
//console.log(vdom) | |
return div([span('hey'), vdom]) | |
}) | |
const reducer$ = Folder(sources).onion | |
return { DOM: vdom$, onion: reducer$ } | |
} | |
function intent(domSource) { | |
const addChild$ = domSource.select('.add').events('click') | |
.mapTo({type: 'addChild'}) | |
const removeSelf$ = domSource.select('.remove').events('click') | |
.mapTo({type: 'removeSelf'}) | |
return xs.merge(addChild$, removeSelf$) | |
} | |
function model(action$) { | |
const initReducer$ = xs.of(function initReducer(prevState) { | |
if (typeof prevState === 'undefined') { | |
return {id: 0, removable: false, children: []} | |
} else { | |
return prevState | |
} | |
}) | |
const addChildReducer$ = action$ | |
.filter(({type}) => type === 'addChild') | |
.mapTo(function addFolderReducer(state) { | |
const newChildren = state.children.concat({ | |
id: generateId(), | |
removable: true, | |
children: [], | |
}) | |
return { | |
...state, | |
children: newChildren, | |
} | |
}) | |
const removeSelfReducer$ = action$ | |
.filter(({type}) => type === 'removeSelf') | |
.mapTo(function removeSelfReducer(state) { | |
return undefined | |
}) | |
return xs.merge(initReducer$, addChildReducer$, removeSelfReducer$) | |
} | |
function view(state$, childrenVDOM$) { | |
return xs.combine(state$, childrenVDOM$) | |
.map(([state, childrenVDOM]) => { | |
const color = idToColor(state.id) | |
const removeButton = state.removable? button('.remove', ['Remove me']): span() | |
const divChildren = state.children? div({}, childrenVDOM): span() | |
return div({style: style(color)}, [ | |
a({attrs: {href: '#', class: 'fun'}}, 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, childState) => ({...state, children: childState}) | |
} | |
//const childrenSinks = isolate(Children, 'children')(sources) | |
const childrenSinks = isolate(Children, {DOM: ':root', 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$, | |
} | |
} | |
run(onionify(App), { DOM: makeDOMDriver('#app') }) | |
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 - hey", | |
"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 _slicedToArray2 = require('babel-runtime/helpers/slicedToArray'); | |
var _slicedToArray3 = _interopRequireDefault(_slicedToArray2); | |
var _extends2 = require('babel-runtime/helpers/extends'); | |
var _extends3 = _interopRequireDefault(_extends2); | |
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 App(sources) { | |
var vdom$ = Folder(sources).DOM.map(function (vdom) { | |
//console.log(vdom) | |
return (0, _dom.div)([(0, _dom.span)('hey'), vdom]); | |
}); | |
var reducer$ = Folder(sources).onion; | |
return { DOM: vdom$, onion: reducer$ }; | |
} | |
function intent(domSource) { | |
var addChild$ = domSource.select('.add').events('click').mapTo({ type: 'addChild' }); | |
var removeSelf$ = domSource.select('.remove').events('click').mapTo({ type: 'removeSelf' }); | |
return _xstream2.default.merge(addChild$, removeSelf$); | |
} | |
function model(action$) { | |
var initReducer$ = _xstream2.default.of(function initReducer(prevState) { | |
if (typeof prevState === 'undefined') { | |
return { id: 0, removable: false, children: [] }; | |
} else { | |
return prevState; | |
} | |
}); | |
var addChildReducer$ = action$.filter(function (_ref) { | |
var type = _ref.type; | |
return type === 'addChild'; | |
}).mapTo(function addFolderReducer(state) { | |
var newChildren = state.children.concat({ | |
id: generateId(), | |
removable: true, | |
children: [] | |
}); | |
return (0, _extends3.default)({}, state, { | |
children: newChildren | |
}); | |
}); | |
var removeSelfReducer$ = action$.filter(function (_ref2) { | |
var type = _ref2.type; | |
return type === 'removeSelf'; | |
}).mapTo(function removeSelfReducer(state) { | |
return undefined; | |
}); | |
return _xstream2.default.merge(initReducer$, addChildReducer$, removeSelfReducer$); | |
} | |
function view(state$, childrenVDOM$) { | |
return _xstream2.default.combine(state$, childrenVDOM$).map(function (_ref3) { | |
var _ref4 = (0, _slicedToArray3.default)(_ref3, 2), | |
state = _ref4[0], | |
childrenVDOM = _ref4[1]; | |
var color = idToColor(state.id); | |
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: { href: '#', class: 'fun' } }, 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, childState) { | |
return (0, _extends3.default)({}, state, { children: childState }); | |
} | |
//const childrenSinks = isolate(Children, 'children')(sources) | |
};var childrenSinks = (0, _isolate2.default)(Children, { DOM: ':root', 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$ | |
}; | |
} | |
(0, _run.run)((0, _cycleOnionify2.default)(App), { DOM: (0, _dom.makeDOMDriver)('#app') }); | |
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