Skip to content

Commit c4c4736

Browse files
committed
PR fixes
1 parent 5c01d56 commit c4c4736

19 files changed

Lines changed: 210 additions & 89 deletions

File tree

CHANGELOG.md

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,14 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
1010

1111
## @wix/splittext
1212

13+
### [0.2.0] - unreleased
14+
15+
#### Added
16+
17+
- `@wix/splittext/plugin` entry point: `splitTextPlugin` (runtime adapter for `Interact.use('splitText', …)`) and its build-time counterpart `splitTextStyle` for `generate()`'s `plugins` option (#275)
18+
- `SplitTextPluginConfig` type — `{ container, hideUntilReady?, ...SplitTextOptions }` — for declaration-merging `$splitText` into `InteractPluginConfigMap` (#275)
19+
- `hideUntilReady` opts into SSR FOUC prevention: `splitTextStyle` hides the container until the runtime split sets `data-splittext-ready` (#275)
20+
1321
### [0.1.2] - 2026-07-14
1422

1523
#### Added
@@ -26,6 +34,12 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
2634

2735
## @wix/interact-validate
2836

37+
### [0.2.0] - unreleased
38+
39+
#### Added
40+
41+
- Plugin fields: `$`-prefixed keys on interactions and effects are accepted with opaque values (validate never inspects plugin config), while every other unknown key is still reported as `SCHEMA_UNRECOGNIZED_KEYS` so typos are still caught (#275)
42+
2943
### [0.1.1] - 2026-07-14
3044

3145
#### Added
@@ -53,6 +67,19 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
5367

5468
## @wix/interact
5569

70+
### [2.6.0] - unreleased
71+
72+
#### Added
73+
74+
- Generic plugin bridge: `Interact.use(name, plugin)` registers a plugin, and a `$<name>` field on an interaction or effect (e.g. `$splitText`) routes its value to it at connect time, before target resolution. Plugin values are opaque to Interact; a returned cleanup runs on disconnect/teardown (#275)
75+
- `generate()` accepts a `plugins` option — a map of plugin name → build-time style generator — so plugins can emit SSR CSS (e.g. FOUC prevention for un-split text) without Interact inspecting their config (#275)
76+
- Plugin types: `InteractPlugin`, `InteractPluginContext`, `InteractPluginCleanup`, `InteractPluginConfigMap` (augment to type `$<name>` fields), `InteractPluginStyleContext`, `InteractPluginStyleGenerator`, `InteractPluginStyles`, and `PluginFields` (#275)
77+
- Agent rules (`rules/plugins.md`) and docs (`docs/guides/plugins.md`) for registering plugins and their SSR styling (#275)
78+
79+
#### Changed
80+
81+
- `generate(config, options?)`: the second argument now accepts an options bag — `{ useFirstChild?, plugins? }` — exported as the `GenerateOptions` type. Passing a bare boolean still works and is treated as `useFirstChild`, so `generate(config, true)` is unchanged (#275)
82+
5683
### [2.5.4] - 2026-07-16
5784

5885
#### Fixed

apps/demo/test/splitText.integration.spec.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ describe('splitText through the Interact plugin bridge (real @wix/splittext)', (
7676
};
7777

7878
// SSR: the container is hidden until the split marks it ready.
79-
const css = generate(config, true, { splitText: splitTextStyle });
79+
const css = generate(config, { plugins: { splitText: splitTextStyle } });
8080
expect(css).toContain(
8181
'[data-interact-key="hero"] .title:not([data-splittext-ready]) {\nvisibility: hidden;\n}',
8282
);
@@ -114,7 +114,7 @@ describe('splitText through the Interact plugin bridge (real @wix/splittext)', (
114114
],
115115
};
116116

117-
const css = generate(config, true, { splitText: splitTextStyle });
117+
const css = generate(config, { plugins: { splitText: splitTextStyle } });
118118
expect(css).not.toContain('data-splittext-ready');
119119
});
120120
});

packages/interact/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -430,7 +430,7 @@ Each example is a complete `InteractConfig` — pass it to `Interact.create(conf
430430
- **Hit-area shift on `hover` / `pointerMove`** — Animating size/position of the hovered element shifts the hit area and causes jitter. Instead, animate a child via `selector` or a different `key`.
431431
- **`registerEffects()` must run before `Interact.create()`/`generate()`** when using `namedEffect`.
432432
- **FOUC prevention** — requires injecting the output of `generate(config)` into `<head>`.
433-
- **`generate(config, useFirstChild)`** — Pass `true` for `<interact-element>` (web), `false` for vanilla and React `<Interaction>`.
433+
- **`generate(config, options?)`** `options` is `{ useFirstChild?, plugins? }`, or a bare boolean used as `useFirstChild`. Pass `true` for `<interact-element>` (web), `false` for vanilla and React `<Interaction>`.
434434
- **`<interact-element>` must wrap exactly one child** — the library targets `:first-child` by default.
435435

436436
## AI & Agent Support

packages/interact/docs/api/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ Complete reference documentation for all public APIs in `@wix/interact`.
1818
- [Error handling](functions.md#error-handling) and [performance considerations](functions.md#performance-considerations)
1919
- [**remove(path)**](functions.md#remove) - Remove interactions from an element
2020
- [Cleanup behavior](functions.md#behavior-details) and [advanced usage](functions.md#advanced-usage)
21-
- [**generate(config, useFirstChild?)**](functions.md#generate) - Generate complete CSS for all animations, transitions, scroll-driven effects, and FOUC prevention
21+
- [**generate(config, options?)**](functions.md#generate) - Generate complete CSS for all animations, transitions, scroll-driven effects, and FOUC prevention
2222
- [What it generates](functions.md#what-it-generates), [benefits](functions.md#benefits), and [use cases](functions.md#use-cases)
2323
- [FOUC prevention](functions.md#fouc-prevention-viewenter), [scroll-driven CSS](functions.md#scroll-driven-css-viewprogress), and [SSR](functions.md#server-side-rendering-ssr)
2424
- [**addListItems(root, key, listContainer, elements)**](functions.md#addlistitems) - Add interactions to new list items

packages/interact/docs/api/functions.md

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -196,27 +196,29 @@ console.log('Interactions removed for hero');
196196

197197
---
198198

199-
## `generate(config, useFirstChild?, plugins?)`
199+
## `generate(config, options?)`
200200

201201
Generates a complete CSS string from an `InteractConfig`. The output includes `@keyframes`, animation and transition custom properties, view-timeline declarations, state-selector rules, coordinated-list aggregation, and FOUC-prevention initial rules — everything the browser needs to run the configured animations and transitions natively, without waiting for JavaScript.
202202

203203
### Signature
204204

205205
```typescript
206-
function generate(
207-
config: InteractConfig,
208-
useFirstChild?: boolean,
209-
plugins?: InteractPluginStyles,
210-
): string;
206+
function generate(config: InteractConfig, options?: boolean | GenerateOptions): string;
207+
208+
type GenerateOptions = {
209+
useFirstChild?: boolean;
210+
plugins?: InteractPluginStyles;
211+
};
211212
```
212213

213214
### Parameters
214215

215216
**`config: InteractConfig`** - The full interaction configuration. Every interaction in the config is processed — not just `viewEnter`.
216217

217-
**`useFirstChild?: boolean`** - When `true` (the default), generated selectors target the first child of each keyed element (e.g. `[data-interact-key="hero"] > :first-child`). This is the correct mode for `<interact-element>` custom elements. Pass `false` when the keyed element itself is the animation target (vanilla JS or React `<Interaction>`).
218+
**`options?: boolean | GenerateOptions`** - Either an options object or — for backwards compatibility — a bare boolean used as `useFirstChild` (`generate(config, false)``generate(config, { useFirstChild: false })`).
218219

219-
**`plugins?: InteractPluginStyles`** - Optional map of plugin name → SSR style generator. For every `$<name>` field in the config, the matching generator is called with the field's (opaque) value and a context, and its returned CSS data is appended to the output. Used to emit build-time styling on a plugin's behalf — e.g. hiding pre-split text for FOUC prevention. Like `create()`/`use()`, `generate()` never inspects the field value. See [Plugins → SSR styling](../guides/plugins.md#ssr-styling-foouc-prevention).
220+
- **`useFirstChild?: boolean`** - When `true` (the default), generated selectors target the first child of each keyed element (e.g. `[data-interact-key="hero"] > :first-child`). This is the correct mode for `<interact-element>` custom elements. Pass `false` when the keyed element itself is the animation target (vanilla JS or React `<Interaction>`).
221+
- **`plugins?: InteractPluginStyles`** - Optional map of plugin name → SSR style generator. For every `$<name>` field in the config, the matching generator is called with the field's (opaque) value and a context, and its returned CSS data is appended to the output. Used to emit build-time styling on a plugin's behalf — e.g. hiding pre-split text for FOUC prevention. Like `create()`/`use()`, `generate()` never inspects the field value. See [Plugins → SSR styling](../guides/plugins.md#ssr-styling-foouc-prevention).
220222

221223
### Returns
222224

packages/interact/docs/guides/plugins.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -141,9 +141,9 @@ A `$`-prefixed field can also sit on an individual effect, using that effect's *
141141

142142
## SSR styling (FOUC prevention)
143143

144-
A plugin often needs initial CSS _before_ it runs — e.g. hiding the un-split text so an entrance animation doesn't flash the raw content. That's a build-time concern, so it lives in [`generate()`](../api/functions.md#generateconfig-usefirstchild-plugins), not in the runtime `use()` callback.
144+
A plugin often needs initial CSS _before_ it runs — e.g. hiding the un-split text so an entrance animation doesn't flash the raw content. That's a build-time concern, so it lives in [`generate()`](../api/functions.md#generateconfig-options), not in the runtime `use()` callback.
145145

146-
Pass a **second, separate callback per plugin** as `generate()`'s third argument. For every `$<name>` field, `generate()` calls the matching generator with the field's (opaque) value and a context, and appends the returned CSS. Like `create()`, `generate()` never looks inside the value — the plugin decides what to emit (and defines its own selectors under `selectorSuffix`).
146+
Pass a **second, separate callback per plugin** in the `plugins` option of `generate()`'s options bag — `generate(config, { useFirstChild, plugins })`. For every `$<name>` field, `generate()` calls the matching generator with the field's (opaque) value and a context, and appends the returned CSS. Like `create()`, `generate()` never looks inside the value — the plugin decides what to emit (and defines its own selectors under `selectorSuffix`).
147147

148148
```ts
149149
type InteractPluginStyleGenerator = (
@@ -179,7 +179,7 @@ const config = {
179179
};
180180

181181
// Embed this CSS in <head> at build/SSR time.
182-
const css = generate(config, true, { splitText: splitTextStyle });
182+
const css = generate(config, { plugins: { splitText: splitTextStyle } });
183183
// → `[data-interact-key="hero"] .title:not([data-splittext-ready]) { visibility: hidden; }`
184184
```
185185

packages/interact/rules/full-lean.md

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -716,7 +716,7 @@ Interact can route config to external plugins registered with `Interact.use(name
716716
- A plugin may return a cleanup function; Interact runs it on disconnect/teardown.
717717
- A `$<name>` field with no registered plugin is ignored.
718718
- Plugin fields MUST be `$`-prefixed — a non-prefixed unknown key on an interaction/effect is rejected by `@wix/interact-validate`.
719-
- **SSR styling:** for FOUC prevention (e.g. hiding un-split text before an entrance animation), pass a **separate** per-plugin callback as `generate()`'s third arg: `generate(config, true, { myPlugin: (value, context) => { declarations, selectorSuffix }[] })`. `generate()` does not inspect the value; the callback returns CSS rule(s) data and scopes them under the base selector (`[data-interact-key="<key>"]`). It is NOT the `use()` callback. If the plugin package ships a generator (e.g. `splitTextStyle` from `@wix/splittext/plugin`), pass that instead of writing one.
719+
- **SSR styling:** for FOUC prevention (e.g. hiding un-split text before an entrance animation), pass a **separate** per-plugin callback in the `plugins` option of `generate()`'s options bag: `generate(config, { useFirstChild: true, plugins: { myPlugin: (value, context) => { declarations, selectorSuffix }[] } })`. `generate()` does not inspect the value; the callback returns CSS rule(s) data and scopes them under the base selector (`[data-interact-key="<key>"]`). It is NOT the `use()` callback. If the plugin package ships a generator (e.g. `splitTextStyle` from `@wix/splittext/plugin`), pass that instead of writing one.
720720
721721
**Example — split text, then stagger the generated char spans.** Use the adapter shipped from `@wix/splittext/plugin` (`splitTextPlugin` + its SSR counterpart `splitTextStyle`); do NOT hand-roll it:
722722
@@ -737,7 +737,7 @@ const config = {
737737
],
738738
};
739739
740-
const css = generate(config, /* useFirstChild */ true, { splitText: splitTextStyle });
740+
const css = generate(config, { useFirstChild: true, plugins: { splitText: splitTextStyle } });
741741
// Embed css in HTML — see CSS Generation & FOUC Prevention
742742
743743
Interact.use('splitText', splitTextPlugin);
@@ -752,16 +752,16 @@ Default split wrapper classes: `.split-c` (chars), `.split-w` (words), `.split-l
752752
753753
## Static API
754754
755-
| Method / Property | Description |
756-
| :------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------- |
757-
| `generate(config, useFirstChild?, plugins?)` | Produce complete CSS for all interactions. Call at build/generation time; embed in HTML. `plugins` = per-plugin SSR style generators (see [Plugins](#plugins)). |
758-
| `Interact.create(config)` | Initialize with a config. Returns the instance. Store the instance to manage its lifecycle. |
759-
| `Interact.registerEffects(presets)` | Register named effect presets. MUST be called before `generate()` and `create`. |
760-
| `Interact.destroy()` | Tear down all instances. Call on unmount or route change to prevent memory leaks. |
761-
| `Interact.forceReducedMotion` | `boolean` (default: `false`) — force reduced-motion behavior regardless of OS setting. |
762-
| `Interact.allowA11yTriggers` | `boolean` (default: `true`) — enable accessibility trigger variants (`interest`, `activate`). |
763-
| `Interact.setup(options)` | Configure global options for scroll, pointer, and viewEnter systems. Call before `create`. See options below. |
764-
| `Interact.use(name, plugin)` | Register an external plugin by name (see [Plugins](#plugins)). Call before `create`. |
755+
| Method / Property | Description |
756+
| :---------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
757+
| `generate(config, options?)` | Produce complete CSS for all interactions. Call at build/generation time; embed in HTML. `options` = `{ useFirstChild?, plugins? }`, or a bare boolean for legacy `useFirstChild`. `plugins` = per-plugin SSR style generators (see [Plugins](#plugins)). |
758+
| `Interact.create(config)` | Initialize with a config. Returns the instance. Store the instance to manage its lifecycle. |
759+
| `Interact.registerEffects(presets)` | Register named effect presets. MUST be called before `generate()` and `create`. |
760+
| `Interact.destroy()` | Tear down all instances. Call on unmount or route change to prevent memory leaks. |
761+
| `Interact.forceReducedMotion` | `boolean` (default: `false`) — force reduced-motion behavior regardless of OS setting. |
762+
| `Interact.allowA11yTriggers` | `boolean` (default: `true`) — enable accessibility trigger variants (`interest`, `activate`). |
763+
| `Interact.setup(options)` | Configure global options for scroll, pointer, and viewEnter systems. Call before `create`. See options below. |
764+
| `Interact.use(name, plugin)` | Register an external plugin by name (see [Plugins](#plugins)). Call before `create`. |
765765
766766
**`Interact.setup(options)`** — optional configuration object:
767767

0 commit comments

Comments
 (0)