Fix sliding animation on table elements and in Safari

This is a proof-of-concept commit for comments. It is not yet cleaned up.
pull/5922/head
Chris Chua 6 years ago
parent ddfe920ede
commit e4ea648a70

@ -18,6 +18,32 @@ function hash(str: string) {
return hash >>> 0;
}
export function create_static_rule(node: Element & ElementCSSInlineStyle, rule: string, uid: number = 0) {
const className = `__svelte_${hash(rule)}_${uid}`;
const doc = node.ownerDocument as ExtendedDoc;
active_docs.add(doc);
const stylesheet = doc.__svelte_stylesheet || (doc.__svelte_stylesheet = doc.head.appendChild(element('style') as HTMLStyleElement).sheet as CSSStyleSheet);
const current_rules = doc.__svelte_rules || (doc.__svelte_rules = {});
if (!current_rules[className]) {
current_rules[className] = true;
stylesheet.insertRule(`.${className} {${rule}}`, stylesheet.cssRules.length);
}
node.classList.add(className);
active += 1;
return className;
}
export function delete_static_rule(node: Element & ElementCSSInlineStyle, name: string) {
if (name) {
node.classList.remove(name); // remove specific class
}
active -= 1;
if (!active) clear_rules();
}
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;
let keyframes = '{\n';

@ -1,7 +1,7 @@
import { identity as linear, is_function, noop, run_all } from './utils';
import { now } from './environment';
import { loop } from './loop';
import { create_rule, delete_rule } from './style_manager';
import { create_rule, delete_rule, create_static_rule, delete_static_rule } from './style_manager';
import { custom_event } from './dom';
import { add_render_callback } from './scheduler';
import { TransitionConfig } from '../transition';
@ -72,12 +72,14 @@ type TransitionFn = (node: Element, params: any) => TransitionConfig;
export function create_in_transition(node: Element & ElementCSSInlineStyle, fn: TransitionFn, params: any) {
let config = fn(node, params);
let running = false;
let static_class_name;
let animation_name;
let task;
let uid = 0;
function cleanup() {
if (animation_name) delete_rule(node, animation_name);
if (static_class_name) delete_static_rule(node, static_class_name);
}
function go() {
@ -86,9 +88,11 @@ export function create_in_transition(node: Element & ElementCSSInlineStyle, fn:
duration = 300,
easing = linear,
tick = noop,
css
css,
staticCss,
} = config || null_transition;
if (staticCss) static_class_name = create_static_rule(node, staticCss, uid++);
if (css) animation_name = create_rule(node, 0, 1, duration, delay, easing, css, uid++);
tick(0, 1);
@ -233,6 +237,14 @@ export function create_bidirectional_transition(node: Element & ElementCSSInline
let running_program = null;
let pending_program = null;
let animation_name = null;
let static_class_name = null;
function clear_static_css() {
if (static_class_name) {
delete_static_rule(node, static_class_name);
static_class_name = null;
}
}
function clear_animation() {
if (animation_name) delete_rule(node, animation_name);
@ -259,7 +271,8 @@ export function create_bidirectional_transition(node: Element & ElementCSSInline
duration = 300,
easing = linear,
tick = noop,
css
css,
staticCss
} = config || null_transition;
const program = {
@ -278,6 +291,9 @@ export function create_bidirectional_transition(node: Element & ElementCSSInline
} else {
// if this is an intro, and there's a delay, we need to do
// an initial tick and/or apply CSS animation immediately
if (staticCss && !static_class_name) {
static_class_name = create_static_rule(node, staticCss);
}
if (css) {
clear_animation();
animation_name = create_rule(node, t, b, duration, delay, easing, css);
@ -311,6 +327,7 @@ export function create_bidirectional_transition(node: Element & ElementCSSInline
if (running_program.b) {
// intro — we can tidy up immediately
clear_animation();
clear_static_css();
} else {
// outro — needs to be coordinated
if (!--running_program.group.r) run_all(running_program.group.c);
@ -345,6 +362,7 @@ export function create_bidirectional_transition(node: Element & ElementCSSInline
end() {
clear_animation();
clear_static_css();
running_program = pending_program = null;
}
};

@ -8,6 +8,7 @@ export interface TransitionConfig {
duration?: number;
easing?: EasingFunction;
css?: (t: number, u: number) => string;
staticCss?: string;
tick?: (t: number, u: number) => void;
}
@ -115,12 +116,19 @@ export function slide(node: Element, {
const border_top_width = parseFloat(style.borderTopWidth);
const border_bottom_width = parseFloat(style.borderBottomWidth);
let displayOverride = '';
// May want to use a whitelist instead
if (style.display.includes('table')) {
displayOverride = 'display: block;';
}
return {
// Support a custom className to be added before and cleaned up after the thing.
staticCss: displayOverride + 'overflow: hidden;',
delay,
duration,
easing,
css: t =>
'overflow: hidden;' +
`opacity: ${Math.min(t * 20, 1) * opacity};` +
`height: ${t * height}px;` +
`padding-top: ${t * padding_top}px;` +

Loading…
Cancel
Save