mirror of https://github.com/sveltejs/svelte
commit
1078bae696
@ -1,12 +0,0 @@
|
||||
import * as shared from '../../shared/index.js';
|
||||
|
||||
export const nameMap = new Map();
|
||||
export const sharedMap = new Map();
|
||||
|
||||
Object.keys(shared).forEach( key => {
|
||||
const value = shared[ key ]; // eslint-disable-line import/namespace
|
||||
if ( typeof value === 'function' ) {
|
||||
nameMap.set( value.name, key );
|
||||
}
|
||||
sharedMap.set( key, value.toString() );
|
||||
});
|
@ -0,0 +1,73 @@
|
||||
import deindent from '../../../../utils/deindent.js';
|
||||
|
||||
export default function addTransitions ( generator, block, state, node, intro, outro ) {
|
||||
const wrapTransition = generator.helper( 'wrapTransition' );
|
||||
|
||||
if ( intro === outro ) {
|
||||
const name = block.getUniqueName( `${state.name}_transition` );
|
||||
const snippet = intro.expression ? block.contextualise( intro.expression ).snippet : '{}';
|
||||
|
||||
block.addVariable( name );
|
||||
|
||||
const fn = `${generator.alias( 'template' )}.transitions.${intro.name}`;
|
||||
|
||||
block.builders.intro.addBlock( deindent`
|
||||
${block.component}._renderHooks.push( function () {
|
||||
if ( !${name} ) ${name} = ${wrapTransition}( ${state.name}, ${fn}, ${snippet}, true, null );
|
||||
${name}.run( ${name}.t, 1, function () {
|
||||
${block.component}.fire( 'intro.end', { node: ${state.name} });
|
||||
});
|
||||
});
|
||||
` );
|
||||
|
||||
block.builders.outro.addBlock( deindent`
|
||||
${name}.run( ${name}.t, 0, function () {
|
||||
${block.component}.fire( 'outro.end', { node: ${state.name} });
|
||||
if ( --${block.alias( 'outros' )} === 0 ) ${block.alias( 'outrocallback' )}();
|
||||
${name} = null;
|
||||
});
|
||||
` );
|
||||
}
|
||||
|
||||
else {
|
||||
const introName = intro && block.getUniqueName( `${state.name}_intro` );
|
||||
const outroName = outro && block.getUniqueName( `${state.name}_outro` );
|
||||
|
||||
if ( intro ) {
|
||||
block.addVariable( introName );
|
||||
const snippet = intro.expression ? block.contextualise( intro.expression ).snippet : '{}';
|
||||
|
||||
const fn = `${generator.alias( 'template' )}.transitions.${intro.name}`; // TODO add built-in transitions?
|
||||
|
||||
if ( outro ) {
|
||||
block.builders.intro.addBlock( `if ( ${outroName} ) ${outroName}.abort();` );
|
||||
}
|
||||
|
||||
block.builders.intro.addBlock( deindent`
|
||||
${block.component}._renderHooks.push( function () {
|
||||
${introName} = ${wrapTransition}( ${state.name}, ${fn}, ${snippet}, true, null );
|
||||
${introName}.run( 0, 1, function () {
|
||||
${block.component}.fire( 'intro.end', { node: ${state.name} });
|
||||
});
|
||||
});
|
||||
` );
|
||||
}
|
||||
|
||||
if ( outro ) {
|
||||
block.addVariable( outroName );
|
||||
const snippet = outro.expression ? block.contextualise( outro.expression ).snippet : '{}';
|
||||
|
||||
const fn = `${generator.alias( 'template' )}.transitions.${outro.name}`;
|
||||
|
||||
// TODO hide elements that have outro'd (unless they belong to a still-outroing
|
||||
// group) prior to their removal from the DOM
|
||||
block.builders.outro.addBlock( deindent`
|
||||
${outroName} = ${wrapTransition}( ${state.name}, ${fn}, ${snippet}, false, null );
|
||||
${outroName}.run( 1, 0, function () {
|
||||
${block.component}.fire( 'outro.end', { node: ${state.name} });
|
||||
if ( --${block.alias( 'outros' )} === 0 ) ${block.alias( 'outrocallback' )}();
|
||||
});
|
||||
` );
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
{
|
||||
"root": true,
|
||||
"rules": {
|
||||
"indent": [ 2, "tab", { "SwitchCase": 1 } ],
|
||||
"semi": [ 2, "always" ],
|
||||
"keyword-spacing": [ 2, { "before": true, "after": true } ],
|
||||
"space-before-blocks": [ 2, "always" ],
|
||||
"no-mixed-spaces-and-tabs": [ 2, "smart-tabs" ],
|
||||
"no-cond-assign": 0,
|
||||
"no-unused-vars": 2,
|
||||
"no-const-assign": 2,
|
||||
"no-class-assign": 2,
|
||||
"no-this-before-super": 2,
|
||||
"no-unreachable": 2,
|
||||
"valid-typeof": 2,
|
||||
"quote-props": [ 2, "as-needed" ],
|
||||
"arrow-spacing": 2,
|
||||
"no-inner-declarations": 0
|
||||
},
|
||||
"env": {
|
||||
"es6": true,
|
||||
"browser": true,
|
||||
"node": true,
|
||||
"mocha": true
|
||||
},
|
||||
"extends": [
|
||||
"eslint:recommended",
|
||||
"plugin:import/errors",
|
||||
"plugin:import/warnings"
|
||||
],
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 6,
|
||||
"sourceType": "module"
|
||||
},
|
||||
"settings": {
|
||||
"import/core-modules": [ "svelte" ]
|
||||
}
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
const fs = require( 'fs' );
|
||||
const path = require( 'path' );
|
||||
const acorn = require( 'acorn' );
|
||||
|
||||
const declarations = {};
|
||||
|
||||
fs.readdirSync( __dirname ).forEach( file => {
|
||||
if ( !/^[a-z]+\.js$/.test( file ) ) return;
|
||||
|
||||
const source = fs.readFileSync( path.join( __dirname, file ), 'utf-8' );
|
||||
const ast = acorn.parse( source, {
|
||||
ecmaVersion: 6,
|
||||
sourceType: 'module'
|
||||
});
|
||||
|
||||
ast.body.forEach( node => {
|
||||
if ( node.type !== 'ExportNamedDeclaration' ) return;
|
||||
|
||||
const declaration = node.declaration;
|
||||
if ( !declaration ) return;
|
||||
|
||||
const name = declaration.type === 'VariableDeclaration' ?
|
||||
declaration.declarations[0].id.name :
|
||||
declaration.id.name;
|
||||
|
||||
const value = declaration.type === 'VariableDeclaration' ?
|
||||
declaration.declarations[0].init :
|
||||
declaration;
|
||||
|
||||
declarations[ name ] = source.slice( value.start, value.end );
|
||||
});
|
||||
});
|
||||
|
||||
fs.writeFileSync( 'src/generators/dom/shared.js', `// this file is auto-generated, do not edit it
|
||||
export default ${JSON.stringify( declarations, null, '\t' )};` );
|
@ -0,0 +1,129 @@
|
||||
import { assign, noop } from './utils.js';
|
||||
|
||||
export function linear ( t ) {
|
||||
return t;
|
||||
}
|
||||
|
||||
function generateKeyframes ( a, b, delta, duration, ease, fn, node, style ) {
|
||||
var id = '__svelte' + ~~( Math.random() * 1e9 ); // TODO make this more robust
|
||||
var keyframes = '@keyframes ' + id + '{\n';
|
||||
|
||||
for ( var p = 0; p <= 1; p += 16.666 / duration ) {
|
||||
var t = a + delta * ease( p );
|
||||
keyframes += ( p * 100 ) + '%{' + fn( t ) + '}\n';
|
||||
}
|
||||
|
||||
keyframes += '100% {' + fn( b ) + '}\n}';
|
||||
style.textContent += keyframes;
|
||||
|
||||
document.head.appendChild( style );
|
||||
|
||||
node.style.animation = node.style.animation.split( ',' )
|
||||
.filter( function ( anim ) {
|
||||
// when introing, discard old animations if there are any
|
||||
return anim && ( delta < 0 || !/__svelte/.test( anim ) );
|
||||
})
|
||||
.concat( id + ' ' + duration + 'ms linear 1 forwards' )
|
||||
.join( ', ' );
|
||||
}
|
||||
|
||||
export function wrapTransition ( node, fn, params, intro, outgroup ) {
|
||||
var obj = fn( node, params, intro );
|
||||
var duration = obj.duration || 300;
|
||||
var ease = obj.easing || linear;
|
||||
|
||||
// TODO share <style> tag between all transitions?
|
||||
if ( obj.css ) {
|
||||
var style = document.createElement( 'style' );
|
||||
}
|
||||
|
||||
if ( intro && obj.tick ) obj.tick( 0 );
|
||||
|
||||
return {
|
||||
start: null,
|
||||
end: null,
|
||||
a: null,
|
||||
b: null,
|
||||
d: null,
|
||||
running: false,
|
||||
t: intro ? 0 : 1,
|
||||
callback: null,
|
||||
run: function ( a, b, callback ) {
|
||||
this.a = a;
|
||||
this.b = b;
|
||||
this.delta = b - a;
|
||||
this.start = window.performance.now() + ( obj.delay || 0 );
|
||||
this.duration = duration * Math.abs( b - a );
|
||||
this.end = this.start + this.duration;
|
||||
|
||||
this.callback = callback;
|
||||
|
||||
if ( obj.css ) {
|
||||
generateKeyframes( this.a, this.b, this.delta, this.duration, ease, obj.css, node, style );
|
||||
}
|
||||
|
||||
if ( !this.running ) {
|
||||
this.running = true;
|
||||
transitionManager.add( this );
|
||||
}
|
||||
},
|
||||
update: function ( now ) {
|
||||
var p = now - this.start;
|
||||
this.t = this.a + this.delta * ease( p / this.duration );
|
||||
if ( obj.tick ) obj.tick( this.t );
|
||||
},
|
||||
done: function () {
|
||||
if ( obj.tick ) obj.tick( intro ? 1 : 0 );
|
||||
if ( obj.css ) document.head.removeChild( style );
|
||||
this.callback();
|
||||
this.running = false;
|
||||
},
|
||||
abort: function () {
|
||||
if ( !intro && obj.tick ) obj.tick( 1 ); // reset css for intro
|
||||
if ( obj.css ) document.head.removeChild( style );
|
||||
this.running = false;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export var transitionManager = {
|
||||
running: false,
|
||||
transitions: [],
|
||||
|
||||
add: function ( transition ) {
|
||||
transitionManager.transitions.push( transition );
|
||||
|
||||
if ( !this.running ) {
|
||||
this.running = true;
|
||||
this.next();
|
||||
}
|
||||
},
|
||||
|
||||
next: function () {
|
||||
transitionManager.running = false;
|
||||
|
||||
var now = window.performance.now();
|
||||
var i = transitionManager.transitions.length;
|
||||
|
||||
while ( i-- ) {
|
||||
var transition = transitionManager.transitions[i];
|
||||
|
||||
if ( transition.running ) {
|
||||
if ( now >= transition.end ) {
|
||||
transition.running = false;
|
||||
transition.done();
|
||||
} else if ( now > transition.start ) {
|
||||
transition.update( now );
|
||||
}
|
||||
|
||||
transitionManager.running = true;
|
||||
} else {
|
||||
transitionManager.transitions.splice( i, 1 );
|
||||
}
|
||||
}
|
||||
|
||||
if ( transitionManager.running ) {
|
||||
requestAnimationFrame( transitionManager.next );
|
||||
}
|
||||
}
|
||||
};
|
@ -0,0 +1,10 @@
|
||||
export function noop () {}
|
||||
|
||||
export function assign ( target ) {
|
||||
for ( var i = 1; i < arguments.length; i += 1 ) {
|
||||
var source = arguments[i];
|
||||
for ( var k in source ) target[k] = source[k];
|
||||
}
|
||||
|
||||
return target;
|
||||
}
|
@ -0,0 +1,44 @@
|
||||
import deindent from './deindent.js';
|
||||
|
||||
export default function toSource ( thing ) {
|
||||
if ( typeof thing === 'function' ) {
|
||||
return normaliseIndentation( thing.toString() );
|
||||
}
|
||||
|
||||
if ( Array.isArray( thing ) ) {
|
||||
if ( thing.length === 0 ) return '[]';
|
||||
throw new Error( 'TODO' ); // not currently needed
|
||||
}
|
||||
|
||||
if ( thing && typeof thing === 'object' ) {
|
||||
const keys = Object.keys( thing );
|
||||
if ( keys.length === 0 ) return '{}';
|
||||
|
||||
const props = keys.map( key => `${key}: ${toSource( thing[ key ] )}` ).join( ',\n' );
|
||||
return deindent`
|
||||
{
|
||||
${props}
|
||||
}
|
||||
`;
|
||||
}
|
||||
|
||||
return JSON.stringify( thing );
|
||||
}
|
||||
|
||||
function normaliseIndentation ( str ) {
|
||||
const lines = str.split( '\n' ).slice( 1, -1 );
|
||||
let minIndentation = Infinity;
|
||||
|
||||
lines.forEach( line => {
|
||||
if ( !/\S/.test( line ) ) return;
|
||||
const indentation = /^\t*/.exec( line )[0].length;
|
||||
if ( indentation < minIndentation ) minIndentation = indentation;
|
||||
});
|
||||
|
||||
if ( minIndentation !== Infinity && minIndentation !== 1 ) {
|
||||
const pattern = new RegExp( `^\\t{${minIndentation - 1}}`, 'gm' );
|
||||
return str.replace( pattern, '' );
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
import checkForDupes from '../utils/checkForDupes.js';
|
||||
import checkForComputedKeys from '../utils/checkForComputedKeys.js';
|
||||
|
||||
export default function transitions ( validator, prop ) {
|
||||
if ( prop.value.type !== 'ObjectExpression' ) {
|
||||
validator.error( `The 'transitions' property must be an object literal`, prop.start );
|
||||
return;
|
||||
}
|
||||
|
||||
checkForDupes( validator, prop.value.properties );
|
||||
checkForComputedKeys( validator, prop.value.properties );
|
||||
|
||||
prop.value.properties.forEach( () => {
|
||||
// TODO probably some validation that can happen here...
|
||||
// checking for use of `this` etc?
|
||||
});
|
||||
}
|
@ -0,0 +1 @@
|
||||
<div in:fade>fades in</div>
|
@ -0,0 +1,37 @@
|
||||
{
|
||||
"hash": 1535528483,
|
||||
"html": {
|
||||
"start": 0,
|
||||
"end": 27,
|
||||
"type": "Fragment",
|
||||
"children": [
|
||||
{
|
||||
"start": 0,
|
||||
"end": 27,
|
||||
"type": "Element",
|
||||
"name": "div",
|
||||
"attributes": [
|
||||
{
|
||||
"start": 5,
|
||||
"end": 12,
|
||||
"type": "Transition",
|
||||
"name": "fade",
|
||||
"intro": true,
|
||||
"outro": false,
|
||||
"expression": null
|
||||
}
|
||||
],
|
||||
"children": [
|
||||
{
|
||||
"start": 13,
|
||||
"end": 21,
|
||||
"type": "Text",
|
||||
"data": "fades in"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"css": null,
|
||||
"js": null
|
||||
}
|
@ -0,0 +1 @@
|
||||
<div in:style='{opacity: 0}'>fades in</div>
|
@ -0,0 +1,65 @@
|
||||
{
|
||||
"hash": 3160753914,
|
||||
"html": {
|
||||
"start": 0,
|
||||
"end": 43,
|
||||
"type": "Fragment",
|
||||
"children": [
|
||||
{
|
||||
"start": 0,
|
||||
"end": 43,
|
||||
"type": "Element",
|
||||
"name": "div",
|
||||
"attributes": [
|
||||
{
|
||||
"start": 5,
|
||||
"end": 28,
|
||||
"type": "Transition",
|
||||
"name": "style",
|
||||
"intro": true,
|
||||
"outro": false,
|
||||
"expression": {
|
||||
"start": 15,
|
||||
"end": 27,
|
||||
"type": "ObjectExpression",
|
||||
"properties": [
|
||||
{
|
||||
"start": 16,
|
||||
"end": 26,
|
||||
"type": "Property",
|
||||
"method": false,
|
||||
"computed": false,
|
||||
"shorthand": false,
|
||||
"kind": "init",
|
||||
"key": {
|
||||
"type": "Identifier",
|
||||
"start": 16,
|
||||
"end": 23,
|
||||
"name": "opacity"
|
||||
},
|
||||
"value": {
|
||||
"start": 25,
|
||||
"end": 26,
|
||||
"type": "Literal",
|
||||
"value": 0,
|
||||
"raw": "0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"children": [
|
||||
{
|
||||
"start": 29,
|
||||
"end": 37,
|
||||
"type": "Text",
|
||||
"data": "fades in"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"css": null,
|
||||
"js": null
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
export default {
|
||||
data: {
|
||||
name: 'world'
|
||||
},
|
||||
|
||||
test ( assert, component, target, window, raf ) {
|
||||
global.count = 0;
|
||||
|
||||
component.set({ visible: true });
|
||||
assert.equal( global.count, 1 );
|
||||
const div = target.querySelector( 'div' );
|
||||
assert.equal( div.foo, 0 );
|
||||
|
||||
raf.tick( 300 );
|
||||
component.set({ name: 'everybody' });
|
||||
assert.equal( div.foo, 0.75 );
|
||||
assert.htmlEqual( div.innerHTML, 'hello everybody!' );
|
||||
|
||||
component.set({ visible: false, name: 'again' });
|
||||
assert.htmlEqual( div.innerHTML, 'hello everybody!' );
|
||||
|
||||
raf.tick( 500 );
|
||||
assert.equal( div.foo, 0.25 );
|
||||
|
||||
component.set({ visible: true });
|
||||
raf.tick( 700 );
|
||||
assert.equal( div.foo, 0.75 );
|
||||
assert.htmlEqual( div.innerHTML, 'hello again!' );
|
||||
|
||||
raf.tick( 800 );
|
||||
assert.equal( div.foo, 1 );
|
||||
|
||||
raf.tick( 900 );
|
||||
|
||||
component.destroy();
|
||||
}
|
||||
};
|
@ -0,0 +1,19 @@
|
||||
{{#if visible}}
|
||||
<div transition:foo>hello {{name}}!</div>
|
||||
{{/if}}
|
||||
|
||||
<script>
|
||||
export default {
|
||||
transitions: {
|
||||
foo: function ( node, params ) {
|
||||
global.count += 1;
|
||||
return {
|
||||
duration: 400,
|
||||
tick: t => {
|
||||
node.foo = t;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
@ -0,0 +1,32 @@
|
||||
export default {
|
||||
data: {
|
||||
things: [ 'a', 'b', 'c' ]
|
||||
},
|
||||
|
||||
test ( assert, component, target, window, raf ) {
|
||||
let divs = target.querySelectorAll( 'div' );
|
||||
assert.equal( divs[0].foo, 0 );
|
||||
assert.equal( divs[1].foo, 0 );
|
||||
assert.equal( divs[2].foo, 0 );
|
||||
|
||||
raf.tick( 50 );
|
||||
assert.equal( divs[0].foo, 0.5 );
|
||||
assert.equal( divs[1].foo, 0.5 );
|
||||
assert.equal( divs[2].foo, 0.5 );
|
||||
|
||||
component.set({ things: [ 'a', 'b', 'c', 'd' ] });
|
||||
divs = target.querySelectorAll( 'div' );
|
||||
assert.equal( divs[0].foo, 0.5 );
|
||||
assert.equal( divs[1].foo, 0.5 );
|
||||
assert.equal( divs[2].foo, 0.5 );
|
||||
assert.equal( divs[3].foo, 0 );
|
||||
|
||||
raf.tick( 75 );
|
||||
assert.equal( divs[0].foo, 0.75 );
|
||||
assert.equal( divs[1].foo, 0.75 );
|
||||
assert.equal( divs[2].foo, 0.75 );
|
||||
assert.equal( divs[3].foo, 0.25 );
|
||||
|
||||
component.destroy();
|
||||
}
|
||||
};
|
@ -0,0 +1,18 @@
|
||||
{{#each things as thing}}
|
||||
<div in:foo>{{thing}}</div>
|
||||
{{/each}}
|
||||
|
||||
<script>
|
||||
export default {
|
||||
transitions: {
|
||||
foo: function ( node, params ) {
|
||||
return {
|
||||
duration: 100,
|
||||
tick: t => {
|
||||
node.foo = t;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
@ -0,0 +1,49 @@
|
||||
export default {
|
||||
data: {
|
||||
things: [
|
||||
{ name: 'a' },
|
||||
{ name: 'b' },
|
||||
{ name: 'c' }
|
||||
]
|
||||
},
|
||||
|
||||
test ( assert, component, target, window, raf ) {
|
||||
let divs = target.querySelectorAll( 'div' );
|
||||
assert.equal( divs[0].foo, 0 );
|
||||
assert.equal( divs[1].foo, 0 );
|
||||
assert.equal( divs[2].foo, 0 );
|
||||
|
||||
raf.tick( 50 );
|
||||
assert.equal( divs[0].foo, 0.5 );
|
||||
assert.equal( divs[1].foo, 0.5 );
|
||||
assert.equal( divs[2].foo, 0.5 );
|
||||
|
||||
component.set({
|
||||
things: [
|
||||
{ name: 'a' },
|
||||
{ name: 'woo!' },
|
||||
{ name: 'b' },
|
||||
{ name: 'c' }
|
||||
]
|
||||
});
|
||||
assert.htmlEqual( target.innerHTML, `
|
||||
<div>a</div>
|
||||
<div>woo!</div>
|
||||
<div>b</div>
|
||||
<div>c</div>
|
||||
` );
|
||||
divs = target.querySelectorAll( 'div' );
|
||||
assert.equal( divs[0].foo, 0.5 );
|
||||
assert.equal( divs[1].foo, 0 );
|
||||
assert.equal( divs[2].foo, 0.5 );
|
||||
assert.equal( divs[3].foo, 0.5 );
|
||||
|
||||
raf.tick( 75 );
|
||||
assert.equal( divs[0].foo, 0.75 );
|
||||
assert.equal( divs[1].foo, 0.25 );
|
||||
assert.equal( divs[2].foo, 0.75 );
|
||||
assert.equal( divs[3].foo, 0.75 );
|
||||
|
||||
component.destroy();
|
||||
}
|
||||
};
|
@ -0,0 +1,18 @@
|
||||
{{#each things as thing @name}}
|
||||
<div in:foo>{{thing.name}}</div>
|
||||
{{/each}}
|
||||
|
||||
<script>
|
||||
export default {
|
||||
transitions: {
|
||||
foo: function ( node, params ) {
|
||||
return {
|
||||
duration: 100,
|
||||
tick: t => {
|
||||
node.foo = t;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
@ -0,0 +1,25 @@
|
||||
export default {
|
||||
data: {
|
||||
things: [
|
||||
{ name: 'a' },
|
||||
{ name: 'b' },
|
||||
{ name: 'c' }
|
||||
]
|
||||
},
|
||||
|
||||
test ( assert, component, target, window, raf ) {
|
||||
const divs = target.querySelectorAll( 'div' );
|
||||
|
||||
component.set({
|
||||
things: [
|
||||
{ name: 'a' },
|
||||
{ name: 'c' }
|
||||
]
|
||||
});
|
||||
|
||||
raf.tick( 50 );
|
||||
assert.equal( divs[0].foo, undefined );
|
||||
assert.equal( divs[1].foo, 0.5 );
|
||||
assert.equal( divs[2].foo, undefined );
|
||||
}
|
||||
};
|
@ -0,0 +1,18 @@
|
||||
{{#each things as thing @name}}
|
||||
<div out:foo>{{thing.name}}</div>
|
||||
{{/each}}
|
||||
|
||||
<script>
|
||||
export default {
|
||||
transitions: {
|
||||
foo: function ( node, params ) {
|
||||
return {
|
||||
duration: 100,
|
||||
tick: t => {
|
||||
node.foo = t;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
@ -0,0 +1,16 @@
|
||||
export default {
|
||||
data: {
|
||||
things: [ 'a', 'b', 'c' ]
|
||||
},
|
||||
|
||||
test ( assert, component, target, window, raf ) {
|
||||
const divs = target.querySelectorAll( 'div' );
|
||||
|
||||
component.set({ things: [ 'a' ] });
|
||||
|
||||
raf.tick( 50 );
|
||||
assert.equal( divs[0].foo, undefined );
|
||||
assert.equal( divs[1].foo, 0.5 );
|
||||
assert.equal( divs[2].foo, 0.5 );
|
||||
}
|
||||
};
|
@ -0,0 +1,18 @@
|
||||
{{#each things as thing}}
|
||||
<div out:foo>{{thing}}</div>
|
||||
{{/each}}
|
||||
|
||||
<script>
|
||||
export default {
|
||||
transitions: {
|
||||
foo: function ( node, params ) {
|
||||
return {
|
||||
duration: 100,
|
||||
tick: t => {
|
||||
node.foo = t;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
@ -0,0 +1,30 @@
|
||||
export default {
|
||||
test ( assert, component, target, window, raf ) {
|
||||
global.count = 0;
|
||||
|
||||
component.set({ visible: true });
|
||||
assert.equal( global.count, 1 );
|
||||
const div = target.querySelector( 'div' );
|
||||
assert.equal( div.foo, 0 );
|
||||
|
||||
raf.tick( 300 );
|
||||
assert.equal( div.foo, 0.75 );
|
||||
|
||||
component.set({ visible: false });
|
||||
assert.equal( global.count, 1 );
|
||||
|
||||
raf.tick( 500 );
|
||||
assert.equal( div.foo, 0.25 );
|
||||
|
||||
component.set({ visible: true });
|
||||
raf.tick( 700 );
|
||||
assert.equal( div.foo, 0.75 );
|
||||
|
||||
raf.tick( 800 );
|
||||
assert.equal( div.foo, 1 );
|
||||
|
||||
raf.tick( 900 );
|
||||
|
||||
component.destroy();
|
||||
}
|
||||
};
|
@ -0,0 +1,19 @@
|
||||
{{#if visible}}
|
||||
<div transition:foo>foo bidi</div>
|
||||
{{/if}}
|
||||
|
||||
<script>
|
||||
export default {
|
||||
transitions: {
|
||||
foo: function ( node, params ) {
|
||||
global.count += 1;
|
||||
return {
|
||||
duration: 400,
|
||||
tick: t => {
|
||||
node.foo = t;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
@ -0,0 +1,46 @@
|
||||
export default {
|
||||
test ( assert, component, target, window, raf ) {
|
||||
component.set({ visible: true });
|
||||
let div = target.querySelector( 'div' );
|
||||
assert.equal( div.foo, 0 );
|
||||
|
||||
raf.tick( 200 );
|
||||
assert.equal( div.foo, 0.5 );
|
||||
|
||||
raf.tick( 400 );
|
||||
assert.equal( div.foo, 1 );
|
||||
|
||||
raf.tick( 500 );
|
||||
assert.equal( div.foo, 1 );
|
||||
|
||||
component.set({ visible: false });
|
||||
raf.tick( 600 );
|
||||
assert.equal( div.foo, 1 );
|
||||
assert.equal( div.bar, 0.75 );
|
||||
|
||||
raf.tick( 900 );
|
||||
assert.equal( div.foo, 1 );
|
||||
assert.equal( div.bar, 0 );
|
||||
|
||||
// test outro before intro complete
|
||||
raf.tick( 1000 );
|
||||
component.set({ visible: true });
|
||||
div = target.querySelector( 'div' );
|
||||
|
||||
raf.tick( 1200 );
|
||||
assert.equal( div.foo, 0.5 );
|
||||
|
||||
component.set({ visible: false });
|
||||
raf.tick( 1300 );
|
||||
assert.equal( div.foo, 0.75 );
|
||||
assert.equal( div.bar, 0.75 );
|
||||
|
||||
raf.tick( 1400 );
|
||||
assert.equal( div.foo, 1 );
|
||||
assert.equal( div.bar, 0.5 );
|
||||
|
||||
raf.tick( 2000 );
|
||||
|
||||
component.destroy();
|
||||
}
|
||||
};
|
@ -0,0 +1,27 @@
|
||||
{{#if visible}}
|
||||
<div in:foo out:bar>foo then bar</div>
|
||||
{{/if}}
|
||||
|
||||
<script>
|
||||
export default {
|
||||
transitions: {
|
||||
foo: function ( node, params ) {
|
||||
return {
|
||||
duration: 400,
|
||||
tick: t => {
|
||||
node.foo = t;
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
bar: function ( node, params ) {
|
||||
return {
|
||||
duration: 400,
|
||||
tick: t => {
|
||||
node.bar = t;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
@ -0,0 +1,17 @@
|
||||
export default {
|
||||
test ( assert, component, target, window, raf ) {
|
||||
component.set({ visible: true });
|
||||
const div = target.querySelector( 'div' );
|
||||
assert.equal( window.getComputedStyle( div ).opacity, 0 );
|
||||
|
||||
raf.tick( 200 );
|
||||
assert.equal( window.getComputedStyle( div ).opacity, 0.5 );
|
||||
|
||||
raf.tick( 400 );
|
||||
assert.equal( window.getComputedStyle( div ).opacity, 1 );
|
||||
|
||||
raf.tick( 500 );
|
||||
|
||||
component.destroy();
|
||||
}
|
||||
};
|
@ -0,0 +1,18 @@
|
||||
{{#if visible}}
|
||||
<div in:fade>fades in</div>
|
||||
{{/if}}
|
||||
|
||||
<script>
|
||||
export default {
|
||||
transitions: {
|
||||
fade: function ( node, params ) {
|
||||
return {
|
||||
duration: 400,
|
||||
tick: t => {
|
||||
node.style.opacity = t;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
@ -0,0 +1,21 @@
|
||||
export default {
|
||||
test ( assert, component, target, window, raf ) {
|
||||
assert.equal( target.querySelector( 'div' ), component.refs.no );
|
||||
assert.equal( component.refs.no.foo, 0 );
|
||||
|
||||
raf.tick( 200 );
|
||||
assert.equal( component.refs.no.foo, 0.5 );
|
||||
|
||||
raf.tick( 500 );
|
||||
component.set({ x: true });
|
||||
assert.equal( component.refs.no, undefined );
|
||||
assert.equal( component.refs.yes.foo, 0 );
|
||||
|
||||
raf.tick( 700 );
|
||||
assert.equal( component.refs.yes.foo, 0.5 );
|
||||
|
||||
raf.tick( 1000 );
|
||||
|
||||
component.destroy();
|
||||
}
|
||||
};
|
@ -0,0 +1,20 @@
|
||||
{{#if x}}
|
||||
<div ref:yes in:foo>yes</div>
|
||||
{{else}}
|
||||
<div ref:no in:foo>no</div>
|
||||
{{/if}}
|
||||
|
||||
<script>
|
||||
export default {
|
||||
transitions: {
|
||||
foo: function ( node, params ) {
|
||||
return {
|
||||
duration: 400,
|
||||
tick: t => {
|
||||
node.foo = t;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
@ -1,3 +1,3 @@
|
||||
<p>before</p>
|
||||
|
||||
|
||||
<p>after</p>
|
Loading…
Reference in new issue