feat: manually mirror opencoze's code from bytedance

Change-Id: I09a73aadda978ad9511264a756b2ce51f5761adf
This commit is contained in:
fanlv
2025-07-20 17:36:12 +08:00
commit 890153324f
14811 changed files with 1923430 additions and 0 deletions

View File

@@ -0,0 +1,116 @@
/*
* Copyright 2025 coze-dev Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { act, renderHook } from '@testing-library/react-hooks';
import useToggle from '../index';
describe('useToggle', () => {
it('toggle values', () => {
const hook = renderHook(() => useToggle());
expect(hook.result.current.state).toBeFalsy();
act(() => {
hook.result.current.toggle();
});
expect(hook.result.current.state).toBeTruthy();
act(() => {
hook.result.current.toggle();
});
expect(hook.result.current.state).toBeFalsy();
act(() => {
hook.result.current.toggle(false);
});
expect(hook.result.current.state).toBeFalsy();
act(() => {
hook.result.current.toggle(true);
});
expect(hook.result.current.state).toBeTruthy();
});
it('default value', () => {
const hook = renderHook(() => useToggle(true));
expect(hook.result.current.state).toBeTruthy();
act(() => {
hook.result.current.toggle();
});
expect(hook.result.current.state).toBeFalsy();
act(() => {
hook.result.current.toggle();
});
expect(hook.result.current.state).toBeTruthy();
act(() => {
hook.result.current.toggle(true);
});
expect(hook.result.current.state).toBeTruthy();
});
it('default non-boolean value', () => {
const defaultValue = {};
const hook = renderHook(() => useToggle(defaultValue));
expect(hook.result.current.state).toBe(defaultValue);
act(() => {
hook.result.current.toggle();
});
expect(hook.result.current.state).toBe(false);
act(() => {
hook.result.current.toggle();
});
expect(hook.result.current.state).toBe(defaultValue);
act(() => {
hook.result.current.toggle(defaultValue);
});
expect(hook.result.current.state).toBe(defaultValue);
});
it('default non-boolean values', () => {
enum Theme {
Light = 0,
Dark,
}
const hook = renderHook(() => useToggle<Theme>(Theme.Light, Theme.Dark));
expect(hook.result.current.state).toBe(Theme.Light);
act(() => {
hook.result.current.toggle();
});
expect(hook.result.current.state).toBe(Theme.Dark);
act(() => {
hook.result.current.toggle();
});
expect(hook.result.current.state).toBe(Theme.Light);
act(() => {
hook.result.current.toggle(Theme.Light);
});
expect(hook.result.current.state).toBe(Theme.Light);
act(() => {
hook.result.current.toggle(Theme.Dark);
});
expect(hook.result.current.state).toBe(Theme.Dark);
});
});

View File

@@ -0,0 +1,62 @@
/*
* Copyright 2025 coze-dev Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { useState, useMemo } from 'react'
type State = any
export interface ReturnValue<T = State> {
state: T;
toggle: (value?: T) => void;
}
function useToggle<T = boolean>(): ReturnValue<T>
function useToggle<T = State>(defaultValue: T): ReturnValue<T>
function useToggle<T = State, U = State>(
defaultValue: T,
reverseValue: U,
): ReturnValue<T | U>
function useToggle<D extends State = State, R extends State = State>(
defaultValue: D = false as D,
reverseValue?: R,
) {
const [state, setState] = useState<D | R>(defaultValue)
const actions = useMemo(() => {
const reverseValueOrigin = (reverseValue === undefined ? !defaultValue : reverseValue) as D | R
const toggle = (value?: D | R) => {
if (value !== undefined) {
setState(value)
return
}
setState((s) => (s === defaultValue ? reverseValueOrigin : defaultValue))
}
return {
toggle,
}
}, [defaultValue, reverseValue])
return {
state,
...actions,
}
}
export default useToggle