cyclejs-modal
Version:
An easy way to open custom modals in a cyclejs app
221 lines • 10 kB
JavaScript
;
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);
};
Object.defineProperty(exports, "__esModule", { value: true });
var xstream_1 = require("xstream");
var dom_1 = require("@cycle/dom");
var adapt_1 = require("@cycle/run/lib/adapt");
var cyclejs_utils_1 = require("cyclejs-utils");
var ModalSource = /** @class */ (function () {
function ModalSource(_namespace, _sinks$$) {
if (_sinks$$ === void 0) { _sinks$$ = xstream_1.default.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 cyclejs_utils_1.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;
}());
exports.ModalSource = ModalSource;
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] = xstream_1.default.fromObservable(parentSinks[k]), _a);
})
.reduce(function (prev, curr) { return Object.assign(prev, curr); }, {});
if (sinks[name]) {
var modalProxy$ = xstream_1.default.create();
var modalStack$ = xstream_1.default
.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$: xstream_1.default.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$ = xstream_1.default.never();
if (curr.backgroundOverlayClose !== false) {
overlayClose$ = xstream_1.default
.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] = xstream_1.default.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$: xstream_1.default.never().startWith(domlessSinks)
});
return acc.concat([
[
curr.id,
curr.namespace || [],
__assign({}, xsComponentSinks, { modal: xstream_1.default.merge(xsComponentSinks[name] || xstream_1.default.never(), overlayClose$) })
]
]);
}
return acc;
}, []);
var modalVDom$ = modalStack$
.map(function (arr) { return arr.map(function (s) { return s[2][DOMDriverKey]; }); })
.map(function (arr) { return xstream_1.default.combine.apply(xstream_1.default, arr); })
.flatten();
var mergedVDom$ = xstream_1.default
.combine(sinks[DOMDriverKey], modalVDom$)
.map(function (_a) {
var vdom = _a[0], modals = _a[1];
return dom_1.h('div', { attrs: { class: wrapperClass || '' } }, [
vdom,
center && modals.length > 0
? displayModals(wrapModals(modals, modalContainerClass), background, zIndex)
: dom_1.h('div', {
attrs: {
class: modalContainerClass || ''
}
}, modals)
]);
});
var extractedSinks = cyclejs_utils_1.extractSinks(modalStack$
.map(function (arr) {
return arr.filter(function (s) { return s[0] === undefined; }).map(function (s) { return s[2]; });
})
.map(cyclejs_utils_1.mergeSinks), Object.keys(sinks));
modalProxy$.imitate(extractedSinks[name]);
var newSinks_1 = __assign({}, cyclejs_utils_1.mergeSinks([extractedSinks, sinks]), (_b = {}, _b[DOMDriverKey] = mergedVDom$, _b));
return Object.keys(newSinks_1)
.map(function (k) {
var _a;
return (_a = {}, _a[k] = adapt_1.adapt(newSinks_1[k]), _a);
})
.reduce(function (prev, curr) { return Object.assign(prev, curr); }, {});
}
return sinks;
};
}
exports.modalify = modalify;
function centerHTML(children) {
return dom_1.h('div', {
style: {
width: '100%',
height: '100%',
position: 'relative',
'pointer-events': 'none'
}
}, children.map(function (child) {
return dom_1.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]);
}));
}
exports.centerHTML = centerHTML;
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%'
}, dom_1.h('div.cyclejs-modal', {}, [centerHTML(processedModals)]));
}
function wrapModals(modals, containerClass) {
if (containerClass === void 0) { containerClass = null; }
var wrapper = function (child) {
return dom_1.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