basic support for style:display|transition

pull/14795/head
adiguba 2 years ago
parent 272f7d4dfc
commit 42bdeaaaa9

@ -10,7 +10,12 @@ import { mark_subtree_dynamic } from './shared/fragment.js';
*/
export function StyleDirective(node, context) {
if (node.modifiers.length > 1 || (node.modifiers.length && node.modifiers[0] !== 'important')) {
e.style_directive_invalid_modifier(node);
if (
node.name !== 'display' ||
node.modifiers.findIndex((m) => m !== 'important' && m !== 'transition') >= 0
) {
e.style_directive_invalid_modifier(node);
}
}
mark_subtree_dynamic(context.path);

@ -148,7 +148,11 @@ export function RegularElement(node, context) {
break;
case 'StyleDirective':
style_directives.push(attribute);
if (attribute.name === 'display' && attribute.modifiers.includes('transition')) {
style_display = attribute;
} else {
style_directives.push(attribute);
}
break;
case 'TransitionDirective':
@ -167,6 +171,10 @@ export function RegularElement(node, context) {
}
if (display_directive) {
if (style_display !== null) {
// TODO
throw new Error('#display and style:display|transition forbidden');
}
// When we have a #display directive, the style:display directive must be handheld differently
const index = style_directives.findIndex((d) => d.name === 'display');
if (index >= 0) {
@ -423,7 +431,11 @@ export function RegularElement(node, context) {
}
}
if (display_directive || node.fragment.nodes.some((node) => node.type === 'SnippetBlock')) {
if (
style_display ||
display_directive ||
node.fragment.nodes.some((node) => node.type === 'SnippetBlock')
) {
// Wrap children in `{...}` to avoid declaration conflicts
const block = b.block([
...child_state.init,
@ -432,7 +444,7 @@ export function RegularElement(node, context) {
...child_state.after_update,
...element_state.after_update
]);
if (display_directive) {
if (display_directive || style_display) {
context.state.init.push(
build_display_directive(node_id, display_directive, style_display, block, context)
);

@ -217,13 +217,15 @@ export function get_attribute_name(element, attribute) {
/**
* @param {Identifier} node_id
* @param {AST.DisplayDirective} display
* @param {AST.DisplayDirective | null} display
* @param {AST.StyleDirective | null} style
* @param {BlockStatement} block
* @param {ComponentContext} context
*/
export function build_display_directive(node_id, display, style, block, context) {
const visibility = b.thunk(/** @type {Expression} */ (context.visit(display.expression)));
const visibility = display
? b.thunk(/** @type {Expression} */ (context.visit(display.expression)))
: b.literal(null);
/** @type {Expression | undefined} */
let value = undefined;

@ -240,7 +240,7 @@ export namespace AST {
name: string;
/** The 'y' in `style:x={y}` */
value: true | ExpressionTag | Array<ExpressionTag | Text>;
modifiers: Array<'important'>;
modifiers: Array<'important' | 'transition'>;
/** @internal */
metadata: {
expression: ExpressionMetadata;

@ -7,7 +7,7 @@ import { hydrate_next, hydrate_node, hydrating } from '../hydration.js';
* @param {HTMLElement} node
* @param {() => any} get_visibility
* @param {() => void} render_fn
* @param {()=>string|null} [get_value]
* @param {()=>string|boolean|null} [get_value]
* @param {boolean} [default_important]
* @returns {void}
*/
@ -41,8 +41,14 @@ export function display(node, get_visibility, render_fn, get_value, default_impo
const effect = block(render_fn);
template_effect(() => {
const visible = !!get_visibility();
const value = visible ? get_value?.() : 'none';
let display_value = get_value?.();
if (display_value === true) {
display_value = null;
} else if (display_value === false) {
display_value = 'none';
}
const visible = get_visibility !== null ? !!get_visibility() : display_value !== 'none';
const value = visible ? display_value : 'none';
if (visible === prev_visible && value === prev_value) {
return;

Loading…
Cancel
Save