Skip to content

Instantly share code, notes, and snippets.

@bloodyKnuckles
Last active July 18, 2017 02:39
Show Gist options
  • Save bloodyKnuckles/264eda790d7211015e7178b445ed14e6 to your computer and use it in GitHub Desktop.
Save bloodyKnuckles/264eda790d7211015e7178b445ed14e6 to your computer and use it in GitHub Desktop.
esnextbin sketch

nested folders - viewcolor...made with esnextbin

<!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>
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',
}
}
{
"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"
}
}
'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