Comparing version 0.3.1 to 0.3.2
@@ -13,3 +13,3 @@ { | ||
"typescript": "1.8.7", | ||
"dompteuse": "0.3.1", | ||
"dompteuse": "0.3.2", | ||
"snabbdom": "0.4.2", | ||
@@ -16,0 +16,0 @@ "most": "0.19.6", |
@@ -50,2 +50,2 @@ import { api as router } from 'abyssa' | ||
//setInterval(appState.emit.bind(null, incrementBlue()), 2500) | ||
//setInterval(appState.send.bind(null, incrementBlue()), 2500) |
@@ -7,3 +7,4 @@ import { Component, h, Message, ConnectParams } from 'dompteuse' | ||
import red from './red' | ||
import { merge } from './util/util' | ||
import { merge } from './util/obj' | ||
import popup, * as Popup from './util/popup' | ||
@@ -22,2 +23,3 @@ | ||
const RedOpened = Message('redOpened') | ||
const ShowPopup = Message('showPopup') | ||
@@ -28,2 +30,3 @@ interface State { | ||
redText: string | ||
popupOpened: boolean | ||
} | ||
@@ -35,3 +38,4 @@ | ||
form: {}, | ||
redText: '' | ||
redText: '', | ||
popupOpened: false | ||
} | ||
@@ -58,8 +62,13 @@ } | ||
) | ||
on(ShowPopup, state => merge(state, { popupOpened: true })) | ||
on(Popup.Close, state => merge(state, { popupOpened: false })) | ||
} | ||
function render(props: void, state: State) { | ||
const { id, form, redText } = state | ||
const { id, form, redText, popupOpened } = state | ||
const { firstName, lastName } = form | ||
const popupEl = popupOpened ? helloPopup() : '' | ||
return h('div#green', [ | ||
@@ -74,3 +83,5 @@ `Green (route id = ${id})`, | ||
onOpened: RedOpened | ||
}) | ||
}), | ||
h('button', { events: { onClick: ShowPopup } }, 'Open popup'), | ||
popupEl | ||
]) | ||
@@ -89,1 +100,10 @@ } | ||
} | ||
function helloPopup() { | ||
const content = [ | ||
h('h2', 'Hello'), | ||
h('button', { events: { onClick: Popup.Close } }, 'Close') | ||
] | ||
return popup({ content }) | ||
} |
import './logger' | ||
import { snabbdom, startApp } from 'dompteuse' | ||
import { startApp } from 'dompteuse' | ||
import app from './app' | ||
@@ -8,3 +8,4 @@ | ||
declare var require: any | ||
const snabbdomModules = [ | ||
export const snabbdomModules = [ | ||
require('snabbdom/modules/class'), | ||
@@ -17,2 +18,2 @@ require('snabbdom/modules/props'), | ||
startApp({ app, snabbdomModules, elm: document.body }) | ||
startApp({ app, snabbdomModules, elm: document.getElementById('screens') }) |
@@ -6,3 +6,3 @@ import update from 'immupdate' | ||
import appState, { incrementBlue } from './appState' | ||
import { merge } from './util/util' | ||
import { merge } from './util/obj' | ||
@@ -9,0 +9,0 @@ |
@@ -5,2 +5,3 @@ import { h } from 'dompteuse' | ||
/* Container animating its children in and out */ | ||
@@ -28,4 +29,4 @@ export default function animate(animations: Animations) { | ||
// It would be cleaner to merge the hooks in. | ||
oldVnodeChild.data['hook'] = oldVnodeChild.data['hook'] || {} | ||
oldVnodeChild.data['hook'].remove = (newVnode.data as any).animations.remove | ||
oldVnodeChild.data.hook = oldVnodeChild.data.hook || {} | ||
oldVnodeChild.data.hook.remove = (newVnode.data as any).animations.remove | ||
} | ||
@@ -55,17 +56,13 @@ } | ||
const duration = 0.2 | ||
const contentAnimations = { | ||
create: (elm: HTMLElement) => { | ||
elm.style.display = 'none' | ||
TweenLite.fromTo(elm, 0.2, | ||
{ css: { opacity: 0 } }, | ||
{ css: { opacity: 1 }, delay: 0.22, overwrite: true } | ||
).eventCallback('onStart', (): any => elm.style.removeProperty('display')) | ||
TweenLite.from(elm, duration, { opacity: 0, delay: duration + 0.02, overwrite: true }) | ||
.eventCallback('onStart', () => elm.style.removeProperty('display')) | ||
}, | ||
remove: (vnode: Vnode, cb: any) => { | ||
TweenLite.fromTo(vnode.elm, 0.2, | ||
{ css: { opacity: 1 } }, | ||
{ css: { opacity: 0 }, overwrite: true } | ||
).eventCallback('onComplete', cb) | ||
remove: (vnode: Vnode, cb: Function) => { | ||
TweenLite.to(vnode.elm, duration, { opacity: 0, overwrite: true }) | ||
.eventCallback('onComplete', cb) | ||
} | ||
@@ -72,0 +69,0 @@ }; |
@@ -11,3 +11,3 @@ { | ||
"filesGlob": [ | ||
"src/*.ts", | ||
"src/**/*.ts", | ||
"typings/main.d.ts", | ||
@@ -24,4 +24,8 @@ "typings/gsap.d.ts" | ||
"src/main.ts", | ||
"src/patch.ts", | ||
"src/red.ts", | ||
"src/util/animation.ts", | ||
"src/util/dom.ts", | ||
"src/util/gsap.ts", | ||
"src/util/obj.ts", | ||
"src/util/popup.ts", | ||
"typings/main.d.ts", | ||
@@ -28,0 +32,0 @@ "typings/gsap.d.ts" |
@@ -50,2 +50,3 @@ | ||
listen<P>(message: Message<P>): Stream<P>; | ||
listenAt<P>(selector: string, message: Message<P>): Stream<P>; | ||
send<P>(payload: MessagePayload<P>): void; | ||
@@ -58,2 +59,4 @@ } | ||
export var patch: PatchFunction; | ||
// most | ||
@@ -65,11 +68,10 @@ | ||
interface PatchFunction { | ||
_isPatchFunction: any; | ||
} | ||
export type PatchFunction = (target: Element | Vnode, vnode: Vnode) => Vnode; | ||
export var snabbdom: { init: (modules: any[]) => PatchFunction } | ||
export var snabbdom: { init: (modules: any[]) => PatchFunction }; | ||
interface VnodeData { | ||
[s: string]: any; | ||
events?: { [s: string]: NoArgMessage | Message<Event> } | ||
hook?: Hooks; | ||
events?: { [s: string]: NoArgMessage | Message<Event> }; | ||
} | ||
@@ -76,0 +78,0 @@ |
'use strict'; | ||
exports.__esModule = true; | ||
exports.h = exports.snabbdom = exports.GlobalStream = exports.log = exports.startApp = exports.Events = exports.Message = exports.Component = undefined; | ||
exports.h = exports.snabbdom = exports.patch = exports.GlobalStream = exports.log = exports.startApp = exports.Events = exports.Message = exports.Component = undefined; | ||
@@ -44,6 +44,8 @@ var _snabbdom = require('snabbdom'); | ||
var modules = snabbdomModules.concat(_events.snabbdomModule); | ||
_render2.default.patch = _snabbdom2.default.init(modules); | ||
exports.patch = patch = _render2.default.patch = _snabbdom2.default.init(modules); | ||
(0, _render.renderApp)(app, elm); | ||
} | ||
var patch = void 0; | ||
exports.Component = _component2.default; | ||
@@ -55,2 +57,3 @@ exports.Message = _message2.default; | ||
exports.GlobalStream = _globalStream.GlobalStream; | ||
exports.patch = patch; | ||
exports. | ||
@@ -57,0 +60,0 @@ |
@@ -5,3 +5,2 @@ 'use strict'; | ||
exports.snabbdomModule = undefined; | ||
exports.sendToNearestComponent = sendToNearestComponent; | ||
@@ -14,2 +13,4 @@ var _most = require('most'); | ||
var _messages = require('./messages'); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
@@ -31,3 +32,3 @@ | ||
var payload = current(evt); | ||
sendToNearestComponent(evt.target, payload); | ||
(0, _messages._sendToNode)(evt.target, payload); | ||
}; | ||
@@ -52,10 +53,2 @@ }; | ||
function sendToNearestComponent(node, message) { | ||
while (node) { | ||
if (node.__comp__) return node.__comp__.messages._receive(message); | ||
node = node.parentElement; | ||
} | ||
} | ||
/* Listens to a DOM Event using delegation */ | ||
@@ -62,0 +55,0 @@ exports.default = { |
@@ -5,2 +5,3 @@ 'use strict'; | ||
exports.default = Messages; | ||
exports._sendToNode = _sendToNode; | ||
@@ -22,3 +23,3 @@ var _most = require('most'); | ||
var stream = _most2.default.create(function (add) { | ||
return _most2.default.create(function (add) { | ||
var sub = { | ||
@@ -35,4 +36,23 @@ messageType: messageType, | ||
}).until(this.componentDestruction); | ||
}; | ||
return stream; | ||
Messages.prototype.listenAt = function (nodeSelector, messageType) { | ||
return _most2.default.create(function (add) { | ||
var el = document.querySelector(nodeSelector); | ||
if (!el) return; | ||
el.__subs__ = el.__subs__ || []; | ||
var subs = el.__subs__; | ||
var sub = { | ||
messageType: messageType, | ||
streamAdd: add | ||
}; | ||
subs.push(sub); | ||
return function () { | ||
subs.splice(subs.indexOf(sub), 1); | ||
if (subs.length === 0) el.__subs__ = undefined; | ||
}; | ||
}).until(this.componentDestruction); | ||
}; | ||
@@ -43,9 +63,3 @@ | ||
var parentEl = this.el.parentElement; | ||
while (parentEl) { | ||
if (parentEl.__comp__) return parentEl.__comp__.messages._receive(msg); | ||
parentEl = parentEl.parentElement; | ||
} | ||
_sendToNode(this.el, msg); | ||
}; | ||
@@ -65,2 +79,19 @@ | ||
} | ||
}; | ||
function _sendToNode(node, msg) { | ||
var parentEl = node.parentElement; | ||
while (parentEl) { | ||
// Classic component's listen | ||
if (parentEl.__comp__) return parentEl.__comp__.messages._receive(msg); | ||
// listenAt | ||
else if (parentEl.__subs__) return parentEl.__subs__.filter(function (sub) { | ||
return sub.messageType._id === msg._id; | ||
}).forEach(function (sub) { | ||
return sub.streamAdd(msg.payload); | ||
}); | ||
parentEl = parentEl.parentElement; | ||
} | ||
}; |
@@ -12,2 +12,6 @@ 'use strict'; | ||
var _vnode = require('snabbdom/vnode'); | ||
var _vnode2 = _interopRequireDefault(_vnode); | ||
var _log = require('./log'); | ||
@@ -82,3 +86,3 @@ | ||
patch(vnode || elm, newVnode); | ||
patch(vnode || (0, _vnode2.default)('div', { key: '_init' }, [], undefined, elm), newVnode); | ||
@@ -85,0 +89,0 @@ if (_log2.default.render) console.log('Render component \'' + component.key + '\'', performance.now() - beforeRender + ' ms', component); |
{ | ||
"name": "dompteuse", | ||
"version": "0.3.1", | ||
"version": "0.3.2", | ||
"main": "lib/dompteuse", | ||
@@ -5,0 +5,0 @@ "typings": "lib/dompteuse.d.ts", |
@@ -215,3 +215,14 @@ # dompteuse | ||
``` | ||
On top of the `snabbdom` modules you pass to `startApp`, an extra module is installed by `dompteuse`: `events`. | ||
```javascript | ||
import { Message } from 'dompteuse' | ||
const SomeMessage = Message<Event>('someMessage') | ||
// Send a message to the enclosing component on click | ||
h('div', { events: { onClick: SomeMessage } }) | ||
``` | ||
## startApp | ||
@@ -280,2 +291,7 @@ | ||
// Listen for a Message at the first Element found using the given CSS selector. | ||
// This should be rarely used, and is mostly useful for components | ||
// that attach their content to a remote DOM Element, like popups. | ||
messages.listenAt<P>(selector: string, message: Message<P>): Stream<P>; | ||
// Sends a message to the nearest parent component | ||
@@ -317,1 +333,10 @@ messages.send<P>(message: MessagePayload<P>): void | ||
``` | ||
## patch | ||
The `snabbdom` patch function that dompteuse uses. Only available after the call to `startApp` | ||
```javascript | ||
import { patch } from 'dompteuse' | ||
``` |
@@ -15,6 +15,8 @@ | ||
const modules = snabbdomModules.concat(snabbdomModule); | ||
Render.patch = snabbdom.init(modules); | ||
patch = Render.patch = snabbdom.init(modules); | ||
renderApp(app, elm); | ||
} | ||
let patch; | ||
export { | ||
@@ -27,2 +29,3 @@ Component, | ||
GlobalStream, | ||
patch, | ||
@@ -29,0 +32,0 @@ // Proxied for convenient typesafety |
import most from 'most'; | ||
import { Set } from './util'; | ||
import { _sendToNode } from './messages'; | ||
@@ -20,4 +21,4 @@ | ||
const payload = current(evt); | ||
sendToNearestComponent(evt.target, payload); | ||
} | ||
_sendToNode(evt.target, payload); | ||
}; | ||
} | ||
@@ -38,12 +39,2 @@ | ||
export function sendToNearestComponent(node, message) { | ||
while (node) { | ||
if (node.__comp__) | ||
return node.__comp__.messages._receive(message); | ||
node = node.parentElement; | ||
} | ||
} | ||
/* Listens to a DOM Event using delegation */ | ||
@@ -50,0 +41,0 @@ export default { |
@@ -11,3 +11,3 @@ import most from 'most'; | ||
const stream = most.create(add => { | ||
return most.create(add => { | ||
const sub = { | ||
@@ -25,4 +25,24 @@ messageType, | ||
.until(this.componentDestruction); | ||
}; | ||
return stream; | ||
Messages.prototype.listenAt = function(nodeSelector, messageType) { | ||
return most.create(add => { | ||
const el = document.querySelector(nodeSelector); | ||
if (!el) return; | ||
el.__subs__ = el.__subs__ || []; | ||
const subs = el.__subs__; | ||
const sub = { | ||
messageType, | ||
streamAdd: add | ||
} | ||
subs.push(sub); | ||
return () => { | ||
subs.splice(subs.indexOf(sub), 1); | ||
if (subs.length === 0) el.__subs__ = undefined; | ||
} | ||
}) | ||
.until(this.componentDestruction); | ||
}; | ||
@@ -34,10 +54,3 @@ | ||
let parentEl = this.el.parentElement; | ||
while (parentEl) { | ||
if (parentEl.__comp__) | ||
return parentEl.__comp__.messages._receive(msg); | ||
parentEl = parentEl.parentElement; | ||
} | ||
_sendToNode(this.el, msg); | ||
}; | ||
@@ -59,1 +72,18 @@ | ||
}; | ||
export function _sendToNode(node, msg) { | ||
let parentEl = node.parentElement; | ||
while (parentEl) { | ||
// Classic component's listen | ||
if (parentEl.__comp__) | ||
return parentEl.__comp__.messages._receive(msg); | ||
// listenAt | ||
else if (parentEl.__subs__) | ||
return parentEl.__subs__ | ||
.filter(sub => sub.messageType._id === msg._id) | ||
.forEach(sub => sub.streamAdd(msg.payload)); | ||
parentEl = parentEl.parentElement; | ||
} | ||
}; |
import h from 'snabbdom/h'; | ||
import Vnode from 'snabbdom/vnode'; | ||
import log from './log'; | ||
@@ -62,3 +63,3 @@ | ||
patch(vnode || elm, newVnode); | ||
patch(vnode || Vnode('div', { key: '_init' }, [], undefined, elm), newVnode); | ||
@@ -65,0 +66,0 @@ if (log.render) console.log(`Render component '${component.key}'`, |
@@ -50,2 +50,3 @@ | ||
listen<P>(message: Message<P>): Stream<P>; | ||
listenAt<P>(selector: string, message: Message<P>): Stream<P>; | ||
send<P>(payload: MessagePayload<P>): void; | ||
@@ -58,2 +59,4 @@ } | ||
export var patch: PatchFunction; | ||
// most | ||
@@ -65,11 +68,10 @@ | ||
interface PatchFunction { | ||
_isPatchFunction: any; | ||
} | ||
export type PatchFunction = (target: Element | Vnode, vnode: Vnode) => Vnode; | ||
export var snabbdom: { init: (modules: any[]) => PatchFunction } | ||
export var snabbdom: { init: (modules: any[]) => PatchFunction }; | ||
interface VnodeData { | ||
[s: string]: any; | ||
events?: { [s: string]: NoArgMessage | Message<Event> } | ||
hook?: Hooks; | ||
events?: { [s: string]: NoArgMessage | Message<Event> }; | ||
} | ||
@@ -76,0 +78,0 @@ |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
1375820
14584
340