From 0c10ea13b6e4063a4eaaa768825d94e85fa77aaf Mon Sep 17 00:00:00 2001 From: Johan Gorter Date: Sat, 11 Jul 2015 22:59:29 +0200 Subject: [PATCH] Improved maquette, no more any's in the API --- maquette/maquette-tests.ts | 16 +++-- maquette/maquette.d.ts | 134 +++++++++++++++++-------------------- 2 files changed, 72 insertions(+), 78 deletions(-) diff --git a/maquette/maquette-tests.ts b/maquette/maquette-tests.ts index 9f4621593b..0c174e6f46 100644 --- a/maquette/maquette-tests.ts +++ b/maquette/maquette-tests.ts @@ -64,20 +64,28 @@ var vnode = h("div", [ // mapping -var createTarget = function(source:any) { +interface Target { + source: number; + updateCount: number; + alreadyPresent: boolean; +} + +var createTarget = function(source:number): Target { return { source: source, - updateCount: 0 + updateCount: 0, + alreadyPresent: false }; }; -var updateTarget = function(source: any, target:any) { +var updateTarget = function(source: number, target:Target) { + target.updateCount++; }; var permutations = [[1,2], [2,1]]; for (var i=0;i // Definitions: https://github.com/johan-gorter/DefinitelyTyped - /** - * @callback enterAnimationCallback - * @param {Element} element - Element that was just added to the DOM. - * @param {Object} properties - The properties object that was supplied to the {@link module:maquette.h} method - */ - - /** - * @callback exitAnimationCallback - * @param {Element} element - Element that ought to be removed from to the DOM. - * @param {function} removeElement - Function that removes the element from the DOM. - * This argument is supplied purely for convenience. - * You may use this function to remove the element when the animation is done. - * @param {Object} properties - The properties object that was supplied to the {@link module:maquette.h} method that rendered this {@link VNode} the previous time. - */ - - /** - * @callback updateAnimationCallback - * @param {Element} element - Element that was modified in the DOM. - * @param {Object} properties - The last properties object that was supplied to the {@link module:maquette.h} method - * @param {Object} previousProperties - The previous properties object that was supplied to the {@link module:maquette.h} method - */ - - /** - * @callback afterCreateCallback - * @param {Element} element - The element that was added to the DOM. - * @param {Object} projectionOptions - The projection options that were used see {@link module:maquette.createProjector}. - * @param {string} vnodeSelector - The selector passed to the {@link module:maquette.h} function. - * @param {Object} properties - The properties passed to the {@link module:maquette.h} function. - * @param {VNode[]} children - The children that were created. - * @param {Object} properties - The last properties object that was supplied to the {@link module:maquette.h} method - * @param {Object} previousProperties - The previous properties object that was supplied to the {@link module:maquette.h} method - */ - - /** - * @callback afterUpdateCallback - * @param {Element} element - The element that may have been updated in the DOM. - * @param {Object} projectionOptions - The projection options that were used see {@link module:maquette.createProjector}. - * @param {string} vnodeSelector - The selector passed to the {@link module:maquette.h} function. - * @param {Object} properties - The properties passed to the {@link module:maquette.h} function. - * @param {VNode[]} children - The children for this node. - */ - - /** * The main object in maquette is the maquette object. * It is either bound to `window.maquette` or it can be obtained using {@link http://browserify.org/|browserify} or {@link http://requirejs.org/|requirejs}. */ declare module maquette { + export interface VNodeProperties { + enterAnimation?: ((element: Element, properties?: VNodeProperties) => void) | string; + exitAnimation?: ((element: Element, removeElement: () => void, properties?: VNodeProperties) => void) | string; + updateAnimation?: (element: Element, properties?: VNodeProperties, previousProperties?: VNodeProperties) => void; + afterCreate?: (element: Element, projectionOptions: ProjectionOptions, vnodeSelector: string, properties: VNodeProperties, + children: VNode[]) => void; + afterUpdate?: (element: Element, projectionOptions: ProjectionOptions, vnodeSelector: string, properties: VNodeProperties, + children: VNode[]) => void; + [index: string]: Object; + } + + export interface ProjectionOptions { + transitions?: { + enter: (element: Element, properties: VNodeProperties, enterAnimation: string) => void; + exit: (element: Element, properties: VNodeProperties, exitAnimation: string, removeElement: () => void) => void; + } + } + + export type VNodeChild = string|VNode|Array>>>; // Array means Array + export var dom: MaquetteDom; /** @@ -59,7 +36,7 @@ declare module maquette { * In practice, caching of {@link VNode} trees is not needed, because achieving 60 frames per second is almost never a problem. * @returns {CalculationCache} */ - export function createCache(): CalculationCache; + export function createCache(): CalculationCache; /** * Creates a {@link Mapping} instance that keeps an array of result objects synchronized with an array of source objects. @@ -68,18 +45,21 @@ declare module maquette { * @param {function} updateResult - `function(source, target, index)` that updates a result to an updated source. * @returns {Mapping} */ - export function createMapping(getSourceKey: (source: any) => any, createResult: (source:any, index:number) => any, updateResult: (source: any, target: any, index: number) => void): Mapping; + export function createMapping( + getSourceKey: (source: Source) => (string|number), + createResult: (source: Source, index:number) => Target, + updateResult: (source: Source, target: Target, index: number) => void): Mapping; /** * Creates a {@link Projector} instance using the provided projectionOptions. - * @param {Object} [projectionOptions] - Options that influence how the DOM is rendered and updated. - * @param {Object} projectionOptions.transitions - A transition strategy to invoke when + * @param {Object} projectionOptions - Options that influence how the DOM is rendered and updated. + * projectionOptions.transitions - A transition strategy to invoke when * enterAnimation and exitAnimation properties are provided as strings. * The module `cssTransitions` in the provided `css-transitions.js` file provides such a strategy. * A transition strategy is not needed when enterAnimation and exitAnimation properties are provided as functions. * @returns {Projector} */ - export function createProjector(options? : any) : Projector; + export function createProjector(projectionOptions? : ProjectionOptions) : Projector; /** * The `h` method is used to create a virtual DOM node. @@ -88,38 +68,44 @@ declare module maquette { * * @param {string} selector - Contains the tagName, id and fixed css classnames in CSS selector format. * It is formatted as follows: `tagname.cssclass1.cssclass2#id`. - * @param {Object} [properties] - An object literal containing properties that will be placed on the DOM node. - * @param {function} properties.* - Properties with functions values like `onclick:handleClick` are registered as event handlers - * @param {String} properties.* - Properties with string values, like `href:"/"` are used as attributes - * @param {object} properties.* - All non-string values are put on the DOM node as properties - * @param {Object} properties.key - Used to uniquely identify a DOM node among siblings. + * @param {Object} properties - An object literal containing properties that will be placed on the DOM node. + * Properties with functions values like `onclick:handleClick` are registered as event handlers. + * Properties with string values, like `href:"/"` are used as attributes. + * All non-string values are put on the DOM node as properties. + * Property 'key' is used to uniquely identify a DOM node among siblings. * A key is required when there are more children with the same selector and these children are added or removed dynamically. - * @param {Object} properties.classes - An object literal like `{important:true}` which allows css classes, like `important` to be added and removed dynamically. - * @param {Object} properties.styles - An object literal like `{height:"100px"}` which allows styles to be changed dynamically. All values must be strings. - * @param {(string|enterAnimationCallback)} properties.enterAnimation - The animation to perform when this node is added to an already existing parent. + * Property classes is an object literal like `{important:true}` which allows css classes, like `important` to be added and removed dynamically. + * Property styles is an object literal like `{height:"100px"}` which allows styles to be changed dynamically. All values must be strings. + * Property enterAnimation is the animation to perform when this node is added to an already existing parent. * {@link http://maquettejs.org/docs/animations.html|More about animations}. * When this value is a string, you must pass a `projectionOptions.transitions` object when creating the projector {@link module:maquette.createProjector}. - * @param {(string|exitAnimationCallback)} properties.exitAnimation - The animation to perform when this node is removed while its parent remains. + * Properties exitAnimation is the animation to perform when this node is removed while its parent remains. * When this value is a string, you must pass a `projectionOptions.transitions` object when creating the projector {@link module:maquette.createProjector}. * {@link http://maquettejs.org/docs/animations.html|More about animations}. - * @param {updateAnimationCallback} properties.updateAnimation - The animation to perform when the properties of this node change. + * Property updateAnimation is the animation to perform when the properties of this node change. * This also includes attributes, styles, css classes. This callback is also invoked when node contains only text and that text changes. * {@link http://maquettejs.org/docs/animations.html|More about animations}. - * @param {afterCreateCallback} properties.afterCreate - Callback that is executed after this node is added to the DOM. Childnodes and properties have already been applied. - * @param {afterUpdateCallback} properties.afterCreate - Callback that is executed every time this node may have been updated. Childnodes and properties have already been updated. - * @param {Object[]} [children] - An array of virtual DOM nodes to add as child nodes. + * property afterCreate is the callback that is executed after this node is added to the DOM. Childnodes and properties have already been applied. + * property afterUpdate is the callback that is executed every time this node may have been updated. Childnodes and properties have already been updated. + * @param {Array} children - An array of virtual DOM nodes and strings to add as child nodes. * This array may contain nested arrays, `null` or `undefined` values. * Nested arrays are flattened, `null` and `undefined` will be skipped. * * @returns {VNode} A VNode object, used to render a real DOM later. NOTE: There are {@link http://maquettejs.org/docs/rules.html|three basic rules} you should be aware of when updating the virtual DOM. */ - export function h(selector: string, properties?: any, children?: Array): VNode; + export function h(selector: string, properties: VNodeProperties, children: Array): VNode; + export function h(selector: string, children: Array): VNode; + export function h(selector: string, properties: VNodeProperties): VNode; + export function h(selector: string): VNode; /** * A virtual representation of a DOM Node. Maquette assumes that {@link VNode} objects are never modified externally. * Instances of {@link VNode} can be created using {@link module:maquette.h}. */ export interface VNode { + vnodeSelector: string; + properties: VNodeProperties; + children: Array; } // Not used anywhere in the maquette sourcecode, but it is a widely used pattern. @@ -133,7 +119,7 @@ declare module maquette { * This object can be used to bypass both rendering and diffing of a virtual DOM subtree. * Instances of {@link CalculationCache} can be created using {@link module:maquette.createCache}. */ - export interface CalculationCache { + export interface CalculationCache { /** * Manually invalidates the cached outcome. */ @@ -146,7 +132,7 @@ declare module maquette { * These objects are assumed to be immutable primitive values. * @param {function} calculation - Function that takes zero arguments and returns an object (A {@link VNode} assumably) that can be cached. */ - result(inputs: Array, calculation: () => any):any; + result(inputs: Array, calculation: () => Result):Result; } /** @@ -156,17 +142,17 @@ declare module maquette { * A {@link Mapping} can be used to keep an array of components (objects with a `renderMaquette` method) synchronized with an array of data. * Instances of {@link Mapping} can be created using {@link module:maquette.createMapping}. */ - export interface Mapping { + export interface Mapping { /** * The array of results. These results will be synchronized with the latest array of sources that were provided using {@link Mapping#map}. * @type {Object[]} */ - results: Array; + results: Array; /** * Maps a new array of sources and updates {@link Mapping#results}. * @param {Object[]} newSources - The new array of sources. */ - map(newSources: Array): void; + map(newSources: Array): void; } /** @@ -181,7 +167,7 @@ declare module maquette { * @param {Object} projectionOptions - Options to be used to create and update the projection, see {@link module:maquette.createProjector}. * @returns {Projection} The {@link Projection} that was created. */ - append(parentNode: Element, vnode: VNode, projectionOptions?: any): Projection; + append(parentNode: Element, vnode: VNode, projectionOptions?: ProjectionOptions): Projection; /** * Creates a real DOM tree from a {@link VNode}. The {@link Projection} object returned will contain the resulting DOM Node under the {@link Projection#domNode} property. * This is a low-level method. Users wil typically use a {@link Projector} instead. @@ -189,7 +175,7 @@ declare module maquette { * @param {Object} projectionOptions - Options to be used to create and update the projection, see {@link module:maquette.createProjector}. * @returns {Projection} The {@link Projection} which contains the DOM Node that was created. */ - create(vnode: VNode, projectionOptions?: any): Projection; + create(vnode: VNode, projectionOptions?: ProjectionOptions): Projection; /** * Inserts a new DOM node which is generated from a {@link VNode}. * This is a low-level method. Users wil typically use a {@link Projector} instead. @@ -250,7 +236,7 @@ declare module maquette { * @param {Element} parentNode - The parent node for the new childNode. * @param {function} renderMaquetteFunction - Function with zero arguments that returns a {@link VNode} tree. */ - append(parentNode: Element, renderMaquette: () => VNode): void; + append(parentNode: Element, renderMaquetteFunction: () => VNode): void; /** * Scans the document for `