export default function LichessChat(element: Element, opts: ChatOpts): { preset: PresetCtrl } { const patch = init([klass, attributes]); const container = element.parentNode as HTMLElement; let vnode: VNode, ctrl: Ctrl function redraw() { vnode = patch(vnode, view(ctrl)); } ctrl = makeCtrl(opts, redraw); const blueprint = view(ctrl); element.innerHTML = ''; vnode = patch(element, blueprint); window.Mousetrap.bind('c', () => { (container.querySelector('.mchat__say') as HTMLElement).focus(); return false; }); return ctrl; };
export function init<A>(emit: (_: A) => void): (old: VNode<A> | Element, vnode: VNode<A>) => VNode<A> { return S.init([ ClassModule, PropsModule, AttrsModule, StyleModule, DatasetModule, createModuleListener(emit) ]) as any; }
function makeDOMDriver( container: string | Element | DocumentFragment, options?: DOMDriverOptions, ): Driver<Stream<VNode>, MainDOMSource> { if (!options) { options = {}; } const modules = options.modules || defaultModules; const isolateModule = new IsolateModule(); const patch = init([isolateModule.createModule()].concat(modules)); const rootElement = getValidNode(container) || document.body; const vnodeWrapper = new VNodeWrapper(rootElement); const delegators = new MapPolyfill<string, EventDelegator>(); makeDOMDriverInputGuard(modules); function DOMDriver(vnode$: Stream<VNode>, name = 'DOM'): MainDOMSource { domDriverInputGuard(vnode$); const sanitation$ = xs.create<null>(); const rootElement$ = xs .merge(vnode$.endWhen(sanitation$), sanitation$) .map(vnode => vnodeWrapper.call(vnode)) .fold(patch, toVNode(rootElement)) .drop(1) .map(unwrapElementFromVNode) .compose(dropCompletion) // don't complete this stream .startWith(rootElement as any); // Start the snabbdom patching, over time const listener = {error: reportSnabbdomError}; if (document.readyState === 'loading') { document.addEventListener('readystatechange', () => { if (document.readyState === 'interactive') { rootElement$.addListener(listener); } }); } else { rootElement$.addListener(listener); } return new MainDOMSource( rootElement$, sanitation$, [], isolateModule, delegators, name, ); } return DOMDriver as any; }
export function app(opts: RoundOpts): RoundApi { const patch = init([klass, attributes]); let vnode: VNode, ctrl: RoundController; function redraw() { vnode = patch(vnode, view(ctrl)); } ctrl = new RoundController(opts, redraw); const blueprint = view(ctrl); opts.element.innerHTML = ''; vnode = patch(opts.element, blueprint); return { socketReceive: ctrl.socket.receive, moveOn: ctrl.moveOn }; };
export default function injectUI(streamContainer: Element) { var nfeContainer = document.createElement('div'); nfeContainer.id = 'nfe-container'; streamContainer.appendChild(nfeContainer); const patch = init([propsModule, attrsModule, eventsModule]); let vnode = toVNode(nfeContainer); storePromise .then(store => { const render = () => { const newVnode = h('div#nfe-container', [NewsFeedEradicator(store)]); patch(vnode, newVnode); vnode = newVnode; }; render(); store.subscribe(render); }) .catch(handleError); }
/// <reference types="types/lichess" /> import { init } from 'snabbdom'; import { VNode } from 'snabbdom/vnode' import makeCtrl from './ctrl'; import view from './view'; import { NotifyOpts, Ctrl } from './interfaces' import klass from 'snabbdom/modules/class'; import attributes from 'snabbdom/modules/attributes'; const patch = init([klass, attributes]); export default function LichessNotify(element: Element, opts: NotifyOpts) { let vnode: VNode, ctrl: Ctrl function redraw() { vnode = patch(vnode, view(ctrl)); } ctrl = makeCtrl(opts, redraw); vnode = patch(element, view(ctrl)); if (opts.data) ctrl.update(opts.data, opts.incoming); else ctrl.loadPage(1); return { update: ctrl.update,
function makeDOMDriver( container: string | Element | DocumentFragment, options?: DOMDriverOptions ): Driver<Stream<VNode>, MainDOMSource> { if (!options) { options = {}; } checkValidContainer(container); const modules = options.modules || defaultModules; makeDOMDriverInputGuard(modules); const isolateModule = new IsolateModule(); const patch = init([isolateModule.createModule()].concat(modules)); const domReady$ = makeDOMReady$(); let vnodeWrapper: VNodeWrapper; let mutationObserver: MutationObserver; const mutationConfirmed$ = xs.create<null>({ start(listener) { mutationObserver = new MutationObserver(() => listener.next(null)); }, stop() { mutationObserver.disconnect(); }, }); function DOMDriver(vnode$: Stream<VNode>, name = 'DOM'): MainDOMSource { domDriverInputGuard(vnode$); const sanitation$ = xs.create<null>(); const firstRoot$ = domReady$.map(() => { const firstRoot = getValidNode(container) || document.body; vnodeWrapper = new VNodeWrapper(firstRoot); return firstRoot; }); // We need to subscribe to the sink (i.e. vnode$) synchronously inside this // driver, and not later in the map().flatten() because this sink is in // reality a SinkProxy from @cycle/run, and we don't want to miss the first // emission when the main() is connected to the drivers. // Read more in issue #739. const rememberedVNode$ = vnode$.remember(); rememberedVNode$.addListener({}); // The mutation observer internal to mutationConfirmed$ should // exist before elementAfterPatch$ calls mutationObserver.observe() mutationConfirmed$.addListener({}); const elementAfterPatch$ = firstRoot$ .map( firstRoot => xs .merge(rememberedVNode$.endWhen(sanitation$), sanitation$) .map(vnode => vnodeWrapper.call(vnode)) .startWith(addRootScope(toVNode(firstRoot))) .fold(patch, toVNode(firstRoot)) .drop(1) .map(unwrapElementFromVNode) .startWith(firstRoot as any) .map(el => { mutationObserver.observe(el, { childList: true, attributes: true, characterData: true, subtree: true, attributeOldValue: true, characterDataOldValue: true, }); return el; }) .compose(dropCompletion) // don't complete this stream ) .flatten(); const rootElement$ = concat(domReady$, mutationConfirmed$) .endWhen(sanitation$) .compose(sampleCombine(elementAfterPatch$)) .map(arr => arr[1]) .remember(); // Start the snabbdom patching, over time rootElement$.addListener({error: reportSnabbdomError}); const delegator = new EventDelegator(rootElement$, isolateModule); return new MainDOMSource( rootElement$, sanitation$, [], isolateModule, delegator, name ); } return DOMDriver as any; }