From 9dfa5d6f3c7c944b34c099421a8b033f4739e056 Mon Sep 17 00:00:00 2001 From: "Shahar Or (mightyiam)" Date: Wed, 5 Apr 2017 21:26:10 +0300 Subject: [PATCH] type VNode props (fixes #264) --- src/helpers/attachto.ts | 37 ++++++++++++++++++++++++++----------- src/modules/style.ts | 10 ++++++++-- src/vnode.ts | 32 ++++++++++++++++++++++---------- 3 files changed, 56 insertions(+), 23 deletions(-) diff --git a/src/helpers/attachto.ts b/src/helpers/attachto.ts index 0d42493..77f81c5 100755 --- a/src/helpers/attachto.ts +++ b/src/helpers/attachto.ts @@ -1,30 +1,45 @@ import {VNode, VNodeData} from '../vnode'; -function pre(vnode: VNode, newVnode: VNode): void { - const attachData = (vnode.data as VNodeData).attachData; +export interface AttachData { + [key: string]: any + [i: number]: any + placeholder?: any + real?: Node +} + +interface VNodeDataWithAttach extends VNodeData { + attachData: AttachData +} + +interface VNodeWithAttachData extends VNode { + data: VNodeDataWithAttach +} + +function pre(vnode: VNodeWithAttachData, newVnode: VNodeWithAttachData): void { + const attachData = vnode.data.attachData; // Copy created placeholder and real element from old vnode - (newVnode.data as VNodeData).attachData.placeholder = attachData.placeholder; - (newVnode.data as VNodeData).attachData.real = attachData.real; + newVnode.data.attachData.placeholder = attachData.placeholder; + newVnode.data.attachData.real = attachData.real; // Mount real element in vnode so the patch process operates on it - vnode.elm = (vnode.data as VNodeData).attachData.real; + vnode.elm = vnode.data.attachData.real; } -function post(_: any, vnode: VNode): void { +function post(_: any, vnode: VNodeWithAttachData): void { // Mount dummy placeholder in vnode so potential reorders use it - vnode.elm = (vnode.data as VNodeData).attachData.placeholder; + vnode.elm = vnode.data.attachData.placeholder; } -function destroy(vnode: VNode): void { +function destroy(vnode: VNodeWithAttachData): void { // Remove placeholder if (vnode.elm !== undefined) { (vnode.elm.parentNode as HTMLElement).removeChild(vnode.elm); } // Remove real element from where it was inserted - vnode.elm = (vnode.data as VNodeData).attachData.real; + vnode.elm = vnode.data.attachData.real; } -function create(_: any, vnode: VNode): void { - const real = vnode.elm, attachData = (vnode.data as VNodeData).attachData; +function create(_: any, vnode: VNodeWithAttachData): void { + const real = vnode.elm, attachData = vnode.data.attachData; const placeholder = document.createElement('span'); // Replace actual element with dummy placeholder // Snabbdom will then insert placeholder instead diff --git a/src/modules/style.ts b/src/modules/style.ts index 27dede9..eca3777 100755 --- a/src/modules/style.ts +++ b/src/modules/style.ts @@ -1,6 +1,12 @@ import {VNode, VNodeData} from '../vnode'; import {Module} from './module'; +export interface VNodeStyle { + delayed: { [prop: string]: string } + remove: { [prop: string]: string } + [prop: string]: string | { [prop: string]: string } +} + var raf = (typeof window !== 'undefined' && window.requestAnimationFrame) || setTimeout; var nextFrame = function(fn: any) { raf(function() { raf(fn); }); }; @@ -15,8 +21,8 @@ function updateStyle(oldVnode: VNode, vnode: VNode): void { if (!oldStyle && !style) return; if (oldStyle === style) return; - oldStyle = oldStyle || {}; - style = style || {}; + oldStyle = oldStyle || {} as VNodeStyle; + style = style || {} as VNodeStyle; var oldHasDel = 'delayed' in oldStyle; for (name in oldStyle) { diff --git a/src/vnode.ts b/src/vnode.ts index 7af30c9..b688e88 100644 --- a/src/vnode.ts +++ b/src/vnode.ts @@ -1,4 +1,6 @@ import {Hooks} from './hooks'; +import {AttachData} from './helpers/attachto' +import {VNodeStyle} from './modules/style' export type Key = string | number; @@ -12,22 +14,32 @@ export interface VNode { } export interface VNodeData { - // modules - use any because Object type is useless - props?: any; - attrs?: any; - class?: any; - style?: any; - dataset?: any; - on?: any; - hero?: any; - attachData?: any; + props?: { + [prop: string]: any + }; + attrs?: { + [attr: string]: any + }; + class?: { + [name: string]: boolean + }; + style?: VNodeStyle; + dataset?: { + [name: string]: string + }; + on?: { + [event: string]: EventListener | EventListener[] + }; + hero?: { + id: string + }; + attachData?: AttachData; hook?: Hooks; key?: Key; ns?: string; // for SVGs fn?: () => VNode; // for thunks args?: Array; // for thunks [key: string]: any; // for any other 3rd party module - // end of modules } export function vnode(sel: string | undefined,