From fcd3ca2ba1b99b67e0feec667636de0656555996 Mon Sep 17 00:00:00 2001 From: ameerf-wix Date: Thu, 25 Jun 2026 14:08:12 +0300 Subject: [PATCH 1/4] fixing entrance SSR - enter='done' --- packages/interact/src/core/cssUtils.ts | 2 +- packages/interact/test/cssUtils.spec.ts | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/interact/src/core/cssUtils.ts b/packages/interact/src/core/cssUtils.ts index 889820db..7833641c 100644 --- a/packages/interact/src/core/cssUtils.ts +++ b/packages/interact/src/core/cssUtils.ts @@ -124,7 +124,7 @@ export function CSSRuleToString(rule: CSSRuleData): string { } if (addInitialSelector) { - selector = `${selector}:not([data-interact-enter])`; + selector = `${selector}:not([data-interact-enter="done"])`; } // maybe nesting is simpler? - diff --git a/packages/interact/test/cssUtils.spec.ts b/packages/interact/test/cssUtils.spec.ts index a270e186..6c678554 100644 --- a/packages/interact/test/cssUtils.spec.ts +++ b/packages/interact/test/cssUtils.spec.ts @@ -207,13 +207,13 @@ describe('CSSRuleToString', () => { expect(CSSRuleToString(rule)).toEqual(expected); }); - it('should add :not([data-interact-enter]) when addInitialSelector is true', () => { + it('should add :not([data-interact-enter="done"]) when addInitialSelector is true', () => { const rule: CSSRuleData = { key: 'my-el', addInitialSelector: true, declarations: [{ name: 'opacity', value: '0' }], }; - const expected = '[data-interact-key="my-el"]:not([data-interact-enter]) {\nopacity: 0;\n}'; + const expected = '[data-interact-key="my-el"]:not([data-interact-enter="done"]) {\nopacity: 0;\n}'; expect(CSSRuleToString(rule)).toEqual(expected); }); @@ -262,7 +262,7 @@ describe('CSSRuleToString', () => { ], }; const expected = - '@media (min-width: 1024px) {\n[data-interact-key="my-el"]:is(:state(hover), :--hover, [data-interact-effect~="hover"]) .child:not([data-interact-enter]) {\nopacity: 1;\ncolor: blue;\n}\n}'; + '@media (min-width: 1024px) {\n[data-interact-key="my-el"]:is(:state(hover), :--hover, [data-interact-effect~="hover"]) .child:not([data-interact-enter="done"]) {\nopacity: 1;\ncolor: blue;\n}\n}'; expect(CSSRuleToString(rule)).toEqual(expected); }); }); From c84768d118f13c7d2e58628b5c47f52ddeddd4df Mon Sep 17 00:00:00 2001 From: ameerf-wix Date: Thu, 25 Jun 2026 14:15:08 +0300 Subject: [PATCH 2/4] format --- packages/interact/test/cssUtils.spec.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/interact/test/cssUtils.spec.ts b/packages/interact/test/cssUtils.spec.ts index 6c678554..6bec75f2 100644 --- a/packages/interact/test/cssUtils.spec.ts +++ b/packages/interact/test/cssUtils.spec.ts @@ -213,7 +213,8 @@ describe('CSSRuleToString', () => { addInitialSelector: true, declarations: [{ name: 'opacity', value: '0' }], }; - const expected = '[data-interact-key="my-el"]:not([data-interact-enter="done"]) {\nopacity: 0;\n}'; + const expected = + '[data-interact-key="my-el"]:not([data-interact-enter="done"]) {\nopacity: 0;\n}'; expect(CSSRuleToString(rule)).toEqual(expected); }); From f8ab0ebb5e2c81241047dd33e7963865a1fb50f0 Mon Sep 17 00:00:00 2001 From: ameerf-wix Date: Thu, 25 Jun 2026 14:44:03 +0300 Subject: [PATCH 3/4] rule separation --- packages/interact/src/core/css.ts | 12 ++++++++++-- packages/interact/src/core/cssUtils.ts | 15 +++++++++++---- packages/interact/src/types/css.ts | 2 +- packages/interact/test/css.spec.ts | 23 ++++++++++++++++------- packages/interact/test/cssUtils.spec.ts | 6 +++--- 5 files changed, 41 insertions(+), 17 deletions(-) diff --git a/packages/interact/src/core/css.ts b/packages/interact/src/core/css.ts index 7890157f..aba27765 100644 --- a/packages/interact/src/core/css.ts +++ b/packages/interact/src/core/css.ts @@ -250,8 +250,16 @@ function effectToCSS( media, selectorCondition, childSelector, - declarations: animationDeclarations.concat(DEFAULT_INITIAL), - addInitialSelector: true, + declarations: DEFAULT_INITIAL, + dataInteractEnterSelector: ':not([data-interact-enter])', + }); + rules.push({ + key, + media, + selectorCondition, + childSelector, + declarations: animationDeclarations, + dataInteractEnterSelector: ':not([data-interact-enter="done"])', }); } else { // declare animation and composition custom properties diff --git a/packages/interact/src/core/cssUtils.ts b/packages/interact/src/core/cssUtils.ts index 7833641c..93bbf235 100644 --- a/packages/interact/src/core/cssUtils.ts +++ b/packages/interact/src/core/cssUtils.ts @@ -102,8 +102,15 @@ export function keyframesToCSS(name: string, keyframes: Keyframe[]): string { } export function CSSRuleToString(rule: CSSRuleData): string { - const { key, childSelector, declarations, media, states, selectorCondition, addInitialSelector } = - rule; + const { + key, + childSelector, + declarations, + media, + states, + selectorCondition, + dataInteractEnterSelector, + } = rule; if (!declarations.length) { return ''; } @@ -123,8 +130,8 @@ export function CSSRuleToString(rule: CSSRuleData): string { selector = `${selector} ${childSelector}`; } - if (addInitialSelector) { - selector = `${selector}:not([data-interact-enter="done"])`; + if (dataInteractEnterSelector) { + selector = `${selector}${dataInteractEnterSelector}`; } // maybe nesting is simpler? - diff --git a/packages/interact/src/types/css.ts b/packages/interact/src/types/css.ts index c1160b4b..433dd02d 100644 --- a/packages/interact/src/types/css.ts +++ b/packages/interact/src/types/css.ts @@ -23,5 +23,5 @@ export type CSSRuleData = { media?: string; states?: string[]; selectorCondition?: string; - addInitialSelector?: boolean; + dataInteractEnterSelector?: string; }; diff --git a/packages/interact/test/css.spec.ts b/packages/interact/test/css.spec.ts index 24cef88a..c89d1a83 100644 --- a/packages/interact/test/css.spec.ts +++ b/packages/interact/test/css.spec.ts @@ -435,7 +435,9 @@ describe('css._generate', () => { const { cssRules } = _generate(config); - const initialRule = cssRules.find((r) => r.addInitialSelector)!; + const initialRule = cssRules.find( + (r) => r.dataInteractEnterSelector === ':not([data-interact-enter])', + )!; expect(initialRule).toBeDefined(); DEFAULT_INITIAL.forEach(({ name, value }) => { @@ -444,7 +446,12 @@ describe('css._generate', () => { expect(decl!.value).toBe(value); }); - const animDeclOnInitial = findDecl(initialRule.declarations, (d) => isAnimationProp(d.name)); + const animationRule = cssRules.find( + (r) => r.dataInteractEnterSelector === ':not([data-interact-enter="done"])', + )!; + const animDeclOnInitial = findDecl(animationRule.declarations, (d) => + isAnimationProp(d.name), + ); expect(animDeclOnInitial).toBeDefined(); expect(animDeclOnInitial!.value).toContain('myAnim'); }); @@ -472,7 +479,7 @@ describe('css._generate', () => { const { cssRules } = _generate(config); - expect(cssRules.every((r) => !r.addInitialSelector)).toBe(true); + expect(cssRules.every((r) => !r.dataInteractEnterSelector)).toBe(true); const effectRule = cssRules.find((r) => r.declarations.some((d) => isAnimationProp(d.name)))!; expect(effectRule).toBeDefined(); @@ -492,7 +499,7 @@ describe('css._generate', () => { const { cssRules } = _generate(config); - expect(cssRules.every((r) => !r.addInitialSelector)).toBe(true); + expect(cssRules.every((r) => !r.dataInteractEnterSelector)).toBe(true); }); }); @@ -654,7 +661,7 @@ describe('css._generate', () => { const { cssRules } = _generate(config); - expect(cssRules.every((r) => !r.addInitialSelector)).toBe(true); + expect(cssRules.every((r) => !r.dataInteractEnterSelector)).toBe(true); }); it('should emit auto duration in animation shorthand for viewProgress (SSR-safe)', () => { @@ -796,7 +803,9 @@ describe('css._generate', () => { const { cssRules } = _generate(config); - const initialRule = cssRules.find((r) => r.addInitialSelector)!; + const initialRule = cssRules.find( + (r) => r.dataInteractEnterSelector === ':not([data-interact-enter])="done"', + )!; expect(initialRule).toBeDefined(); const timelineDecl = findDecl(initialRule.declarations, (d) => isTimelineProp(d.name)); @@ -1150,7 +1159,7 @@ describe('css._generate', () => { }; const { cssRules } = _generate(config); - const initialRule = cssRules.find((r) => r.addInitialSelector)!; + const initialRule = cssRules.find((r) => r.dataInteractEnterSelector)!; expect(initialRule).toBeDefined(); expect(initialRule.media).toContain('min-width: 1024px'); diff --git a/packages/interact/test/cssUtils.spec.ts b/packages/interact/test/cssUtils.spec.ts index 6bec75f2..09349e9e 100644 --- a/packages/interact/test/cssUtils.spec.ts +++ b/packages/interact/test/cssUtils.spec.ts @@ -207,10 +207,10 @@ describe('CSSRuleToString', () => { expect(CSSRuleToString(rule)).toEqual(expected); }); - it('should add :not([data-interact-enter="done"]) when addInitialSelector is true', () => { + it('should dataInteractEnterSelector when provided', () => { const rule: CSSRuleData = { key: 'my-el', - addInitialSelector: true, + dataInteractEnterSelector: ':not([data-interact-enter="done"])', declarations: [{ name: 'opacity', value: '0' }], }; const expected = @@ -254,7 +254,7 @@ describe('CSSRuleToString', () => { const rule: CSSRuleData = { key: 'my-el', childSelector: '.child', - addInitialSelector: true, + dataInteractEnterSelector: ':not([data-interact-enter="done"])', states: ['hover'], media: '(min-width: 1024px)', declarations: [ From 8829c93f0646744969fca12c82312a0b9ed167dc Mon Sep 17 00:00:00 2001 From: ameerf-wix Date: Thu, 25 Jun 2026 14:49:05 +0300 Subject: [PATCH 4/4] oopsy --- packages/interact/test/css.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/interact/test/css.spec.ts b/packages/interact/test/css.spec.ts index c89d1a83..88c9ac3d 100644 --- a/packages/interact/test/css.spec.ts +++ b/packages/interact/test/css.spec.ts @@ -804,7 +804,7 @@ describe('css._generate', () => { const { cssRules } = _generate(config); const initialRule = cssRules.find( - (r) => r.dataInteractEnterSelector === ':not([data-interact-enter])="done"', + (r) => r.dataInteractEnterSelector === ':not([data-interact-enter="done"])', )!; expect(initialRule).toBeDefined();