Merge branch 'master' into folder-structure

pull/2887/head
Richard Harris 6 years ago
commit 7e3b91e3ee

1
.gitignore vendored

@ -29,5 +29,6 @@ _actual*.*
/site/.sessions /site/.sessions
/site/static/svelte-app.json /site/static/svelte-app.json
/site/static/contributors.jpg /site/static/contributors.jpg
/site/static/workers
/site/scripts/svelte-app /site/scripts/svelte-app
/site/src/routes/_contributors.js /site/src/routes/_contributors.js

22
package-lock.json generated

@ -1,6 +1,6 @@
{ {
"name": "svelte", "name": "svelte",
"version": "3.4.3", "version": "3.4.4",
"lockfileVersion": 1, "lockfileVersion": 1,
"requires": true, "requires": true,
"dependencies": { "dependencies": {
@ -168,7 +168,7 @@
}, },
"array-equal": { "array-equal": {
"version": "1.0.0", "version": "1.0.0",
"resolved": "http://registry.npmjs.org/array-equal/-/array-equal-1.0.0.tgz", "resolved": "https://registry.npmjs.org/array-equal/-/array-equal-1.0.0.tgz",
"integrity": "sha1-jCpe8kcv2ep0KwTHenUJO6J1fJM=", "integrity": "sha1-jCpe8kcv2ep0KwTHenUJO6J1fJM=",
"dev": true "dev": true
}, },
@ -528,7 +528,7 @@
}, },
"commander": { "commander": {
"version": "2.15.1", "version": "2.15.1",
"resolved": "http://registry.npmjs.org/commander/-/commander-2.15.1.tgz", "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz",
"integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==", "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==",
"dev": true "dev": true
}, },
@ -844,9 +844,9 @@
"dev": true "dev": true
}, },
"estree-walker": { "estree-walker": {
"version": "0.6.0", "version": "0.6.1",
"resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.6.0.tgz", "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.6.1.tgz",
"integrity": "sha512-peq1RfVAVzr3PU/jL31RaOjUKLoZJpObQWJJ+LgfcxDUifyLZ1RjPQZTl0pzj2uJ45b7A7XpyppXvxdEqzo4rw==", "integrity": "sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==",
"dev": true "dev": true
}, },
"esutils": { "esutils": {
@ -1307,7 +1307,7 @@
}, },
"is-builtin-module": { "is-builtin-module": {
"version": "1.0.0", "version": "1.0.0",
"resolved": "http://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz",
"integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=",
"dev": true, "dev": true,
"requires": { "requires": {
@ -1712,7 +1712,7 @@
}, },
"minimist": { "minimist": {
"version": "0.0.8", "version": "0.0.8",
"resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
"integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=",
"dev": true "dev": true
}, },
@ -1739,7 +1739,7 @@
}, },
"mkdirp": { "mkdirp": {
"version": "0.5.1", "version": "0.5.1",
"resolved": "http://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
"integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
"dev": true, "dev": true,
"requires": { "requires": {
@ -2070,7 +2070,7 @@
}, },
"path-is-absolute": { "path-is-absolute": {
"version": "1.0.1", "version": "1.0.1",
"resolved": "http://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
"integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
"dev": true "dev": true
}, },
@ -2710,7 +2710,7 @@
}, },
"safe-regex": { "safe-regex": {
"version": "1.1.0", "version": "1.1.0",
"resolved": "http://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz",
"integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=",
"dev": true, "dev": true,
"requires": { "requires": {

@ -6,7 +6,7 @@
"main": "index", "main": "index",
"files": [ "files": [
"types", "types",
"compiler.js", "compiler.*",
"register.js", "register.js",
"index.*", "index.*",
"internal", "internal",
@ -63,7 +63,7 @@
"c8": "^3.4.0", "c8": "^3.4.0",
"codecov": "^3.0.0", "codecov": "^3.0.0",
"css-tree": "1.0.0-alpha22", "css-tree": "1.0.0-alpha22",
"estree-walker": "^0.6.0", "estree-walker": "^0.6.1",
"is-reference": "^1.1.1", "is-reference": "^1.1.1",
"jsdom": "^12.2.0", "jsdom": "^12.2.0",
"kleur": "^3.0.0", "kleur": "^3.0.0",

@ -1,5 +1,5 @@
<script> <script>
import Eliza from 'elizanode'; import Eliza from 'elizabot';
import { beforeUpdate, afterUpdate } from 'svelte'; import { beforeUpdate, afterUpdate } from 'svelte';
let div; let div;

@ -1,5 +1,5 @@
<script> <script>
import Eliza from 'elizanode'; import Eliza from 'elizabot';
import { beforeUpdate, afterUpdate } from 'svelte'; import { beforeUpdate, afterUpdate } from 'svelte';
let div; let div;

@ -1,5 +1,5 @@
<script> <script>
import Eliza from 'elizanode'; import Eliza from 'elizabot';
import { beforeUpdate, afterUpdate } from 'svelte'; import { beforeUpdate, afterUpdate } from 'svelte';
let div; let div;

@ -1362,13 +1362,15 @@
} }
}, },
"@sveltejs/svelte-repl": { "@sveltejs/svelte-repl": {
"version": "0.0.11", "version": "0.1.2",
"resolved": "https://registry.npmjs.org/@sveltejs/svelte-repl/-/svelte-repl-0.0.11.tgz", "resolved": "https://registry.npmjs.org/@sveltejs/svelte-repl/-/svelte-repl-0.1.2.tgz",
"integrity": "sha512-F284f8qaUs1rp8akqWXcB6oovlaso7qmsUz1rqm80FwUKLffjYIWy2a1p6+Yo1kRy6Q+fW8kj21JLEqv7pjOwA==", "integrity": "sha512-OHIj01ly4+/WwNb0zGqLSQL7POSs2BPx47CzryVsbu0omVDe7olYTJnCYV4ePUENnlL5JzZihzvlvxmVGP6knw==",
"dev": true, "dev": true,
"requires": { "requires": {
"codemirror": "^5.45.0", "codemirror": "^5.45.0",
"sourcemap-codec": "^1.4.4" "estree-walker": "^0.6.0",
"sourcemap-codec": "^1.4.4",
"yootils": "0.0.15"
} }
}, },
"@types/estree": { "@types/estree": {
@ -1799,9 +1801,9 @@
"dev": true "dev": true
}, },
"codemirror": { "codemirror": {
"version": "5.46.0", "version": "5.47.0",
"resolved": "https://registry.npmjs.org/codemirror/-/codemirror-5.46.0.tgz", "resolved": "https://registry.npmjs.org/codemirror/-/codemirror-5.47.0.tgz",
"integrity": "sha512-3QpMge0vg4QEhHW3hBAtCipJEWjTJrqLLXdIaWptJOblf1vHFeXLNtFhPai/uX2lnFCehWNk4yOdaMR853Z02w==", "integrity": "sha512-kV49Fr+NGFHFc/Imsx6g180hSlkGhuHxTSDDmDHOuyln0MQYFLixDY4+bFkBVeCEiepYfDimAF/e++9jPJk4QA==",
"dev": true "dev": true
}, },
"collection-visit": { "collection-visit": {

@ -3,9 +3,10 @@
"version": "1.0.0", "version": "1.0.0",
"description": "Docs and examples for Svelte", "description": "Docs and examples for Svelte",
"scripts": { "scripts": {
"dev": "sapper dev", "dev": "npm run copy-workers && sapper dev",
"copy-workers": "rm -rf static/workers && cp -r node_modules/@sveltejs/svelte-repl/workers static",
"migrate": "node-pg-migrate -r dotenv/config", "migrate": "node-pg-migrate -r dotenv/config",
"sapper": "sapper build --legacy", "sapper": "npm run copy-workers && sapper build --legacy",
"update_shimport": "cp node_modules/shimport/index.js __sapper__/build/client/shimport@0.0.14.js", "update_shimport": "cp node_modules/shimport/index.js __sapper__/build/client/shimport@0.0.14.js",
"update": "node scripts/update_template.js && node scripts/get-contributors.js", "update": "node scripts/update_template.js && node scripts/get-contributors.js",
"start": "node __sapper__/build", "start": "node __sapper__/build",
@ -38,7 +39,7 @@
"@babel/runtime": "^7.4.4", "@babel/runtime": "^7.4.4",
"@sindresorhus/slugify": "^0.9.1", "@sindresorhus/slugify": "^0.9.1",
"@sveltejs/site-kit": "^1.0.4", "@sveltejs/site-kit": "^1.0.4",
"@sveltejs/svelte-repl": "0.0.11", "@sveltejs/svelte-repl": "^0.1.2",
"degit": "^2.1.3", "degit": "^2.1.3",
"dotenv": "^8.0.0", "dotenv": "^8.0.0",
"eslint-plugin-svelte3": "^1.0.0", "eslint-plugin-svelte3": "^1.0.0",

@ -116,6 +116,7 @@
{#if process.browser} {#if process.browser}
<Repl <Repl
bind:this={repl} bind:this={repl}
workersUrl="workers"
fixed={mobile} fixed={mobile}
{svelteUrl} {svelteUrl}
{rollupUrl} {rollupUrl}

@ -102,6 +102,7 @@
<div class="repl-container" class:loading={isLoading}> <div class="repl-container" class:loading={isLoading}>
<Repl <Repl
bind:this={repl} bind:this={repl}
workersUrl="workers"
{svelteUrl} {svelteUrl}
{rollupUrl} {rollupUrl}
orientation={replOrientation} orientation={replOrientation}

@ -206,6 +206,7 @@
<div class="viewport" class:offset={checked}> <div class="viewport" class:offset={checked}>
<Repl <Repl
bind:this={repl} bind:this={repl}
workersUrl="workers"
{svelteUrl} {svelteUrl}
{rollupUrl} {rollupUrl}
{relaxed} {relaxed}

@ -302,6 +302,7 @@
<div class="tutorial-repl"> <div class="tutorial-repl">
<Repl <Repl
bind:this={repl} bind:this={repl}
workersUrl="workers"
{svelteUrl} {svelteUrl}
{rollupUrl} {rollupUrl}
orientation={mobile ? 'columns' : 'rows'} orientation={mobile ? 'columns' : 'rows'}

@ -2,11 +2,12 @@ import sirv from 'sirv';
import * as sapper from '@sapper/server'; import * as sapper from '@sapper/server';
import { API } from './backend/auth'; import { API } from './backend/auth';
const { PORT=3000 } = process.env; const { PORT = 3000 } = process.env;
API() API()
.use( .use(
sirv('static', { sirv('static', {
dev: process.env.NODE_ENV === 'development',
setHeaders(res) { setHeaders(res) {
res.setHeader('Access-Control-Allow-Origin', '*'); res.setHeader('Access-Control-Allow-Origin', '*');
res.hasHeader('Cache-Control') || res.setHeader('Cache-Control', 'max-age=600'); // 10min default res.hasHeader('Cache-Control') || res.setHeader('Cache-Control', 'max-age=600'); // 10min default

@ -1,7 +1,22 @@
import { cubicOut } from 'svelte/easing'; import { cubicOut } from 'svelte/easing';
import { is_function } from 'svelte/internal'; import { is_function } from 'svelte/internal';
export function flip(node, animation, params) { // todo: same as Transition, should it be shared?
export interface AnimationConfig {
delay?: number,
duration?: number,
easing?: (t: number) => number,
css?: (t: number, u: number) => string,
tick?: (t: number, u: number) => void
}
interface FlipParams {
delay: number;
duration: number | ((len: number) => number);
easing: (t: number) => number,
}
export function flip(node: Element, animation: { from: DOMRect, to: DOMRect }, params: FlipParams): AnimationConfig {
const style = getComputedStyle(node); const style = getComputedStyle(node);
const transform = style.transform === 'none' ? '' : style.transform; const transform = style.transform === 'none' ? '' : style.transform;

@ -1,18 +1,28 @@
import { identity as linear, noop, now } from './utils'; import { identity as linear, noop, now } from './utils';
import { loop } from './loop'; import { loop } from './loop';
import { create_rule, delete_rule } from './style_manager'; import { create_rule, delete_rule } from './style_manager';
import { AnimationConfig } from '../animate';
export function create_animation(node, from, fn, params) {
//todo: documentation says it is DOMRect, but in IE it would be ClientRect
type PositionRect = DOMRect|ClientRect;
type AnimationFn = (node: Element, { from, to }: { from: PositionRect, to: PositionRect }, params: any) => AnimationConfig;
export function create_animation(node: Element & ElementCSSInlineStyle, from: PositionRect, fn: AnimationFn, params) {
if (!from) return noop; if (!from) return noop;
const to = node.getBoundingClientRect(); const to = node.getBoundingClientRect();
if (from.left === to.left && from.right === to.right && from.top === to.top && from.bottom === to.bottom) return noop; if (from.left === to.left && from.right === to.right && from.top === to.top && from.bottom === to.bottom) return noop;
const { const {
delay = 0, delay = 0,
duration = 300, duration = 300,
easing = linear, easing = linear,
// @ts-ignore todo: should this be separated from destructuring? Or start/end added to public api and documentation?
start: start_time = now() + delay, start: start_time = now() + delay,
// @ts-ignore todo:
end = start_time + duration, end = start_time + duration,
tick = noop, tick = noop,
css css
@ -67,7 +77,7 @@ export function create_animation(node, from, fn, params) {
return stop; return stop;
} }
export function fix_position(node) { export function fix_position(node: Element & ElementCSSInlineStyle) {
const style = getComputedStyle(node); const style = getComputedStyle(node);
if (style.position !== 'absolute' && style.position !== 'fixed') { if (style.position !== 'absolute' && style.position !== 'fixed') {

@ -53,8 +53,8 @@ export function object_without_properties<T,K extends keyof T>(obj:T, exclude: K
return target; return target;
} }
export function svg_element(name:string):SVGElement { export function svg_element<K extends keyof SVGElementTagNameMap>(name:K):SVGElement {
return document.createElementNS('http://www.w3.org/2000/svg', name); return document.createElementNS<K>('http://www.w3.org/2000/svg', name);
} }
export function text(data:string) { export function text(data:string) {
@ -95,7 +95,7 @@ export function attr(node: Element, attribute: string, value?: string) {
else node.setAttribute(attribute, value); else node.setAttribute(attribute, value);
} }
export function set_attributes(node: HTMLElement, attributes: { [x: string]: string; }) { export function set_attributes(node: Element & ElementCSSInlineStyle, attributes: { [x: string]: string; }) {
for (const key in attributes) { for (const key in attributes) {
if (key === 'style') { if (key === 'style') {
node.style.cssText = attributes[key]; node.style.cssText = attributes[key];

@ -1,6 +1,6 @@
import { now, raf } from './utils'; import { now, raf } from './utils';
export interface Task { abort(): void; promise: Promise<undefined> } export interface Task { abort(): void; promise: Promise<void> }
const tasks = new Set(); const tasks = new Set();
let running = false; let running = false;
@ -32,7 +32,7 @@ export function loop(fn: (number)=>void): Task {
} }
return { return {
promise: new Promise<undefined>(fulfil => { promise: new Promise<void>(fulfil => {
tasks.add(task = [fn, fulfil]); tasks.add(task = [fn, fulfil]);
}), }),
abort() { abort() {

@ -1,5 +1,6 @@
import { set_current_component, current_component } from './lifecycle'; import { set_current_component, current_component } from './lifecycle';
import { run_all, blank_object } from './utils'; import { run_all, blank_object } from './utils';
import { Readable } from 'svelte/store';
export const invalid_attribute_name_character = /[\s'">/=\u{FDD0}-\u{FDEF}\u{FFFE}\u{FFFF}\u{1FFFE}\u{1FFFF}\u{2FFFE}\u{2FFFF}\u{3FFFE}\u{3FFFF}\u{4FFFE}\u{4FFFF}\u{5FFFE}\u{5FFFF}\u{6FFFE}\u{6FFFF}\u{7FFFE}\u{7FFFF}\u{8FFFE}\u{8FFFF}\u{9FFFE}\u{9FFFF}\u{AFFFE}\u{AFFFF}\u{BFFFE}\u{BFFFF}\u{CFFFE}\u{CFFFF}\u{DFFFE}\u{DFFFF}\u{EFFFE}\u{EFFFF}\u{FFFFE}\u{FFFFF}\u{10FFFE}\u{10FFFF}]/u; export const invalid_attribute_name_character = /[\s'">/=\u{FDD0}-\u{FDEF}\u{FFFE}\u{FFFF}\u{1FFFE}\u{1FFFF}\u{2FFFE}\u{2FFFF}\u{3FFFE}\u{3FFFF}\u{4FFFE}\u{4FFFF}\u{5FFFE}\u{5FFFF}\u{6FFFE}\u{6FFFF}\u{7FFFE}\u{7FFFF}\u{8FFFE}\u{8FFFF}\u{9FFFE}\u{9FFFF}\u{AFFFE}\u{AFFFF}\u{BFFFE}\u{BFFFF}\u{CFFFE}\u{CFFFF}\u{DFFFE}\u{DFFFF}\u{EFFFE}\u{EFFFF}\u{FFFFE}\u{FFFFF}\u{10FFFE}\u{10FFFF}]/u;
// https://html.spec.whatwg.org/multipage/syntax.html#attributes-2 // https://html.spec.whatwg.org/multipage/syntax.html#attributes-2
@ -113,7 +114,7 @@ export function create_ssr_component(fn) {
}; };
} }
export function get_store_value(store) { export function get_store_value<T>(store: Readable<T>): T | undefined {
let value; let value;
store.subscribe(_ => value = _)(); store.subscribe(_ => value = _)();
return value; return value;

@ -6,7 +6,7 @@ let active = 0;
let current_rules = {}; let current_rules = {};
// https://github.com/darkskyapp/string-hash/blob/master/index.js // https://github.com/darkskyapp/string-hash/blob/master/index.js
function hash(str) { function hash(str: string) {
let hash = 5381; let hash = 5381;
let i = str.length; let i = str.length;
@ -14,7 +14,7 @@ function hash(str) {
return hash >>> 0; return hash >>> 0;
} }
export function create_rule(node, a, b, duration, delay, ease, fn, uid = 0) { export function create_rule(node: Element & ElementCSSInlineStyle, a: number, b: number, duration: number, delay: number, ease: (t: number) => number, fn: (t: number, u: number) => string, uid: number = 0) {
const step = 16.666 / duration; const step = 16.666 / duration;
let keyframes = '{\n'; let keyframes = '{\n';
@ -44,7 +44,7 @@ export function create_rule(node, a, b, duration, delay, ease, fn, uid = 0) {
return name; return name;
} }
export function delete_rule(node, name?) { export function delete_rule(node: Element & ElementCSSInlineStyle, name?: string) {
node.style.animation = (node.style.animation || '') node.style.animation = (node.style.animation || '')
.split(', ') .split(', ')
.filter(name .filter(name

@ -1,10 +1,11 @@
import { identity as linear, noop, now, run_all } from './utils'; import { identity as linear, is_function, noop, now, run_all } from './utils';
import { loop } from './loop'; import { loop } from './loop';
import { create_rule, delete_rule } from './style_manager'; import { create_rule, delete_rule } from './style_manager';
import { custom_event } from './dom'; import { custom_event } from './dom';
import { add_render_callback } from './scheduler'; import { add_render_callback } from './scheduler';
import { TransitionConfig } from '../transition';
let promise; let promise: Promise<void>|null;
function wait() { function wait() {
if (!promise) { if (!promise) {
@ -17,7 +18,7 @@ function wait() {
return promise; return promise;
} }
function dispatch(node, direction, kind) { function dispatch(node: Element, direction: boolean, kind: 'start' | 'end') {
node.dispatchEvent(custom_event(`${direction ? 'intro' : 'outro'}${kind}`)); node.dispatchEvent(custom_event(`${direction ? 'intro' : 'outro'}${kind}`));
} }
@ -39,8 +40,9 @@ export function check_outros() {
export function on_outro(callback) { export function on_outro(callback) {
outros.callbacks.push(callback); outros.callbacks.push(callback);
} }
type TransitionFn = (node: Element, params: any) => TransitionConfig;
export function create_in_transition(node, fn, params) { export function create_in_transition(node: Element & ElementCSSInlineStyle, fn: TransitionFn, params: any) {
let config = fn(node, params); let config = fn(node, params);
let running = false; let running = false;
let animation_name; let animation_name;
@ -95,7 +97,7 @@ export function create_in_transition(node, fn, params) {
delete_rule(node); delete_rule(node);
if (typeof config === 'function') { if (is_function(config)) {
config = config(); config = config();
wait().then(go); wait().then(go);
} else { } else {
@ -116,7 +118,7 @@ export function create_in_transition(node, fn, params) {
}; };
} }
export function create_out_transition(node, fn, params) { export function create_out_transition(node: Element & ElementCSSInlineStyle, fn: TransitionFn, params: any) {
let config = fn(node, params); let config = fn(node, params);
let running = true; let running = true;
let animation_name; let animation_name;
@ -163,8 +165,9 @@ export function create_out_transition(node, fn, params) {
}); });
} }
if (typeof config === 'function') { if (is_function(config)) {
wait().then(() => { wait().then(() => {
// @ts-ignore
config = config(); config = config();
go(); go();
}); });
@ -186,7 +189,7 @@ export function create_out_transition(node, fn, params) {
}; };
} }
export function create_bidirectional_transition(node, fn, params, intro) { export function create_bidirectional_transition(node: Element & ElementCSSInlineStyle, fn: TransitionFn, params: any, intro: boolean) {
let config = fn(node, params); let config = fn(node, params);
let t = intro ? 0 : 1; let t = intro ? 0 : 1;
@ -295,8 +298,9 @@ export function create_bidirectional_transition(node, fn, params, intro) {
return { return {
run(b) { run(b) {
if (typeof config === 'function') { if (is_function(config)) {
wait().then(() => { wait().then(() => {
// @ts-ignore
config = config(); config = config();
go(b); go(b);
}); });

@ -2,13 +2,14 @@ export function noop() {}
export const identity = x => x; export const identity = x => x;
export function assign(tar, src) { export function assign<T, S>(tar:T, src:S): T & S {
// @ts-ignore
for (const k in src) tar[k] = src[k]; for (const k in src) tar[k] = src[k];
return tar; return tar as T & S;
} }
export function is_promise(value) { export function is_promise<T = any>(value: any): value is PromiseLike<T> {
return value && typeof value.then === 'function'; return value && typeof value === 'object' && typeof value.then === 'function';
} }
export function add_location(element, file, line, column, char) { export function add_location(element, file, line, column, char) {
@ -29,7 +30,7 @@ export function run_all(fns) {
fns.forEach(run); fns.forEach(run);
} }
export function is_function(thing) { export function is_function(thing: any): thing is Function {
return typeof thing === 'function'; return typeof thing === 'function';
} }

@ -2,9 +2,18 @@ import { Readable, writable } from 'svelte/store';
import { loop, now, Task } from 'svelte/internal'; import { loop, now, Task } from 'svelte/internal';
import { is_date } from './utils'; import { is_date } from './utils';
function tick_spring(ctx, last_value, current_value, target_value) { interface TickContext<T> {
inv_mass: number;
dt: number;
opts: Spring<T>;
settled: boolean
}
function tick_spring<T>(ctx: TickContext<T>, last_value: T, current_value: T, target_value: T):T {
if (typeof current_value === 'number' || is_date(current_value)) { if (typeof current_value === 'number' || is_date(current_value)) {
// @ts-ignore
const delta = target_value - current_value; const delta = target_value - current_value;
// @ts-ignore
const velocity = (current_value - last_value) / (ctx.dt||1/60); // guard div by 0 const velocity = (current_value - last_value) / (ctx.dt||1/60); // guard div by 0
const spring = ctx.opts.stiffness * delta; const spring = ctx.opts.stiffness * delta;
const damper = ctx.opts.damping * velocity; const damper = ctx.opts.damping * velocity;
@ -15,16 +24,20 @@ function tick_spring(ctx, last_value, current_value, target_value) {
return target_value; // settled return target_value; // settled
} else { } else {
ctx.settled = false; // signal loop to keep ticking ctx.settled = false; // signal loop to keep ticking
// @ts-ignore
return is_date(current_value) ? return is_date(current_value) ?
new Date(current_value.getTime() + d) : current_value + d; new Date(current_value.getTime() + d) : current_value + d;
} }
} else if (Array.isArray(current_value)) { } else if (Array.isArray(current_value)) {
// @ts-ignore
return current_value.map((_, i) => return current_value.map((_, i) =>
tick_spring(ctx, last_value[i], current_value[i], target_value[i])); tick_spring(ctx, last_value[i], current_value[i], target_value[i]));
} else if (typeof current_value === 'object') { } else if (typeof current_value === 'object') {
const next_value = {}; const next_value = {};
for (const k in current_value) for (const k in current_value)
// @ts-ignore
next_value[k] = tick_spring(ctx, last_value[k], current_value[k], target_value[k]); next_value[k] = tick_spring(ctx, last_value[k], current_value[k], target_value[k]);
// @ts-ignore
return next_value; return next_value;
} else { } else {
throw new Error(`Cannot spring ${typeof current_value} values`); throw new Error(`Cannot spring ${typeof current_value} values`);
@ -37,17 +50,22 @@ interface SpringOpts {
precision?: number, precision?: number,
} }
type SpringUpdateOpts = { hard?: any; soft?: string | number | boolean; }; interface SpringUpdateOpts {
hard?: any;
soft?: string | number | boolean;
}
type Updater<T> = (target_value: T, value: T) => T;
interface Spring<T=any> extends Readable<T>{ interface Spring<T> extends Readable<T>{
set: (new_value: T, opts?: SpringUpdateOpts) => (Promise<T> | Promise<T>); set: (new_value: T, opts?: SpringUpdateOpts) => Promise<void>;
update: (fn: Updater<T>, opts?: SpringUpdateOpts) => Promise<void>;
precision: number; precision: number;
update: (fn, opts: SpringUpdateOpts) => Promise<T>;
damping: number; damping: number;
stiffness: number stiffness: number
} }
export function spring<T=any>(value: T, opts: SpringOpts = {}) { export function spring<T=any>(value: T, opts: SpringOpts = {}): Spring<T> {
const store = writable(value); const store = writable(value);
const { stiffness = 0.15, damping = 0.8, precision = 0.01 } = opts; const { stiffness = 0.15, damping = 0.8, precision = 0.01 } = opts;
@ -61,7 +79,7 @@ export function spring<T=any>(value: T, opts: SpringOpts = {}) {
let inv_mass_recovery_rate = 0; let inv_mass_recovery_rate = 0;
let cancel_task = false; let cancel_task = false;
function set(new_value: any, opts: SpringUpdateOpts={}) { function set(new_value: T, opts: SpringUpdateOpts={}): Promise<void> {
target_value = new_value; target_value = new_value;
const token = current_token = {}; const token = current_token = {};
@ -91,7 +109,7 @@ export function spring<T=any>(value: T, opts: SpringOpts = {}) {
inv_mass = Math.min(inv_mass + inv_mass_recovery_rate, 1); inv_mass = Math.min(inv_mass + inv_mass_recovery_rate, 1);
const ctx = { const ctx: TickContext<T> = {
inv_mass, inv_mass,
opts: spring, opts: spring,
settled: true, // tick_spring may signal false settled: true, // tick_spring may signal false
@ -116,14 +134,14 @@ export function spring<T=any>(value: T, opts: SpringOpts = {}) {
}); });
} }
const spring: Spring = { const spring = {
set, set,
update: (fn, opts:SpringUpdateOpts) => set(fn(target_value, value), opts), update: (fn, opts:SpringUpdateOpts) => set(fn(target_value, value), opts),
subscribe: store.subscribe, subscribe: store.subscribe,
stiffness, stiffness,
damping, damping,
precision precision
}; } as Spring<T>;
return spring; return spring;
} }

@ -1,6 +1,6 @@
import { writable } from 'svelte/store'; // eslint-disable-line import/no-unresolved import { Readable, writable } from 'svelte/store';
import { assign, loop, now } from 'svelte/internal'; // eslint-disable-line import/no-unresolved import { assign, loop, now, Task } from 'svelte/internal';
import { linear } from 'svelte/easing'; // eslint-disable-line import/no-unresolved import { linear } from 'svelte/easing';
import { is_date } from './utils'; import { is_date } from './utils';
function get_interpolator(a, b) { function get_interpolator(a, b) {
@ -54,13 +54,28 @@ function get_interpolator(a, b) {
throw new Error(`Cannot interpolate ${type} values`); throw new Error(`Cannot interpolate ${type} values`);
} }
export function tweened(value, defaults = {}) { interface Options<T> {
delay?: number;
duration?: number | ((from: T, to: T) => number)
easing?: (t: number) => number;
interpolate?: (a: T, b: T) => (t: number) => T
}
type Updater<T> = (target_value: T, value: T) => T;
interface Tweened<T> extends Readable<T> {
set(value: T, opts: Options<T>): Promise<void>;
update(updater: Updater<T>, opts: Options<T>): Promise<void>;
}
export function tweened<T>(value: T, defaults: Options<T> = {}):Tweened<T> {
const store = writable(value); const store = writable(value);
let task; let task: Task;
let target_value = value; let target_value = value;
function set(new_value, opts) { function set(new_value: T, opts: Options<T>) {
target_value = new_value; target_value = new_value;
let previous_task = task; let previous_task = task;
@ -97,6 +112,7 @@ export function tweened(value, defaults = {}) {
return false; return false;
} }
// @ts-ignore
store.set(value = fn(easing(elapsed / duration))); store.set(value = fn(easing(elapsed / duration)));
return true; return true;
}); });
@ -106,7 +122,7 @@ export function tweened(value, defaults = {}) {
return { return {
set, set,
update: (fn, opts) => set(fn(target_value, value), opts), update: (fn, opts:Options<T>) => set(fn(target_value, value), opts),
subscribe: store.subscribe subscribe: store.subscribe
}; };
} }

@ -1,3 +1,3 @@
export function is_date(obj: any) { export function is_date(obj: any): obj is Date {
return Object.prototype.toString.call(obj) === '[object Date]'; return Object.prototype.toString.call(obj) === '[object Date]';
} }

@ -1,10 +1,23 @@
import { cubicOut, cubicInOut } from 'svelte/easing'; import { cubicOut, cubicInOut } from 'svelte/easing';
import { assign, is_function } from 'svelte/internal'; import { assign, is_function } from 'svelte/internal';
export function fade(node, { export interface TransitionConfig {
delay?: number,
duration?: number,
easing?: (t: number) => number,
css?: (t: number, u: number) => string,
tick?: (t: number, u: number) => void
}
interface FadeParams {
delay: number;
duration: number;
}
export function fade(node: Element, {
delay = 0, delay = 0,
duration = 400 duration = 400
}) { }: FadeParams): TransitionConfig {
const o = +getComputedStyle(node).opacity; const o = +getComputedStyle(node).opacity;
return { return {
@ -14,14 +27,23 @@ export function fade(node, {
}; };
} }
export function fly(node, { interface FlyParams {
delay: number;
duration: number;
easing: (t: number)=>number,
x: number;
y: number;
opacity: number;
}
export function fly(node: Element, {
delay = 0, delay = 0,
duration = 400, duration = 400,
easing = cubicOut, easing = cubicOut,
x = 0, x = 0,
y = 0, y = 0,
opacity = 0 opacity = 0
}) { }: FlyParams): TransitionConfig {
const style = getComputedStyle(node); const style = getComputedStyle(node);
const target_opacity = +style.opacity; const target_opacity = +style.opacity;
const transform = style.transform === 'none' ? '' : style.transform; const transform = style.transform === 'none' ? '' : style.transform;
@ -38,11 +60,17 @@ export function fly(node, {
}; };
} }
export function slide(node, { interface SlideParams {
delay: number;
duration: number;
easing: (t: number)=>number,
}
export function slide(node: Element, {
delay = 0, delay = 0,
duration = 400, duration = 400,
easing = cubicOut easing = cubicOut
}) { }: SlideParams): TransitionConfig {
const style = getComputedStyle(node); const style = getComputedStyle(node);
const opacity = +style.opacity; const opacity = +style.opacity;
const height = parseFloat(style.height); const height = parseFloat(style.height);
@ -70,13 +98,21 @@ export function slide(node, {
}; };
} }
export function scale(node, { interface ScaleParams {
delay: number;
duration: number;
easing: (t: number)=>number,
start: number;
opacity: number;
}
export function scale(node: Element, {
delay = 0, delay = 0,
duration = 400, duration = 400,
easing = cubicOut, easing = cubicOut,
start = 0, start = 0,
opacity = 0 opacity = 0
}) { }: ScaleParams): TransitionConfig {
const style = getComputedStyle(node); const style = getComputedStyle(node);
const target_opacity = +style.opacity; const target_opacity = +style.opacity;
const transform = style.transform === 'none' ? '' : style.transform; const transform = style.transform === 'none' ? '' : style.transform;
@ -95,12 +131,19 @@ export function scale(node, {
}; };
} }
export function draw(node, { interface DrawParams {
delay: number;
speed: number;
duration: number | ((len: number) => number);
easing: (t: number) => number,
}
export function draw(node: SVGElement & { getTotalLength(): number }, {
delay = 0, delay = 0,
speed, speed,
duration, duration,
easing = cubicInOut easing = cubicInOut
}) { }: DrawParams): TransitionConfig {
const len = node.getTotalLength(); const len = node.getTotalLength();
if (duration === undefined) { if (duration === undefined) {
@ -121,11 +164,21 @@ export function draw(node, {
}; };
} }
export function crossfade({ fallback, ...defaults }) { interface CrossfadeParams {
const to_receive = new Map(); delay: number;
const to_send = new Map(); duration: number | ((len: number) => number);
easing: (t: number) => number,
}
type ClientRectMap = Map<any, { rect: ClientRect }>;
export function crossfade({ fallback, ...defaults }: CrossfadeParams & {
fallback: (node: Element, params: CrossfadeParams, intro: boolean)=> TransitionConfig
}) {
const to_receive: ClientRectMap = new Map();
const to_send: ClientRectMap = new Map();
function crossfade(from, node, params) { function crossfade(from: ClientRect, node: Element, params: CrossfadeParams):TransitionConfig {
const { const {
delay = 0, delay = 0,
duration = d => Math.sqrt(d) * 30, duration = d => Math.sqrt(d) * 30,
@ -152,8 +205,8 @@ export function crossfade({ fallback, ...defaults }) {
}; };
} }
function transition(items, counterparts, intro) { function transition(items: ClientRectMap, counterparts: ClientRectMap, intro: boolean) {
return (node, params) => { return (node: Element, params: CrossfadeParams & { key: any }) => {
items.set(params.key, { items.set(params.key, {
rect: node.getBoundingClientRect() rect: node.getBoundingClientRect()
}); });

Loading…
Cancel
Save