Comparing version 0.3.4 to 0.3.5
@@ -13,3 +13,3 @@ { | ||
"typescript": "1.8.7", | ||
"dompteuse": "0.3.4", | ||
"dompteuse": "0.3.5", | ||
"snabbdom": "0.4.2", | ||
@@ -16,0 +16,0 @@ "most": "0.19.6", |
@@ -38,3 +38,3 @@ import { api as router } from 'abyssa' | ||
function initState() { | ||
return merge({ users: [], loading: false }, readGlobalState()) | ||
return merge({ users: [], loading: true }, readGlobalState()) | ||
} | ||
@@ -77,12 +77,6 @@ | ||
const refreshes = messages.listen(RefreshSelect).startWith(undefined).multicast() | ||
const userData = refreshes | ||
.map(getSomeUsers) | ||
.switch() | ||
.multicast() | ||
const refreshes = messages.listen(RefreshSelect) | ||
const userData = refreshes.map(getSomeUsers).startWith(getSomeUsers()).switch().multicast() | ||
const loading = most.merge( | ||
refreshes.map(_ => true), | ||
userData.map(_ => false) | ||
) | ||
const loading = most.merge(refreshes.constant(true), userData.constant(false)) | ||
@@ -95,12 +89,17 @@ return [userData, loading] | ||
return h('div#blue', [ | ||
h('h1', 'Blue screen'), | ||
h('a', { attrs: { href: router.link('app.blue.green', { id }), 'data-nav': 'mousedown' } }, 'Green'), | ||
h('a', { attrs: { href: router.link('app.blue.red', { id }), 'data-nav': 'mousedown' } }, 'Red'), | ||
h('div.increment', [ | ||
'Count: ' + state.count, | ||
h('button', { events: { onClick: Increment } }, 'Increment') | ||
]), | ||
contentAnimation('section', getChildren(state)) | ||
]) | ||
const greenHref = router.link('app.blue.green', { id }) | ||
const redHref = router.link('app.blue.red', { id }) | ||
return ( | ||
h('div#blue', [ | ||
h('h1', 'Blue screen'), | ||
h('a', { attrs: { href: greenHref, 'data-nav': 'mousedown' } }, 'Green'), | ||
h('a', { attrs: { href: redHref, 'data-nav': 'mousedown' } }, 'Red'), | ||
h('div.increment', [ | ||
'Count: ' + state.count, | ||
h('button', { events: { onClick: Increment } }, 'Increment') | ||
]), | ||
contentAnimation('section', getChildren(state)) | ||
]) | ||
) | ||
} | ||
@@ -107,0 +106,0 @@ |
@@ -61,22 +61,26 @@ import { Component, h, Message, ConnectParams } from 'dompteuse' | ||
return h('div#green', [ | ||
`Green (route id = ${id})`, | ||
h('form', [ | ||
input('firstName', firstName), | ||
input('lastName', lastName) | ||
]), | ||
h('button', { events: { onClick: ShowPopup } }, 'Open popup'), | ||
popupEl | ||
]) | ||
return ( | ||
h('div#green', [ | ||
`Green (route id = ${id})`, | ||
h('form', [ | ||
input('firstName', firstName), | ||
input('lastName', lastName) | ||
]), | ||
h('button', { events: { onClick: ShowPopup } }, 'Open popup'), | ||
popupEl | ||
]) | ||
) | ||
} | ||
function input(name: string, value: string) { | ||
return h('label', [ | ||
name, | ||
h('input', { | ||
props: { name }, | ||
forceProps: { value }, | ||
events: { onInput: InputChanged } | ||
}) | ||
]) | ||
return ( | ||
h('label', [ | ||
name, | ||
h('input', { | ||
props: { name }, | ||
forceProps: { value }, | ||
events: { onInput: InputChanged } | ||
}) | ||
]) | ||
) | ||
} | ||
@@ -83,0 +87,0 @@ |
@@ -46,7 +46,9 @@ | ||
return h('div', { | ||
content, | ||
attrs: { 'data-popup': true }, | ||
hook: { insert, postpatch, destroy } | ||
}) | ||
return ( | ||
h('div', { | ||
content, | ||
attrs: { 'data-popup': true }, | ||
hook: { insert, postpatch, destroy } | ||
}) | ||
) | ||
} | ||
@@ -81,5 +83,7 @@ | ||
function popupWithContent(content: Array<Vnode>) { | ||
return h('div.overlay', { hook: animationHook, events: { onClick: OverlayClick } }, [ | ||
h('div.popup', content) | ||
]) | ||
return ( | ||
h('div.overlay', { hook: animationHook, events: { onClick: OverlayClick } }, [ | ||
h('div.popup', content) | ||
]) | ||
) | ||
} | ||
@@ -86,0 +90,0 @@ |
@@ -59,10 +59,12 @@ import update from 'immupdate' | ||
return h('div.select', [ | ||
h('input', { | ||
events: { onClick: Open, onBlur: Close }, | ||
props: { value: text }, | ||
attrs: { readonly: true, placeholder: 'click me' } | ||
}), | ||
dropdownEl | ||
]) | ||
return ( | ||
h('div.select', [ | ||
h('input', { | ||
events: { onClick: Open, onBlur: Close }, | ||
props: { value: text }, | ||
attrs: { readonly: true, placeholder: 'click me' } | ||
}), | ||
dropdownEl | ||
]) | ||
) | ||
} | ||
@@ -87,8 +89,3 @@ | ||
function renderItem(item: any) { | ||
function onMouseDown(evt: Event) { | ||
return ItemSelected(item) | ||
} | ||
return h('li', { events: { onMouseDown } }, item) | ||
return h('li', { events: { onMouseDown: ItemSelected.with(item) } }, String(item)) | ||
} | ||
@@ -95,0 +92,0 @@ |
@@ -24,6 +24,2 @@ 'use strict'; | ||
var _log = require('./log'); | ||
var _log2 = _interopRequireDefault(_log); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
@@ -104,6 +100,3 @@ | ||
if (!(0, _shallowEqual2.default)(oldState, newState)) { | ||
if (_log2.default.stream) console.log('Component state updated %c' + component.key, 'font-weight: bold', component.state); | ||
(0, _render.renderComponentAsync)(component); | ||
} | ||
if (!(0, _shallowEqual2.default)(oldState, newState)) (0, _render.renderComponentAsync)(component); | ||
}); | ||
@@ -132,3 +125,3 @@ | ||
// Called on every re-render, this is where the props passed by the component's parent may have changed. | ||
// Called on every parent re-render, this is where the props passed by the component's parent may have changed. | ||
function postpatch(oldVnode, vnode) { | ||
@@ -140,8 +133,8 @@ var oldData = oldVnode.data; | ||
var oldProps = component.props; | ||
var newProps = newData.component.props; | ||
// Pass on the component instance everytime a new Vnode instance is created, | ||
// but update any important property that can change over time. | ||
component.props = newData.component.props; | ||
component.render = newData.component.render; | ||
// Update the original component with any property that may have changed on this render | ||
component.props = newProps; | ||
component.placeholder = vnode; | ||
newData.component = component; | ||
@@ -151,3 +144,3 @@ | ||
// in the render context of our parent | ||
if (!(0, _shallowEqual2.default)(component.props, oldProps)) (0, _render.renderComponentSync)(component); | ||
if (!(0, _shallowEqual2.default)(oldProps, newProps)) (0, _render.renderComponentSync)(component); | ||
} | ||
@@ -154,0 +147,0 @@ |
// dompteuse internals | ||
// startApp | ||
@@ -10,2 +10,4 @@ export function startApp<S>(options: { | ||
// Components | ||
interface StreamSub<S> { | ||
@@ -32,2 +34,4 @@ <A>(stream: Stream<A>, cb: (state: S, value: A) => S|void): Stream<A>; | ||
// dompteuse internals | ||
export var log: { | ||
@@ -38,5 +42,13 @@ render: boolean; | ||
export type NoArgMessage = () => MessagePayload<void>; | ||
export type Message<P> = (payload: P) => MessagePayload<P>; | ||
// Messages & Events | ||
export interface NoArgMessage { | ||
(): MessagePayload<void>; | ||
} | ||
export interface Message<P> { | ||
(payload: P): MessagePayload<P>; | ||
with(payload: P): [Message<P>, P] | ||
} | ||
export function Message(name: string): NoArgMessage; | ||
@@ -53,3 +65,5 @@ export function Message<P>(name: string): Message<P>; | ||
listen<P>(message: Message<P>): Stream<P>; | ||
listen(message: NoArgMessage): Stream<void>; | ||
listenAt<P>(selector: string, message: Message<P>): Stream<P>; | ||
listenAt(selector: string, message: NoArgMessage): Stream<void>; | ||
send<P>(payload: MessagePayload<P>): void; | ||
@@ -62,4 +76,19 @@ } | ||
export var patch: PatchFunction; | ||
// Global stream | ||
interface OnMessage<S> { | ||
(message: NoArgMessage, handler: (state: S) => S): void; | ||
<P>(message: Message<P>, handler: (state: S, payload: P) => S): void; | ||
} | ||
type GlobalStream<S> = Stream<S> & { | ||
value: S | ||
send: <P>(payload: MessagePayload<P>) => void | ||
} | ||
export function GlobalStream<S>( | ||
initialState: S, | ||
registerHandlers: (on: OnMessage<S>) => void): GlobalStream<S>; | ||
// most | ||
@@ -75,6 +104,9 @@ | ||
type EventHandler = NoArgMessage | Message<Event> | [ Message<any>, any ] | ||
interface VnodeData { | ||
[s: string]: any; | ||
hook?: Hooks; | ||
events?: { [s: string]: NoArgMessage | Message<Event> }; | ||
events?: { [s: string]: EventHandler }; | ||
} | ||
@@ -110,16 +142,2 @@ | ||
// GlobalStream | ||
interface OnMessage<S> { | ||
(message: NoArgMessage, handler: (state: S) => S): void; | ||
<P>(message: Message<P>, handler: (state: S, payload: P) => S): void; | ||
} | ||
type GlobalStream<S> = Stream<S> & { | ||
value: S | ||
send: <P>(payload: MessagePayload<P>) => void | ||
} | ||
export function GlobalStream<S>( | ||
initialState: S, | ||
registerHandlers: (on: OnMessage<S>) => void): GlobalStream<S>; | ||
export var patch: PatchFunction; |
@@ -29,4 +29,8 @@ 'use strict'; | ||
if (old !== current) vnode.elm[name.toLowerCase()] = function (evt) { | ||
var payload = current(evt); | ||
(0, _messages._sendToNode)(evt.target, payload); | ||
var _ref = Array.isArray(current) ? current : [current, evt]; | ||
var msg = _ref[0]; | ||
var arg = _ref[1]; | ||
(0, _messages._sendToNode)(evt.target, msg(arg)); | ||
}; | ||
@@ -33,0 +37,0 @@ }; |
@@ -40,5 +40,5 @@ 'use strict'; | ||
// TODO: Is it even useful to prevent redispatching since we have async redraws? We could push to a temp queue. | ||
// The scenario would be: in the middle of a msg handling, we want to conditionally dispatch another msg. | ||
if (log) console.log('%c' + _name, 'color: #C93CBD', 'sent globally with payload ', payload); | ||
if (dispatching) throw new Error('Cannot dispatch a Msg in the middle of another msg\'s dispatch'); | ||
@@ -45,0 +45,0 @@ |
@@ -1,2 +0,2 @@ | ||
'use strict'; | ||
"use strict"; | ||
@@ -6,8 +6,2 @@ exports.__esModule = true; | ||
var _log = require('./log'); | ||
var _log2 = _interopRequireDefault(_log); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
var messageId = 1; | ||
@@ -21,4 +15,2 @@ | ||
function message(payload) { | ||
if (_log2.default.stream) console.log('%c' + name, 'color: #FAACF3', 'dispatched with payload ', payload); | ||
return { _id: _id, _name: name, payload: payload }; | ||
@@ -31,2 +23,6 @@ } | ||
message.with = function (payload) { | ||
return [message, payload]; | ||
}; | ||
// Allows Actions to be used as Object keys with the correct behavior | ||
@@ -33,0 +29,0 @@ message.toString = function () { |
@@ -11,2 +11,6 @@ 'use strict'; | ||
var _log = require('./log'); | ||
var _log2 = _interopRequireDefault(_log); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
@@ -83,3 +87,7 @@ | ||
// Classic component's listen | ||
if (parentEl.__comp__) return parentEl.__comp__.messages._receive(msg); | ||
if (parentEl.__comp__) { | ||
if (_log2.default) console.log('%c' + msg._name, 'color: #FAACF3', 'sent locally to', parentEl, 'with payload ', msg.payload); | ||
return parentEl.__comp__.messages._receive(msg); | ||
} | ||
// listenAt | ||
@@ -89,3 +97,4 @@ else if (parentEl.__subs__) return parentEl.__subs__.filter(function (sub) { | ||
}).forEach(function (sub) { | ||
return sub.streamAdd(msg.payload); | ||
if (_log2.default) console.log('%c' + msg._name, 'color: #FAACF3', 'sent locally to', parentEl, 'with payload ', msg.payload); | ||
sub.streamAdd(msg.payload); | ||
}); | ||
@@ -92,0 +101,0 @@ |
@@ -31,7 +31,13 @@ 'use strict'; | ||
logBeginRender(); | ||
var emptyVnode = (0, _vnode2.default)('div', { key: '_init' }, [], undefined, appElm); | ||
Render.patch(emptyVnode, app); | ||
var el = document.createElement('div'); | ||
var emptyVnode = (0, _vnode2.default)('div', { key: '_init' }, [], undefined, el); | ||
var appNode = Render.patch(emptyVnode, app); | ||
newComponents.forEach(function (c) { | ||
return c.lifecycle.inserted(c); | ||
}); | ||
appElm.appendChild(appNode.elm); | ||
logEndRender(); | ||
@@ -90,3 +96,3 @@ } | ||
var renderTime = Math.round((performance.now() - beforeRender) * 100) / 100; | ||
console.log('Render component %c' + component.key, 'font-weight: bold', renderTime + ' ms', component); | ||
console.log('Render component %c' + component.key, 'font-weight: bold', renderTime + ' ms', props, state); | ||
} | ||
@@ -93,0 +99,0 @@ |
{ | ||
"name": "dompteuse", | ||
"version": "0.3.4", | ||
"version": "0.3.5", | ||
"main": "lib/dompteuse", | ||
@@ -5,0 +5,0 @@ "typings": "lib/dompteuse.d.ts", |
@@ -231,2 +231,8 @@ # dompteuse | ||
h('div', { events: { onClick: SomeMessage } }) | ||
// Or prepare the message to be sent with an argument. | ||
// This is more efficient than creating a closure on every render. | ||
const AnotherMessage = Message<{x: number}>('anotherMessage') | ||
h('div', { events: { onClick: AnotherMessage.with({ x: 3 }) } }) | ||
``` | ||
@@ -233,0 +239,0 @@ |
@@ -7,5 +7,3 @@ import h from 'snabbdom/h'; | ||
import Messages from './messages'; | ||
import log from './log'; | ||
const empty = {}; | ||
@@ -76,7 +74,4 @@ | ||
if (!shallowEqual(oldState, newState)) { | ||
if (log.stream) | ||
console.log(`Component state updated %c${component.key}`, 'font-weight: bold', component.state); | ||
if (!shallowEqual(oldState, newState)) | ||
renderComponentAsync(component); | ||
} | ||
}); | ||
@@ -103,3 +98,3 @@ | ||
// Called on every re-render, this is where the props passed by the component's parent may have changed. | ||
// Called on every parent re-render, this is where the props passed by the component's parent may have changed. | ||
function postpatch(oldVnode, vnode) { | ||
@@ -111,8 +106,8 @@ const oldData = oldVnode.data; | ||
const oldProps = component.props; | ||
const newProps = newData.component.props; | ||
// Pass on the component instance everytime a new Vnode instance is created, | ||
// but update any important property that can change over time. | ||
component.props = newData.component.props; | ||
component.render = newData.component.render; | ||
// Update the original component with any property that may have changed on this render | ||
component.props = newProps; | ||
component.placeholder = vnode; | ||
newData.component = component; | ||
@@ -122,3 +117,3 @@ | ||
// in the render context of our parent | ||
if (!shallowEqual(component.props, oldProps)) | ||
if (!shallowEqual(oldProps, newProps)) | ||
renderComponentSync(component); | ||
@@ -125,0 +120,0 @@ } |
@@ -20,4 +20,4 @@ import most from 'most'; | ||
vnode.elm[name.toLowerCase()] = function(evt) { | ||
const payload = current(evt); | ||
_sendToNode(evt.target, payload); | ||
const [msg, arg] = Array.isArray(current) ? current : [current, evt]; | ||
_sendToNode(evt.target, msg(arg)); | ||
}; | ||
@@ -24,0 +24,0 @@ } |
@@ -25,4 +25,5 @@ /* Opt-in, convenience construct used to update a global stream imperatively and in a type safe fashion */ | ||
// TODO: Is it even useful to prevent redispatching since we have async redraws? We could push to a temp queue. | ||
// The scenario would be: in the middle of a msg handling, we want to conditionally dispatch another msg. | ||
if (log) | ||
console.log('%c' + _name, 'color: #C93CBD', 'sent globally with payload ', payload); | ||
if (dispatching) throw new Error( | ||
@@ -56,3 +57,3 @@ 'Cannot dispatch a Msg in the middle of another msg\'s dispatch'); | ||
} | ||
}) | ||
}); | ||
@@ -59,0 +60,0 @@ stream.value = initialState; |
@@ -1,4 +0,2 @@ | ||
import defaultLog from './log'; | ||
let messageId = 1; | ||
@@ -12,5 +10,2 @@ | ||
function message(payload) { | ||
if (defaultLog.stream) | ||
console.log('%c' + name, 'color: #FAACF3', 'dispatched with payload ', payload); | ||
return { _id, _name: name, payload }; | ||
@@ -23,2 +18,4 @@ } | ||
message.with = payload => [message, payload]; | ||
// Allows Actions to be used as Object keys with the correct behavior | ||
@@ -25,0 +22,0 @@ message.toString = () => _id; |
import most from 'most'; | ||
import log from './log'; | ||
export default function Messages(componentDestruction) { | ||
@@ -75,4 +77,8 @@ this.componentDestruction = componentDestruction; | ||
// Classic component's listen | ||
if (parentEl.__comp__) | ||
if (parentEl.__comp__) { | ||
if (log) console.log('%c' + msg._name, 'color: #FAACF3', | ||
'sent locally to', parentEl , 'with payload ', msg.payload); | ||
return parentEl.__comp__.messages._receive(msg); | ||
} | ||
// listenAt | ||
@@ -82,3 +88,7 @@ else if (parentEl.__subs__) | ||
.filter(sub => sub.messageType._id === msg._id) | ||
.forEach(sub => sub.streamAdd(msg.payload)); | ||
.forEach(sub => { | ||
if (log) console.log('%c' + msg._name, 'color: #FAACF3', | ||
'sent locally to', parentEl , 'with payload ', msg.payload); | ||
sub.streamAdd(msg.payload); | ||
}); | ||
@@ -85,0 +95,0 @@ parentEl = parentEl.parentElement; |
@@ -17,5 +17,11 @@ | ||
logBeginRender(); | ||
const emptyVnode = Vnode('div', { key: '_init' }, [], undefined, appElm); | ||
Render.patch(emptyVnode, app); | ||
const el = document.createElement('div'); | ||
const emptyVnode = Vnode('div', { key: '_init' }, [], undefined, el); | ||
const appNode = Render.patch(emptyVnode, app); | ||
newComponents.forEach(c => c.lifecycle.inserted(c)); | ||
appElm.appendChild(appNode.elm); | ||
logEndRender(); | ||
@@ -68,3 +74,3 @@ } | ||
const renderTime = Math.round((performance.now() - beforeRender) * 100) / 100; | ||
console.log(`Render component %c${component.key}`, 'font-weight: bold', renderTime + ' ms', component); | ||
console.log(`Render component %c${component.key}`, 'font-weight: bold', renderTime + ' ms', props, state); | ||
} | ||
@@ -71,0 +77,0 @@ |
// dompteuse internals | ||
// startApp | ||
@@ -10,2 +10,4 @@ export function startApp<S>(options: { | ||
// Components | ||
interface StreamSub<S> { | ||
@@ -32,2 +34,4 @@ <A>(stream: Stream<A>, cb: (state: S, value: A) => S|void): Stream<A>; | ||
// dompteuse internals | ||
export var log: { | ||
@@ -38,5 +42,13 @@ render: boolean; | ||
export type NoArgMessage = () => MessagePayload<void>; | ||
export type Message<P> = (payload: P) => MessagePayload<P>; | ||
// Messages & Events | ||
export interface NoArgMessage { | ||
(): MessagePayload<void>; | ||
} | ||
export interface Message<P> { | ||
(payload: P): MessagePayload<P>; | ||
with(payload: P): [Message<P>, P] | ||
} | ||
export function Message(name: string): NoArgMessage; | ||
@@ -53,3 +65,5 @@ export function Message<P>(name: string): Message<P>; | ||
listen<P>(message: Message<P>): Stream<P>; | ||
listen(message: NoArgMessage): Stream<void>; | ||
listenAt<P>(selector: string, message: Message<P>): Stream<P>; | ||
listenAt(selector: string, message: NoArgMessage): Stream<void>; | ||
send<P>(payload: MessagePayload<P>): void; | ||
@@ -62,4 +76,19 @@ } | ||
export var patch: PatchFunction; | ||
// Global stream | ||
interface OnMessage<S> { | ||
(message: NoArgMessage, handler: (state: S) => S): void; | ||
<P>(message: Message<P>, handler: (state: S, payload: P) => S): void; | ||
} | ||
type GlobalStream<S> = Stream<S> & { | ||
value: S | ||
send: <P>(payload: MessagePayload<P>) => void | ||
} | ||
export function GlobalStream<S>( | ||
initialState: S, | ||
registerHandlers: (on: OnMessage<S>) => void): GlobalStream<S>; | ||
// most | ||
@@ -75,6 +104,9 @@ | ||
type EventHandler = NoArgMessage | Message<Event> | [ Message<any>, any ] | ||
interface VnodeData { | ||
[s: string]: any; | ||
hook?: Hooks; | ||
events?: { [s: string]: NoArgMessage | Message<Event> }; | ||
events?: { [s: string]: EventHandler }; | ||
} | ||
@@ -110,16 +142,2 @@ | ||
// GlobalStream | ||
interface OnMessage<S> { | ||
(message: NoArgMessage, handler: (state: S) => S): void; | ||
<P>(message: Message<P>, handler: (state: S, payload: P) => S): void; | ||
} | ||
type GlobalStream<S> = Stream<S> & { | ||
value: S | ||
send: <P>(payload: MessagePayload<P>) => void | ||
} | ||
export function GlobalStream<S>( | ||
initialState: S, | ||
registerHandlers: (on: OnMessage<S>) => void): GlobalStream<S>; | ||
export var patch: PatchFunction; |
Sorry, the diff of this file is too big to display
1375993
55
14500
353