Skip to content
This repository has been archived by the owner on Dec 11, 2023. It is now read-only.

Commit

Permalink
[feat] useFromRef (#11)
Browse files Browse the repository at this point in the history
* Add UseCreateRef Export

* Test SugarFormRef

* Create useFromRef Implementations
  • Loading branch information
AsPulse authored Mar 12, 2023
1 parent e4940b6 commit be13589
Show file tree
Hide file tree
Showing 5 changed files with 95 additions and 1 deletion.
6 changes: 5 additions & 1 deletion src/component/sugar/create.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import type { Sugar, SugarObjectNode, SugarUser, SugarUserReshaper } from '.';
import type { Sugar, SugarObjectNode, SugarUser, SugarUserReshaper, SugarValue } from '.';
import { SugarDownstreamEventEmitter } from '../../util/events/downstreamEvent';
import { SugarUpstreamEventEmitter } from '../../util/events/upstreamEvent';
import type { SugarObject } from '../../util/object';
import { isSugarObject } from '../../util/object';
import { useSugar } from './use';
import { useSugarFromRef } from './useFromRef';

export function createEmptySugar<T>(path: string, template: T): Sugar<T> {
const sugar: Sugar<T> = {
Expand All @@ -14,6 +15,9 @@ export function createEmptySugar<T>(path: string, template: T): Sugar<T> {
downstream: new SugarDownstreamEventEmitter(),
use:
<U extends SugarObject>(options: SugarUserReshaper<T, U>) => useSugar<T, U>(sugar, options),
useFromRef:
(param: { get: () => SugarValue<T>, set: (value: T) => void }) =>
useSugarFromRef(sugar, param),
};

if (isSugarObject(template)) {
Expand Down
3 changes: 3 additions & 0 deletions src/component/sugar/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ export type SugarData<T> = {
template: T,
upstream: SugarUpstreamEventEmitter,
downstream: SugarDownstreamEventEmitter,
useFromRef: (param: { get: () => SugarValue<T>, set: (value: T) => void }) => {
onChange: () => void, onBlur: () => void
},
} & (
T extends SugarObject ?
{
Expand Down
33 changes: 33 additions & 0 deletions src/component/sugar/useFromRef.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import type { Sugar, SugarValue } from '.';
import { SugarFormError } from '../../util/error';
import { setDirty } from './dirty';

export function useSugarFromRef<T>(
sugar: Sugar<T>, param: { get: () => SugarValue<T>, set: (value: T) => void },
): {
onChange: () => void, onBlur: () => void
} {

const refreshDirty = (): void => {
if (!sugar.mounted) throw new SugarFormError('SF0021', `Path: ${sugar.path}}`);
const value = sugar.get();
setDirty(sugar, !value.success || sugar.template !== value.value);
};

const updateSugar = sugar as Sugar<T> & { mounted: true };
updateSugar.mounted = true;
updateSugar.get = param.get;
updateSugar.set = (v): void => {
param.set(v);
refreshDirty();
};
updateSugar.isDirty = false;

return {
onChange: (): void => {
if (!sugar.mounted) throw new SugarFormError('SF0021', `Path: ${sugar.path}}`);
if (!sugar.isDirty) setDirty(sugar, true);
},
onBlur: () => refreshDirty(),
};
}
4 changes: 4 additions & 0 deletions tests/sugarUse.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ describe('wrapSugar', () => {
downstream: expect.any(SugarDownstreamEventEmitter),
use: expect.any(Function),
useObject: expect.any(Function),
useFromRef: expect.any(Function),
},
d: {
mounted: false,
Expand All @@ -34,6 +35,7 @@ describe('wrapSugar', () => {
upstream: expect.any(SugarUpstreamEventEmitter),
downstream: expect.any(SugarDownstreamEventEmitter),
use: expect.any(Function),
useFromRef: expect.any(Function),
},
};

Expand All @@ -58,6 +60,7 @@ describe('useObject', () => {
upstream: expect.any(SugarUpstreamEventEmitter),
downstream: expect.any(SugarDownstreamEventEmitter),
use: expect.any(Function),
useFromRef: expect.any(Function),
},
c: {
mounted: false,
Expand All @@ -66,6 +69,7 @@ describe('useObject', () => {
upstream: expect.any(SugarUpstreamEventEmitter),
downstream: expect.any(SugarDownstreamEventEmitter),
use: expect.any(Function),
useFromRef: expect.any(Function),
},
};

Expand Down
50 changes: 50 additions & 0 deletions tests/useFromRef.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { describe, it } from '@jest/globals';
import { renderHook } from '@testing-library/react';
import type { Sugar, SugarValue } from '../src/component/sugar';
import { createEmptySugar } from '../src/component/sugar/create';


const safeSet = <T,>(a: Sugar<T>, value: T): void => {
if (a.mounted) {
a.get = (): SugarValue<T> => ({ success: true, value });
a.set(value);
}
};

const safeEdit = <T,>(a: Sugar<T>, value: T): void => {
if (a.mounted) {
a.get = (): SugarValue<T> => ({ success: true, value });
}
};

describe('useFromRef', () => {

it('should work', () => {
const a = createEmptySugar<string>('', 'abc');
const setter = jest.fn();

const { result: { current: { onChange, onBlur } } } = renderHook(() =>
a.useFromRef({
get: () => ({ success: true, value: 'abc' }),
set: setter,
}),
);

expect(a.mounted).toBe(true);
expect(a.mounted && a.isDirty).toBe(false);
expect(a.mounted && a.get()).toStrictEqual({ success: true, value: 'abc' });
safeSet(a, 'def');
expect(a.mounted && a.isDirty).toBe(true);
expect(setter).toHaveBeenCalledTimes(1);
expect(setter).toHaveBeenCalledWith('def');
safeEdit(a, 'ghi');
onChange();
expect(a.mounted && a.isDirty).toBe(true);
expect(a.mounted && a.get()).toStrictEqual({ success: true, value: 'ghi' });
safeEdit(a, 'abc');
onBlur();
expect(a.mounted && a.isDirty).toBe(false);

});

});

0 comments on commit be13589

Please sign in to comment.