Skip to content

Commit

Permalink
feat: add onChange handler to proxyWithHistory
Browse files Browse the repository at this point in the history
  • Loading branch information
lwhiteley committed Jan 13, 2024
1 parent 3f12f1b commit e8f5100
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 20 deletions.
31 changes: 19 additions & 12 deletions packages/history-utility/docs/modules.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@

#### Defined in

[packages/history-utility/src/history-utility.ts:26](https://github.com/valtiojs/valtio-history/blob/43e2fcd/packages/history-utility/src/history-utility.ts#L26)
[packages/history-utility/src/history-utility.ts:26](https://github.com/valtiojs/valtio-history/blob/3f12f1b/packages/history-utility/src/history-utility.ts#L26)

---

Expand All @@ -60,23 +60,30 @@

#### Defined in

[packages/history-utility/src/history-utility.ts:10](https://github.com/valtiojs/valtio-history/blob/43e2fcd/packages/history-utility/src/history-utility.ts#L10)
[packages/history-utility/src/history-utility.ts:10](https://github.com/valtiojs/valtio-history/blob/3f12f1b/packages/history-utility/src/history-utility.ts#L10)

---

### HistoryOptions

Ƭ **HistoryOptions**: `Object`
Ƭ **HistoryOptions**\<`T`\>: `Object`

#### Type parameters

| Name |
| :--- |
| `T` |

#### Type declaration

| Name | Type | Description |
| :--------------- | :-------- | :---------------------------------------------------------------- |
| `skipSubscribe?` | `boolean` | determines if the internal subscribe behaviour should be skipped. |
| Name | Type | Description |
| :--------------- | :-------------------------------------------------------------------------------- | :----------------------------------------------------------------- |
| `skipSubscribe?` | `boolean` | determines if the internal subscribe behaviour should be skipped. |
| `onChange?` | (`value`: `T`, `data`: \{ `historySaved`: `boolean` ; `ops`: `any`[] }) => `void` | callback that triggers any time a change happens wihin the utility |

#### Defined in

[packages/history-utility/src/history-utility.ts:43](https://github.com/valtiojs/valtio-history/blob/43e2fcd/packages/history-utility/src/history-utility.ts#L43)
[packages/history-utility/src/history-utility.ts:43](https://github.com/valtiojs/valtio-history/blob/3f12f1b/packages/history-utility/src/history-utility.ts#L43)

## Functions

Expand Down Expand Up @@ -114,10 +121,10 @@ Notes: <br>

#### Parameters

| Name | Type | Description |
| :------------- | :--------------------------------------------------------- | :--------------------------------------------- |
| `initialValue` | `V` | any value to be tracked |
| `options?` | `boolean` \| [`HistoryOptions`](modules.md#historyoptions) | use to configure the proxyWithHistory utility. |
| Name | Type | Description |
| :------------- | :---------------------------------------------------------------- | :--------------------------------------------- |
| `initialValue` | `V` | any value to be tracked |
| `options?` | `boolean` \| [`HistoryOptions`](modules.md#historyoptions)\<`V`\> | use to configure the proxyWithHistory utility. |

#### Returns

Expand Down Expand Up @@ -154,4 +161,4 @@ const state = proxyWithHistory({

#### Defined in

[packages/history-utility/src/history-utility.ts:129](https://github.com/valtiojs/valtio-history/blob/43e2fcd/packages/history-utility/src/history-utility.ts#L129)
[packages/history-utility/src/history-utility.ts:136](https://github.com/valtiojs/valtio-history/blob/3f12f1b/packages/history-utility/src/history-utility.ts#L136)
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { describe, expect, it } from 'vitest';
import { describe, expect, it, vi } from 'vitest';

import { HistoryNode, proxyWithHistory } from '../history-utility';

Expand All @@ -25,6 +25,30 @@ describe('proxyWithHistory: vanilla', () => {
expect(state.value.count).toEqual(1);
});

it('should call onChange when provided', async () => {
const onChange = vi.fn();
const state = proxyWithHistory({ count: 0 }, { onChange });
await Promise.resolve();
expect(state.value.count).toEqual(0);

state.value.count += 1;
await Promise.resolve();
expect(state.value.count).toEqual(1);
expect(onChange).toBeCalledWith({ count: 1 }, expect.any(Object));

state.undo();
await Promise.resolve();
expect(state.value.count).toEqual(0);
expect(onChange).toBeCalledWith({ count: 0 }, expect.any(Object));

state.redo();
await Promise.resolve();
expect(state.value.count).toEqual(1);
expect(onChange).toBeCalledWith({ count: 1 }, expect.any(Object));

expect(onChange).toHaveBeenCalledTimes(3);
});

it('should provide basic sequential undo functionality', async () => {
const state = proxyWithHistory({ count: 0 });
await Promise.resolve();
Expand Down
28 changes: 21 additions & 7 deletions packages/history-utility/src/history-utility.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,18 @@ export type History<T> = {

type SubscribeOps = Parameters<Parameters<typeof subscribe>[1]>[0];

export type HistoryOptions = {
export type HistoryOptions<T> = {
/**
* determines if the internal subscribe behaviour should be skipped.
*/
skipSubscribe?: boolean;
/**
* callback that triggers any time a change happens wihin the utility
*
* @param value - the changed value being tracked
* @param data - metadata of the change
*/
onChange?(value: T, data: { ops: SubscribeOps; historySaved: boolean }): void;
};

const isObject = (value: unknown): value is object =>
Expand All @@ -68,9 +75,9 @@ const deepClone = <T>(value: T): T => {
return baseObject;
};

const normalizeOptions = (
options?: HistoryOptions | boolean
): HistoryOptions => {
function normalizeOptions<T>(
options?: HistoryOptions<T> | boolean
): HistoryOptions<T> {
if (typeof options === 'boolean') {
if (import.meta.env?.MODE !== 'production') {
console.warn(`The second parameter of 'proxyWithHistory' as boolean is deprecated and support for boolean will be removed
Expand All @@ -92,7 +99,7 @@ const normalizeOptions = (
...defaultOptions,
...options,
};
};
}

/**
* This creates a new proxy with history support (ProxyHistoryObject).
Expand Down Expand Up @@ -128,7 +135,7 @@ const normalizeOptions = (
*/
export function proxyWithHistory<V>(
initialValue: V,
options?: HistoryOptions | boolean
options?: HistoryOptions<V> | boolean
) {
const utilOptions = normalizeOptions(options);
const proxyObject = proxy({
Expand Down Expand Up @@ -247,7 +254,14 @@ export function proxyWithHistory<V>(
*/
subscribe: () =>
subscribe(proxyObject, (ops) => {
if (proxyObject.shouldSaveHistory(ops)) proxyObject.saveHistory();
const shouldSaveHistory = proxyObject.shouldSaveHistory(ops);

if (shouldSaveHistory) proxyObject.saveHistory();

utilOptions.onChange?.(proxyObject.value, {
ops,
historySaved: shouldSaveHistory,
});
}),

// history rewrite utilities
Expand Down

0 comments on commit e8f5100

Please sign in to comment.