UNPKG

cyclejs-modal

Version:

An easy way to open custom modals in a cyclejs app

217 lines 9.57 kB
var __assign = (this && this.__assign) || function () { __assign = Object.assign || function(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; return __assign.apply(this, arguments); }; import xs from 'xstream'; import { h } from '@cycle/dom'; import { adapt } from '@cycle/run/lib/adapt'; import { mergeSinks, extractSinks } from 'cyclejs-utils'; var ModalSource = /** @class */ (function () { function ModalSource(_namespace, _sinks$$) { if (_sinks$$ === void 0) { _sinks$$ = xs.create(); } this._namespace = _namespace; this._sinks$$ = _sinks$$; } ModalSource.prototype.select = function (id) { return new ModalSource(this._namespace, this._sinks$$.filter(function (o) { return o.id !== undefined && o.id === id; })); }; ModalSource.prototype.sinks = function (driverNames) { if (driverNames) { return extractSinks(this.sinks(), driverNames); } return this._sinks$$.map(function (o) { return o.sinks$; }).flatten(); }; ModalSource.prototype.isolateSource = function (source, scope) { return new ModalSource(source._namespace.concat(scope), source._sinks$$ .filter(function (o) { return o.namespace[0] === scope; }) .map(function (o) { return (__assign({}, o, { namespace: o.namespace.slice(1) })); })); }; ModalSource.prototype.isolateSink = function (modal$, scope) { var _this = this; return modal$.map(function (action) { return (__assign({}, action, { namespace: action.namespace ? action.namespace : _this._namespace.concat(scope) })); }); }; return ModalSource; }()); export { ModalSource }; export function modalify(main, _a) { var _b = _a === void 0 ? {} : _a, _c = _b.name, name = _c === void 0 ? 'modal' : _c, _d = _b.DOMDriverKey, DOMDriverKey = _d === void 0 ? 'DOM' : _d, _e = _b.center, center = _e === void 0 ? true : _e, _f = _b.wrapperClass, wrapperClass = _f === void 0 ? null : _f, _g = _b.modalContainerClass, modalContainerClass = _g === void 0 ? null : _g, _h = _b.background, background = _h === void 0 ? 'rgba(0,0,0,0.8)' : _h, _j = _b.zIndex, zIndex = _j === void 0 ? 500 : _j; return function (sources) { var _a, _b; var modalSource = new ModalSource([]); var parentSinks = main(__assign({}, sources, (_a = {}, _a[name] = modalSource, _a))); var sinks = Object.keys(parentSinks) .map(function (k) { var _a; return (_a = {}, _a[k] = xs.fromObservable(parentSinks[k]), _a); }) .reduce(function (prev, curr) { return Object.assign(prev, curr); }, {}); if (sinks[name]) { var modalProxy$ = xs.create(); var modalStack$ = xs .merge(sinks[name], modalProxy$) .fold(function (acc, curr) { if (curr.type === 'close') { var count = curr.count || 1; for (var i = 0; i < Math.min(acc.length, count); i++) { var _a = acc[acc.length - i - 1], id = _a[0], namespace = _a[1], _ = _a[2]; modalSource._sinks$$.shamefullySendNext({ id: id, namespace: namespace, sinks$: xs.never() }); } return acc.slice(0, Math.max(acc.length - count, 0)); } else if (curr.type === 'open') { var _sources = curr.sources !== undefined ? curr.sources : sources; var overlayClose$ = xs.never(); if (curr.backgroundOverlayClose !== false) { overlayClose$ = xs .fromObservable(sources[DOMDriverKey].select('div.cyclejs-modal').events('click')) .map(function (ev) { ev.stopPropagation(); return ev; }) .filter(function (e) { return e.target === (e.currentTarget || e.ownerTarget); }) .mapTo({ type: 'close' }); } var componentSinks_1 = curr.component(_sources); var xsComponentSinks = Object.keys(componentSinks_1) .map(function (k) { var _a; return (_a = {}, _a[k] = xs.fromObservable(componentSinks_1[k]), _a); }) .reduce(function (prev, curr) { return Object.assign(prev, curr); }, {}); var domlessSinks = __assign({}, componentSinks_1); delete domlessSinks[DOMDriverKey]; modalSource._sinks$$.shamefullySendNext({ id: curr.id, namespace: curr.namespace || [], sinks$: xs.never().startWith(domlessSinks) }); return acc.concat([ [ curr.id, curr.namespace || [], __assign({}, xsComponentSinks, { modal: xs.merge(xsComponentSinks[name] || xs.never(), overlayClose$) }) ] ]); } return acc; }, []); var modalVDom$ = modalStack$ .map(function (arr) { return arr.map(function (s) { return s[2][DOMDriverKey]; }); }) .map(function (arr) { return xs.combine.apply(xs, arr); }) .flatten(); var mergedVDom$ = xs .combine(sinks[DOMDriverKey], modalVDom$) .map(function (_a) { var vdom = _a[0], modals = _a[1]; return h('div', { attrs: { class: wrapperClass || '' } }, [ vdom, center && modals.length > 0 ? displayModals(wrapModals(modals, modalContainerClass), background, zIndex) : h('div', { attrs: { class: modalContainerClass || '' } }, modals) ]); }); var extractedSinks = extractSinks(modalStack$ .map(function (arr) { return arr.filter(function (s) { return s[0] === undefined; }).map(function (s) { return s[2]; }); }) .map(mergeSinks), Object.keys(sinks)); modalProxy$.imitate(extractedSinks[name]); var newSinks_1 = __assign({}, mergeSinks([extractedSinks, sinks]), (_b = {}, _b[DOMDriverKey] = mergedVDom$, _b)); return Object.keys(newSinks_1) .map(function (k) { var _a; return (_a = {}, _a[k] = adapt(newSinks_1[k]), _a); }) .reduce(function (prev, curr) { return Object.assign(prev, curr); }, {}); } return sinks; }; } export function centerHTML(children) { return h('div', { style: { width: '100%', height: '100%', position: 'relative', 'pointer-events': 'none' } }, children.map(function (child) { return h('div', { style: { position: 'absolute', top: '50%', left: '50%', '-ms-transform': 'translate(-50%, -50%)', '-webkit-transform': 'translate(-50%, -50%)', transform: 'translate(-50%, -50%)', 'pointer-events': 'auto' } }, [child]); })); } function displayModals(modals, background, zIndex) { if (background === void 0) { background = 'rgba(0,0,0,0.8)'; } if (zIndex === void 0) { zIndex = 500; } var processedModals = modals.map(function (m, i) { return addStyles({ 'z-index': i * 5 + 10 + zIndex }, m); }); return addStyles({ background: background, 'z-index': zIndex, top: '0px', left: '0px', position: 'fixed', width: '100%', height: '100%' }, h('div.cyclejs-modal', {}, [centerHTML(processedModals)])); } function wrapModals(modals, containerClass) { if (containerClass === void 0) { containerClass = null; } var wrapper = function (child) { return h('div', containerClass ? { attrs: { class: containerClass } } : { style: { display: 'block', padding: '10px', background: 'white', width: 'auto', height: 'auto', 'border-radius': '5px' } }, [child]); }; return modals.map(wrapper); } function addStyles(styles, vnode) { return __assign({}, vnode, { data: __assign({}, (vnode.data || {}), { style: __assign({}, (vnode.data.style || {}), styles) }) }); } //# sourceMappingURL=modalify.js.map