Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 0 additions & 43 deletions .changeset/animation-groups.md

This file was deleted.

13 changes: 0 additions & 13 deletions .changeset/deprecate-animation-helpers.md

This file was deleted.

9 changes: 0 additions & 9 deletions .changeset/fix-animation-serialization.md

This file was deleted.

10 changes: 10 additions & 0 deletions apps/docs/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
# docs

## 0.0.14

### Patch Changes

- Updated dependencies [b650fd8]
- Updated dependencies [12654be]
- Updated dependencies [0dd6440]
- @effex/dom@1.2.0
- @effex/router@1.2.2

## 0.0.13

### Patch Changes
Expand Down
2 changes: 1 addition & 1 deletion apps/docs/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "docs",
"version": "0.0.13",
"version": "0.0.14",
"private": true,
"type": "module",
"scripts": {
Expand Down
68 changes: 68 additions & 0 deletions packages/dom/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,73 @@
# @effex/dom

## 1.2.0

### Minor Changes

- b650fd8: Add animation groups — declarative sequencing across multiple animated blocks. Solves the "chained word-by-word intro" case where each word is its own `each` and word N should only start after word N-1 finishes.

```ts
import { $, Animation, collect, each, stagger } from "@effex/dom";

const App = () =>
Effect.gen(function* () {
const [greeting, name, tagline] = yield* Animation.sequence(3);
return $.div(
{},
collect(
each(greetingLetters, {
key: (l) => l.id,
render: (l) => $.span({}, $.of(l.char)),
animate: {
enter: "letter-in",
stagger: stagger(40),
group: greeting,
},
}),
each(nameLetters, {
key: (l) => l.id,
render: (l) => $.span({}, $.of(l.char)),
animate: { enter: "letter-in", stagger: stagger(40), group: name },
}),
each(taglineLetters, {
key: (l) => l.id,
render: (l) => $.span({}, $.of(l.char)),
animate: {
enter: "letter-in",
stagger: stagger(40),
group: tagline,
},
}),
),
);
});
```

New API:
- `Animation.group()` — creates a group with a gate (unresolved) and a completion signal.
- `Animation.sequence(count)` — returns `count` groups wired end-to-end: group 0's gate is open immediately, group N's gate opens when group N-1's registered animations all complete.
- `Animation.parallel(count)` — returns `count` groups with all gates open (useful nested inside `sequence` for concurrent segments in a follow-up release).
- `animate.group: AnimationGroup` — new option on any animated control (`each`, `when`, `match`, ...). The animation registers with the group synchronously, awaits the gate before starting, and signals completion when finished.

Groups finalize when their pending count returns to zero for the first time after having been non-zero. Late registrations that arrive after finalization run immediately (gate is already open) — intended semantics for one-shot intros where post-sequence additions behave like ordinary animations.

### Patch Changes

- 12654be: Deprecate five under-used animation helpers with `@deprecated` JSDoc tags. All continue to work — they'll be removed in a future major.
- `staggerEased` — compose your own: `(index, total) => easingFn(index / (total - 1)) * totalDurationMs`
- `delay` — use `Effect.delay(effect, ms)` directly
- `sequence` — use `Effect.all([...], { concurrency: 1 })` directly
- `parallel` — use `Effect.all([...], { concurrency: "unbounded" })` directly
- `calculateStaggerDelay` — was only ever an internal helper; not re-exported by anything downstream

These wrapped effect combinators without adding real value beyond a slightly shorter name; the framework should be a thin layer over Effect rather than shadow its stdlib.

- 0dd6440: Fix inline animation serialization in `addSlot` / `removeSlot`. Previously each enter/exit animation was awaited via `yield*`, which serialized the `reconcile` sync loop — for a list of `[a, b, c]` added at once, item `b`'s animation would only start after item `a`'s finished. Made `stagger` configs effectively double-counted (each addSlot's stagger delay applied _after_ the previous animation completed rather than concurrently).

Now enter animations are forked into the slot's scope so multiple slots animate concurrently, and exit animations run in a fiber attached to the parent scope so `removeSlot` returns immediately (letting the reconcile loop continue) while the exit still plays before the DOM node is removed. If a slot is removed mid-enter, closing the slot scope interrupts the enter animation before exit starts. This applies to `ClientControlCtx` and both factories in `HydrationControlCtx`.

`@effex/router` will receive an automatic patch via `updateInternalDependencies` since it depends on `@effex/dom` as a workspace dependency.

## 1.1.1

### Patch Changes
Expand Down
2 changes: 1 addition & 1 deletion packages/dom/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@effex/dom",
"version": "1.1.1",
"version": "1.2.0",
"description": "DOM rendering for Effex - a reactive UI framework built on Effect.ts",
"type": "module",
"license": "MIT",
Expand Down
9 changes: 9 additions & 0 deletions packages/router/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
# @effex/router

## 1.2.2

### Patch Changes

- Updated dependencies [b650fd8]
- Updated dependencies [12654be]
- Updated dependencies [0dd6440]
- @effex/dom@1.2.0

## 1.2.1

### Patch Changes
Expand Down
2 changes: 1 addition & 1 deletion packages/router/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@effex/router",
"version": "1.2.1",
"version": "1.2.2",
"description": "Router for Effex applications",
"type": "module",
"license": "MIT",
Expand Down