mirror of https://github.com/sveltejs/svelte
parent
56eeead1b3
commit
4aa510d2d9
@ -0,0 +1,102 @@
|
|||||||
|
import { transitionManager, linear, generateRule, hash } from './transitions.js';
|
||||||
|
|
||||||
|
export function wrapAnimation(node, from, fn, params) {
|
||||||
|
if (!from) return;
|
||||||
|
|
||||||
|
const to = node.getBoundingClientRect();
|
||||||
|
if (from.left === to.left && from.right === to.right && from.top === to.top && from.bottom === to.bottom) return;
|
||||||
|
|
||||||
|
const info = fn(node, { from, to }, params);
|
||||||
|
|
||||||
|
const duration = 'duration' in info ? info.duration : 300;
|
||||||
|
const delay = 'delay' in info ? info.delay : 0;
|
||||||
|
const ease = info.easing || linear;
|
||||||
|
const start = window.performance.now() + delay;
|
||||||
|
const end = start + duration;
|
||||||
|
|
||||||
|
const program = {
|
||||||
|
a: 0,
|
||||||
|
t: 0,
|
||||||
|
b: 1,
|
||||||
|
delta: 1,
|
||||||
|
duration,
|
||||||
|
start,
|
||||||
|
end
|
||||||
|
};
|
||||||
|
|
||||||
|
const cssText = node.style.cssText;
|
||||||
|
|
||||||
|
const animation = {
|
||||||
|
pending: delay ? program : null,
|
||||||
|
program: delay ? null : program,
|
||||||
|
running: true,
|
||||||
|
|
||||||
|
start() {
|
||||||
|
if (info.css) {
|
||||||
|
if (delay) node.style.cssText = cssText;
|
||||||
|
|
||||||
|
const rule = generateRule(program, ease, info.css);
|
||||||
|
program.name = `__svelte_${hash(rule)}`;
|
||||||
|
|
||||||
|
transitionManager.addRule(rule, program.name);
|
||||||
|
|
||||||
|
node.style.animation = (node.style.animation || '')
|
||||||
|
.split(', ')
|
||||||
|
.filter(anim => anim && (program.delta < 0 || !/__svelte/.test(anim)))
|
||||||
|
.concat(`${program.name} ${program.duration}ms linear 1 forwards`)
|
||||||
|
.join(', ');
|
||||||
|
}
|
||||||
|
|
||||||
|
animation.program = program;
|
||||||
|
animation.pending = null;
|
||||||
|
},
|
||||||
|
|
||||||
|
update: now => {
|
||||||
|
const p = now - program.start;
|
||||||
|
const t = program.a + program.delta * ease(p / program.duration);
|
||||||
|
if (info.tick) info.tick(t, 1 - t);
|
||||||
|
},
|
||||||
|
|
||||||
|
done() {
|
||||||
|
if (info.tick) info.tick(1, 0);
|
||||||
|
animation.stop();
|
||||||
|
},
|
||||||
|
|
||||||
|
stop() {
|
||||||
|
if (info.css) transitionManager.deleteRule(node, program.name);
|
||||||
|
animation.running = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
transitionManager.add(animation);
|
||||||
|
|
||||||
|
if (info.tick) info.tick(0, 1);
|
||||||
|
|
||||||
|
if (delay) {
|
||||||
|
if (info.css) node.style.cssText += info.css(0, 1);
|
||||||
|
} else {
|
||||||
|
animation.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
return animation;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function fixPosition(node) {
|
||||||
|
const style = getComputedStyle(node);
|
||||||
|
|
||||||
|
if (style.position !== 'absolute' && style.position !== 'fixed') {
|
||||||
|
const { width, height } = style;
|
||||||
|
const a = node.getBoundingClientRect();
|
||||||
|
node.style.position = 'absolute';
|
||||||
|
node.style.width = width;
|
||||||
|
node.style.height = height;
|
||||||
|
const b = node.getBoundingClientRect();
|
||||||
|
|
||||||
|
if (a.left !== b.left || a.top !== b.top) {
|
||||||
|
const style = getComputedStyle(node);
|
||||||
|
const transform = style.transform === 'none' ? '' : style.transform;
|
||||||
|
|
||||||
|
node.style.transform = `${transform} translate(${a.left - b.left}px, ${a.top - b.top}px)`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,60 @@
|
|||||||
|
import { assign, isPromise } from './utils.js';
|
||||||
|
import { groupOutros } from './transitions.js';
|
||||||
|
|
||||||
|
export function handlePromise(promise, info) {
|
||||||
|
var token = info.token = {};
|
||||||
|
|
||||||
|
function update(type, index, key, value) {
|
||||||
|
if (info.token !== token) return;
|
||||||
|
|
||||||
|
info.resolved = key && { [key]: value };
|
||||||
|
|
||||||
|
const child_ctx = assign(assign({}, info.ctx), info.resolved);
|
||||||
|
const block = type && (info.current = type)(info.component, child_ctx);
|
||||||
|
|
||||||
|
if (info.block) {
|
||||||
|
if (info.blocks) {
|
||||||
|
info.blocks.forEach((block, i) => {
|
||||||
|
if (i !== index && block) {
|
||||||
|
groupOutros();
|
||||||
|
block.o(() => {
|
||||||
|
block.d(1);
|
||||||
|
info.blocks[i] = null;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
info.block.d(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
block.c();
|
||||||
|
block[block.i ? 'i' : 'm'](info.mount(), info.anchor);
|
||||||
|
|
||||||
|
info.component.root.set({}); // flush any handlers that were created
|
||||||
|
}
|
||||||
|
|
||||||
|
info.block = block;
|
||||||
|
if (info.blocks) info.blocks[index] = block;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isPromise(promise)) {
|
||||||
|
promise.then(value => {
|
||||||
|
update(info.then, 1, info.value, value);
|
||||||
|
}, error => {
|
||||||
|
update(info.catch, 2, info.error, error);
|
||||||
|
});
|
||||||
|
|
||||||
|
// if we previously had a then/catch block, destroy it
|
||||||
|
if (info.current !== info.pending) {
|
||||||
|
update(info.pending, 0);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (info.current !== info.then) {
|
||||||
|
update(info.then, 1, info.value, promise);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
info.resolved = { [info.value]: promise };
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,10 @@
|
|||||||
|
export * from './animations.js';
|
||||||
|
export * from './await-block.js';
|
||||||
export * from './dom.js';
|
export * from './dom.js';
|
||||||
|
export * from './keyed-each.js';
|
||||||
export * from './scheduler.js';
|
export * from './scheduler.js';
|
||||||
|
export * from './spread.js';
|
||||||
|
export * from './ssr.js';
|
||||||
export * from './transitions.js';
|
export * from './transitions.js';
|
||||||
export * from './utils.js';
|
export * from './utils.js';
|
||||||
export * from './SvelteComponent.js';
|
export * from './SvelteComponent.js';
|
@ -0,0 +1,123 @@
|
|||||||
|
export function destroyBlock(block, lookup) {
|
||||||
|
block.d(1);
|
||||||
|
lookup[block.key] = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function outroAndDestroyBlock(block, lookup) {
|
||||||
|
block.o(function() {
|
||||||
|
destroyBlock(block, lookup);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function fixAndOutroAndDestroyBlock(block, lookup) {
|
||||||
|
block.f();
|
||||||
|
outroAndDestroyBlock(block, lookup);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function updateKeyedEach(old_blocks, changed, get_key, dynamic, ctx, list, lookup, node, destroy, create_each_block, intro_method, next, get_context) {
|
||||||
|
var o = old_blocks.length;
|
||||||
|
var n = list.length;
|
||||||
|
|
||||||
|
var i = o;
|
||||||
|
var old_indexes = {};
|
||||||
|
while (i--) old_indexes[old_blocks[i].key] = i;
|
||||||
|
|
||||||
|
var new_blocks = [];
|
||||||
|
var new_lookup = {};
|
||||||
|
var deltas = {};
|
||||||
|
|
||||||
|
var i = n;
|
||||||
|
while (i--) {
|
||||||
|
var child_ctx = get_context(ctx, list, i);
|
||||||
|
var key = get_key(child_ctx);
|
||||||
|
var block = lookup[key];
|
||||||
|
|
||||||
|
if (!block) {
|
||||||
|
block = create_each_block(key, child_ctx);
|
||||||
|
block.c();
|
||||||
|
} else if (dynamic) {
|
||||||
|
block.p(changed, child_ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
new_blocks[i] = new_lookup[key] = block;
|
||||||
|
|
||||||
|
if (key in old_indexes) deltas[key] = Math.abs(i - old_indexes[key]);
|
||||||
|
}
|
||||||
|
|
||||||
|
var will_move = {};
|
||||||
|
var did_move = {};
|
||||||
|
|
||||||
|
function insert(block) {
|
||||||
|
block[intro_method](node, next);
|
||||||
|
lookup[block.key] = block;
|
||||||
|
next = block.first;
|
||||||
|
n--;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (o && n) {
|
||||||
|
var new_block = new_blocks[n - 1];
|
||||||
|
var old_block = old_blocks[o - 1];
|
||||||
|
var new_key = new_block.key;
|
||||||
|
var old_key = old_block.key;
|
||||||
|
|
||||||
|
if (new_block === old_block) {
|
||||||
|
// do nothing
|
||||||
|
next = new_block.first;
|
||||||
|
o--;
|
||||||
|
n--;
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (!new_lookup[old_key]) {
|
||||||
|
// remove old block
|
||||||
|
destroy(old_block, lookup);
|
||||||
|
o--;
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (!lookup[new_key] || will_move[new_key]) {
|
||||||
|
insert(new_block);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (did_move[old_key]) {
|
||||||
|
o--;
|
||||||
|
|
||||||
|
} else if (deltas[new_key] > deltas[old_key]) {
|
||||||
|
did_move[new_key] = true;
|
||||||
|
insert(new_block);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
will_move[old_key] = true;
|
||||||
|
o--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
while (o--) {
|
||||||
|
var old_block = old_blocks[o];
|
||||||
|
if (!new_lookup[old_block.key]) destroy(old_block, lookup);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (n) insert(new_blocks[n - 1]);
|
||||||
|
|
||||||
|
return new_blocks;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function measure(blocks) {
|
||||||
|
const rects = {};
|
||||||
|
let i = blocks.length;
|
||||||
|
while (i--) rects[blocks[i].key] = blocks[i].node.getBoundingClientRect();
|
||||||
|
return rects;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function animate(blocks, rects, fn, params) {
|
||||||
|
let i = blocks.length;
|
||||||
|
while (i--) {
|
||||||
|
const block = blocks[i];
|
||||||
|
const from = rects[block.key];
|
||||||
|
|
||||||
|
if (!from) continue;
|
||||||
|
const to = block.node.getBoundingClientRect();
|
||||||
|
|
||||||
|
if (from.left === to.left && from.right === to.right && from.top === to.top && from.bottom === to.bottom) continue;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,37 @@
|
|||||||
|
export function getSpreadUpdate(levels, updates) {
|
||||||
|
var update = {};
|
||||||
|
|
||||||
|
var to_null_out = {};
|
||||||
|
var accounted_for = {};
|
||||||
|
|
||||||
|
var i = levels.length;
|
||||||
|
while (i--) {
|
||||||
|
var o = levels[i];
|
||||||
|
var n = updates[i];
|
||||||
|
|
||||||
|
if (n) {
|
||||||
|
for (var key in o) {
|
||||||
|
if (!(key in n)) to_null_out[key] = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var key in n) {
|
||||||
|
if (!accounted_for[key]) {
|
||||||
|
update[key] = n[key];
|
||||||
|
accounted_for[key] = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
levels[i] = n;
|
||||||
|
} else {
|
||||||
|
for (var key in o) {
|
||||||
|
accounted_for[key] = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var key in to_null_out) {
|
||||||
|
if (!(key in update)) update[key] = undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
return update;
|
||||||
|
}
|
@ -0,0 +1,63 @@
|
|||||||
|
// https://html.spec.whatwg.org/multipage/syntax.html#attributes-2
|
||||||
|
// https://infra.spec.whatwg.org/#noncharacter
|
||||||
|
export const invalidAttributeNameCharacter = /[\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 function spread(args) {
|
||||||
|
const attributes = Object.assign({}, ...args);
|
||||||
|
let str = '';
|
||||||
|
|
||||||
|
Object.keys(attributes).forEach(name => {
|
||||||
|
if (invalidAttributeNameCharacter.test(name)) return;
|
||||||
|
|
||||||
|
const value = attributes[name];
|
||||||
|
if (value === undefined) return;
|
||||||
|
if (value === true) str += " " + name;
|
||||||
|
|
||||||
|
const escaped = String(value)
|
||||||
|
.replace(/"/g, '"')
|
||||||
|
.replace(/'/g, ''');
|
||||||
|
|
||||||
|
str += " " + name + "=" + JSON.stringify(escaped);
|
||||||
|
});
|
||||||
|
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const escaped = {
|
||||||
|
'"': '"',
|
||||||
|
"'": ''',
|
||||||
|
'&': '&',
|
||||||
|
'<': '<',
|
||||||
|
'>': '>'
|
||||||
|
};
|
||||||
|
|
||||||
|
export function escape(html) {
|
||||||
|
return String(html).replace(/["'&<>]/g, match => escaped[match]);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function each(items, assign, fn) {
|
||||||
|
let str = '';
|
||||||
|
for (let i = 0; i < items.length; i += 1) {
|
||||||
|
str += fn(assign(items[i], i));
|
||||||
|
}
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const missingComponent = {
|
||||||
|
_render: () => ''
|
||||||
|
};
|
||||||
|
|
||||||
|
export function validateSsrComponent(component, name) {
|
||||||
|
if (!component || !component._render) {
|
||||||
|
if (name === 'svelte:component') name += ' this={...}';
|
||||||
|
throw new Error(`<${name}> is not a valid SSR component. You may need to review your build config to ensure that dependencies are compiled, rather than imported as pre-compiled modules`);
|
||||||
|
}
|
||||||
|
|
||||||
|
return component;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function debug(file, line, column, values) {
|
||||||
|
console.log(`{@debug} ${file ? file + ' ' : ''}(${line}:${column})`);
|
||||||
|
console.log(values);
|
||||||
|
return '';
|
||||||
|
}
|
Loading…
Reference in new issue