Skip to content
Draft
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
17 changes: 17 additions & 0 deletions .changeset/history-solid2-migration.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
---
"@solid-primitives/history": major
---

Migrate to Solid.js v2.0 (beta.10)

## Breaking Changes

**Peer dependency**: `solid-js@^2.0.0-beta.10` and `@solidjs/web@^2.0.0-beta.10` are now required.

### `@solid-primitives/history`

- `isServer` import moved from `solid-js/web` to `@solidjs/web`
- `batch()` removed from `undo()` and `redo()` — Solid 2.0 batches signal updates automatically; call `flush()` before reading `canUndo()`/`canRedo()` in tests or non-reactive (non-render) contexts
- Internal count signal uses `{ pureWrite: true }` for Solid 2.0 signal semantics
- `createMemo` initial state is now managed via an explicit `initialState` reference — Solid 2.0's `createMemo` passes `undefined` as `prev` on the first call, unlike Solid 1.x which passed the `init` argument
- Added SSR test coverage (`test/server.test.ts`)
14 changes: 14 additions & 0 deletions packages/history/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,19 @@
# @solid-primitives/history

## 0.3.0

### Minor Changes

- Migrate to Solid.js v2.0 (beta.10)

### Breaking Changes

- **Peer dependency**: `solid-js@^2.0.0-beta.10` and `@solidjs/web@^2.0.0-beta.10` are now required.
- `isServer` import moved from `solid-js/web` to `@solidjs/web`.
- `batch()` removed from `undo()` and `redo()` — Solid 2.0 batches signal updates automatically. Call `flush()` before reading `canUndo()`/`canRedo()` in tests or non-reactive contexts.
- Internal count signal uses `{ pureWrite: true }` for Solid 2.0 signal semantics.
- `createMemo` initial value handled via an explicit `initialState` reference to accommodate Solid 2.0's `undefined`-prev first-call behavior.

## 0.2.3

### Patch Changes
Expand Down
9 changes: 4 additions & 5 deletions packages/history/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -118,11 +118,10 @@ const history = createUndoHistory(() => {
};
});

// set them both at the same time, to only create one point in history
batch(() => {
setA(1);
setB(1);
});
// Note: updates are batched by default in Solid 2.0 — both
// changes create a single history entry
setA(1);
setB(1);
```

### Observing multiple independent sources
Expand Down
6 changes: 4 additions & 2 deletions packages/history/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -54,13 +54,15 @@
"test:ssr": "pnpm run vitest --mode ssr"
},
"peerDependencies": {
"solid-js": "^1.6.12"
"@solidjs/web": "^2.0.0-beta.10",
"solid-js": "^2.0.0-beta.10"
},
"dependencies": {
"@solid-primitives/utils": "workspace:^"
},
"devDependencies": {
"@solid-primitives/deep": "workspace:^",
"solid-js": "^1.9.7"
"@solidjs/web": "2.0.0-beta.10",
"solid-js": "2.0.0-beta.10"
}
}
52 changes: 28 additions & 24 deletions packages/history/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { type Many, createMicrotask, falseFn, noop } from "@solid-primitives/utils";
import { type Accessor, type Signal, batch, createMemo, createSignal, untrack } from "solid-js";
import { isServer } from "solid-js/web";
import { type Accessor, type Signal, createMemo, createSignal, untrack } from "solid-js";
import { isServer } from "@solidjs/web";

/**
* Configuration object for {@link createUndoHistory}.
Expand Down Expand Up @@ -43,6 +43,8 @@ export type UndoHistoryReturn = {
redo: VoidFunction;
};

type HistoryState = { count: Signal<number>; list: VoidFunction[][] };

/**
* Creates an undo history from a reactive source for going back and forth between state snapshots.
*
Expand Down Expand Up @@ -88,29 +90,31 @@ export function createUndoHistory(
const limit = options?.limit ?? 100,
sources = Array.isArray(source) ? source.map(s => createMemo(s)) : [source],
clearIgnore = createMicrotask(() => (ignoreNext = false)),
history = createMemo<{ count: Signal<number>; list: VoidFunction[][] }>(
p => {
// always track the sources
const setters: VoidFunction[] = [];
for (const s of sources) {
const setter = s();
if (setter) setters.push(setter);
}
// Initial state lives outside the memo so Solid 2.0's undefined-prev first-call is handled
initialCount = createSignal<number>(0, { pureWrite: true }),
initialState: HistoryState = { list: [], count: initialCount },
history = createMemo<HistoryState>(p => {
const prev = p ?? initialState;

if (ignoreNext || !setters.length) {
ignoreNext = false;
return p;
}
// always track the sources
const setters: VoidFunction[] = [];
for (const s of sources) {
const setter = s();
if (setter) setters.push(setter);
}

const count = untrack(p.count[0]),
newLength = p.list.length - count,
newHistory = p.list.slice(Math.max(0, newLength - limit), newLength);
newHistory.push(setters);
if (ignoreNext || !setters.length) {
ignoreNext = false;
return prev;
}

return { count: count ? createSignal(0) : p.count, list: newHistory };
},
{ list: [], count: createSignal(0) },
),
const count = untrack(prev.count[0]),
newLength = prev.list.length - count,
newHistory = prev.list.slice(Math.max(0, newLength - limit), newLength);
newHistory.push(setters);

return { count: count ? createSignal(0, { pureWrite: true }) : prev.count, list: newHistory };
}),
canUndo = createMemo(() => {
const h = history();
return h.list.length - h.count[0]() > 1;
Expand All @@ -134,10 +138,10 @@ export function createUndoHistory(
canUndo,
canRedo,
undo() {
untrack(() => canUndo() && batch(() => move(1)));
untrack(() => canUndo() && move(1));
},
redo() {
untrack(() => canRedo() && batch(() => move(-1)));
untrack(() => canRedo() && move(-1));
},
};
}
Loading