Skip to content

Commit 42bdeaa

Browse files
committed
basic support for style:display|transition
1 parent 272f7d4 commit 42bdeaa

File tree

5 files changed

+35
-10
lines changed

5 files changed

+35
-10
lines changed

packages/svelte/src/compiler/phases/2-analyze/visitors/StyleDirective.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,12 @@ import { mark_subtree_dynamic } from './shared/fragment.js';
1010
*/
1111
export function StyleDirective(node, context) {
1212
if (node.modifiers.length > 1 || (node.modifiers.length && node.modifiers[0] !== 'important')) {
13-
e.style_directive_invalid_modifier(node);
13+
if (
14+
node.name !== 'display' ||
15+
node.modifiers.findIndex((m) => m !== 'important' && m !== 'transition') >= 0
16+
) {
17+
e.style_directive_invalid_modifier(node);
18+
}
1419
}
1520

1621
mark_subtree_dynamic(context.path);

packages/svelte/src/compiler/phases/3-transform/client/visitors/RegularElement.js

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,11 @@ export function RegularElement(node, context) {
148148
break;
149149

150150
case 'StyleDirective':
151-
style_directives.push(attribute);
151+
if (attribute.name === 'display' && attribute.modifiers.includes('transition')) {
152+
style_display = attribute;
153+
} else {
154+
style_directives.push(attribute);
155+
}
152156
break;
153157

154158
case 'TransitionDirective':
@@ -167,6 +171,10 @@ export function RegularElement(node, context) {
167171
}
168172

169173
if (display_directive) {
174+
if (style_display !== null) {
175+
// TODO
176+
throw new Error('#display and style:display|transition forbidden');
177+
}
170178
// When we have a #display directive, the style:display directive must be handheld differently
171179
const index = style_directives.findIndex((d) => d.name === 'display');
172180
if (index >= 0) {
@@ -423,7 +431,11 @@ export function RegularElement(node, context) {
423431
}
424432
}
425433

426-
if (display_directive || node.fragment.nodes.some((node) => node.type === 'SnippetBlock')) {
434+
if (
435+
style_display ||
436+
display_directive ||
437+
node.fragment.nodes.some((node) => node.type === 'SnippetBlock')
438+
) {
427439
// Wrap children in `{...}` to avoid declaration conflicts
428440
const block = b.block([
429441
...child_state.init,
@@ -432,7 +444,7 @@ export function RegularElement(node, context) {
432444
...child_state.after_update,
433445
...element_state.after_update
434446
]);
435-
if (display_directive) {
447+
if (display_directive || style_display) {
436448
context.state.init.push(
437449
build_display_directive(node_id, display_directive, style_display, block, context)
438450
);

packages/svelte/src/compiler/phases/3-transform/client/visitors/shared/element.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -217,13 +217,15 @@ export function get_attribute_name(element, attribute) {
217217

218218
/**
219219
* @param {Identifier} node_id
220-
* @param {AST.DisplayDirective} display
220+
* @param {AST.DisplayDirective | null} display
221221
* @param {AST.StyleDirective | null} style
222222
* @param {BlockStatement} block
223223
* @param {ComponentContext} context
224224
*/
225225
export function build_display_directive(node_id, display, style, block, context) {
226-
const visibility = b.thunk(/** @type {Expression} */ (context.visit(display.expression)));
226+
const visibility = display
227+
? b.thunk(/** @type {Expression} */ (context.visit(display.expression)))
228+
: b.literal(null);
227229

228230
/** @type {Expression | undefined} */
229231
let value = undefined;

packages/svelte/src/compiler/types/template.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -240,7 +240,7 @@ export namespace AST {
240240
name: string;
241241
/** The 'y' in `style:x={y}` */
242242
value: true | ExpressionTag | Array<ExpressionTag | Text>;
243-
modifiers: Array<'important'>;
243+
modifiers: Array<'important' | 'transition'>;
244244
/** @internal */
245245
metadata: {
246246
expression: ExpressionMetadata;

packages/svelte/src/internal/client/dom/blocks/display.js

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { hydrate_next, hydrate_node, hydrating } from '../hydration.js';
77
* @param {HTMLElement} node
88
* @param {() => any} get_visibility
99
* @param {() => void} render_fn
10-
* @param {()=>string|null} [get_value]
10+
* @param {()=>string|boolean|null} [get_value]
1111
* @param {boolean} [default_important]
1212
* @returns {void}
1313
*/
@@ -41,8 +41,14 @@ export function display(node, get_visibility, render_fn, get_value, default_impo
4141

4242
const effect = block(render_fn);
4343
template_effect(() => {
44-
const visible = !!get_visibility();
45-
const value = visible ? get_value?.() : 'none';
44+
let display_value = get_value?.();
45+
if (display_value === true) {
46+
display_value = null;
47+
} else if (display_value === false) {
48+
display_value = 'none';
49+
}
50+
const visible = get_visibility !== null ? !!get_visibility() : display_value !== 'none';
51+
const value = visible ? display_value : 'none';
4652

4753
if (visible === prev_visible && value === prev_value) {
4854
return;

0 commit comments

Comments
 (0)