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 './keyed-each.js';
|
||||
export * from './scheduler.js';
|
||||
export * from './spread.js';
|
||||
export * from './ssr.js';
|
||||
export * from './transitions.js';
|
||||
export * from './utils.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