/** @license * Copyright 2016 - present The Material Motion Authors. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy * of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations * under the License. */ import pairwise from 'xstream/extra/pairwise' import sampleCombine from 'xstream/extra/sampleCombine' import { DOMSource } from '@cycle/dom/rxjs-typings'; import xs, { Stream } from 'xstream' import { VNode } from '@cycle/dom'; import { html } from 'snabbdom-jsx'; export type Sources = { DOM: DOMSource } export type Sinks = { DOM: Stream } // helpers moved to bottom of file for brevity export function App(sources: Sources): Sinks { const drag$ = getDrag$FromDOMSource( sources.DOM.select('.draggable') ); // This looks like the right way to implement mutual observation according to // http://staltz.com/xstream/#imitate but it isn't working. Moreover, if I // even subscribe to location$Proxy, vtree$ stops dispatching. const location$Proxy = xs.create(); const location$ = xs.merge( xs.of( { x: 0, y: 0, } ), drag$.compose( sampleCombine(location$Proxy) ).map( addPoints ) ); location$Proxy.imitate(location$); const vtree$ = location$.map( location => (
) ); const sinks = { DOM: vtree$ }; return sinks; } function getPointerLocationFromEvent(event: PointerEvent) { return { x: event.pageX, y: event.pageY, }; } function getDistanceBetweenPoints([prev, next]) { if (!prev || !next) { return { x: 0, y: 0, }; } return { x: next.x - prev.x, y: next.y - prev.y, }; } function addPoints([prev, next]) { if (!prev || !next) { return { x: 0, y: 0, }; } return { x: next.x + prev.x, y: next.y + prev.y, }; } function getDrag$FromDOMSource(domSource) { return domSource.events('pointerdown').map( downEvent => { downEvent.target.setPointerCapture(downEvent.pointerId); return domSource.events('pointermove').endWhen( domSource.events('pointerup').take() ).startWith( downEvent ).map( getPointerLocationFromEvent ).compose(pairwise).map( getDistanceBetweenPoints ) } ).flatten(); }