toss / slash Goto Github PK
View Code? Open in Web Editor NEWA collection of TypeScript/JavaScript packages to build high-quality web services.
Home Page: https://slash.page
License: MIT License
A collection of TypeScript/JavaScript packages to build high-quality web services.
Home Page: https://slash.page
License: MIT License
Package name: @toss/react
Please see follow hooks
I think these hooks are exactly same hook and there purpose for their own Component hook.
useKey
is useful for user who use key (typed for number) and reseting that key (by increasing), But I doubt that this hook will be used often.
So, Is it useful to take out the useKey
hook separately?
In my opinion, rather than managing the same hook as a local file in multiple packages, it is more useful in terms of management to bring dependencies and use them.
But I doubt that this hook will be used often... 🤔
Package name: react/emotion-utils
I want to like code like this position({top:10,bottom:8})
But position function did not support this type.
I want to add this code.
export function position(coordinates: Coordinates): SerializedStyles;`
const [top, right, bottom, left] = (() => {
// position(coordinates)
if (typeof positionOrTopOrCoordinates === 'object') {
return [
positionOrTopOrCoordinates.top,
positionOrTopOrCoordinates.right,
positionOrTopOrCoordinates.bottom,
positionOrTopOrCoordinates.left,
];
}
and test code
it('position({top: 0, left: 0})', () => {
const { getByTestId } = render(<div data-testid="test" css={position({ top: 0, left: 0 })} />);
const el = getByTestId('test');
expect(el).toBeInTheDocument();
expect(el).toHaveStyleRule('top', '0');
expect(el).not.toHaveStyleRule('bottom', '0');
expect(el).not.toHaveStyleRule('right', '0');
expect(el).toHaveStyleRule('left', '0');
});
I think toss team may not agree my opinion. So I open an issue, not pr. Thank you
Package name: @toss/utils
A function that indexes an array of objects based on a specific key value. It is a function that makes the object a key and value pair , which makes the cost of find specific data in the future cheaper.
const foo = [
{ id: 1, name: 'park', age: 23 },
{ id: 3, name: 'kim', age: 21 },
{ id: 5, name: 'lee', age: 24 },
];
// normal approach
const result = foo.find(item => item.name === "park") // Tour all items.
const result = foo.find(item => item.name === "kim") // Tour all items.
const result = foo.find(item => item.name === "lee") // Tour all items.
// new indexBy function
const indexedObj = indexBy(foo, "name") // Tour just one tiem
const result = indexedObj["kim"] // quick search
const result = indexedObj["lee"] // quick search
const result = indexedObj["park"] // quick search
If indexed, it is a performance-friendly situation because it can be found immediately without looking for values while traveling all list.
These functions are good for those situations when they can be found quickly and easily after a just one traveling.
type ElementType<T extends unknown[]> = T[number];
const indexBy = <ArrayObjectType extends Array<Record<PropertyKey, unknown>>, IndexType extends keyof ElementType<ArrayObjectType>>(
arrayObj:ArrayObjectType, key:IndexType
) => {
return arrayObj.reduce((acc, obj) => {
acc[obj[key]] = obj;
return acc
}, {} as any);
}
If the developer uses a key which have value that is other than a Property Key, it should be treated well.
Package name: @toss/emotion-utils
// FullHeight.tsx
export function FullHeight({ children, ...props }: { children: ReactNode } & HTMLAttributes<HTMLDivElement>) {
return (
<div> // why only div tag?
{children}
</div>
);
}
If you look at the current implementation of FullHeight, it is fixed and wrapped with a div
container.
However, in actual development, it is often necessary to semantically use section
or main
and other elements instead of div containers. In that case, it is inconvenient to use FullHeight.
I think it would be good to have better scalability!
like OpenGraph
interface Props {
container?: ComponentType<any>; // accept other tag
}
Package name:
id값이 자동으로 생성되고 export되지 않아서 오버레이가 사용된 컴포넌트에서만 열고 닫을 수 있는 것 같은데
혹시 다른 컴포넌트에서 특정한 오버레이를 열고 다는 방법이 있을까요?
It declaratively returns the defined value, and returns false
if the value is not defined(undefined, null
). The main function of isDefined
is to track undefined value, and is also useful for declaratively filtering array whice elements are objects.
itemList = [
{id: 1, isValid: true},
{isValid: false},
{isValid: false},
{id: 4, isValid: true},
]
itemList.map(item => item.id).filter(isDefined)
function isDefined<T>(argument: T | undefined | null): argument is T {
return argument !== undefined && argument !== null;
}
related #169
Package name: react-query
support useSuspendedQueries like useSuspendedQuery.
In my opinion, supporting Parallel Queries is a necessary api since @toss/react-query uses suspense as default. I hope we have support plans for this api.
https://tanstack.com/query/v3/docs/react/guides/parallel-queries
async-boundary, error-boundary
Current AsyncBoundaryProvider is not scoped AsyncBoundary, I think it is just designed only for reseting resetKey ErrorBoundary
(@toss/async-boundary)
interface AsyncBoundaryProvider {
resetKey: number;
reset(): void;
}
const AsyncBoundaryContext = createContext<AsyncBoundaryProvider | null>(null);
interface Props {
children: ReactNode;
}
export function AsyncBoundaryProvider({ children }: Props) {
const [resetKey, reset] = useResetError();
return <AsyncBoundaryContext.Provider value={{ resetKey, reset }}>{children}</AsyncBoundaryContext.Provider>;
}
export function useAsyncBoundaryContext() {
return useContext(AsyncBoundaryContext) ?? { resetKey: null, reset: () => {} };
}
If I can edit, I want to change AsyncBoundaryProvider to ResetErrorBoundaryProvider
(@toss/error-boundary)
const ResetErrorBoundaryContext = createContext({
resetKey: 0,
reset: () => {},
});
if (process.env.NODE_ENV !== 'production') {
ResetErrorBoundaryContext.displayName = 'ResetErrorBoundaryContext';
}
interface Props {
children: ReactNode;
}
export function ResetErrorBoundaryProvider({ children }: Props) {
const [resetKey, reset] = useResetError();
return <ResetErrorBoundaryContext.Provider value={{ resetKey, reset }}>{children}</ResetErrorBoundaryContext.Provider>;
}
export function useResetErrorBoundaryContext() {
return useContext(ResetErrorBoundaryContext);
}
ReturnType<typeof useAsyncBoundaryContext>
)union type is not intuitive.
import { expectType } from 'tsd';
expectType<AsyncBoundaryProvider | { resetKey: number; reset(): void; }>(useAsyncBoundaryContext()) // not intuitive, not essential union type
ReturnType<typeof useResetErrorBoundaryContext>
)infer just one type like below picture
import { expectType } from 'tsd';
expectType<{ resetKey: number; reset(): void; }>(useResetErrorBoundaryContext()) // intuitive, just essential type
we can check displayName, ResetErrorBoundaryContext.Provider
on react-devtools only for development mode
const ResetErrorBoundaryContext = createContext({
resetKey: 0,
reset: () => {},
});
if (process.env.NODE_ENV !== 'production') {
ResetErrorBoundaryContext.displayName = 'ResetErrorBoundaryContext';
}
If I can't use useContext, for example in Class Component or HTML like button or div, It will be helpful
export function ResetErrorBoundaryProvider({ children: Children }: Props) {
const [resetKey, reset] = useResetError();
const node = typeof Children === 'function' ? <Children reset={reset} /> : Children;
return <ResetErrorBoundaryContext.Provider value={{ resetKey, reset }}>{node}</ResetErrorBoundaryContext.Provider>;
}
<ResetErrorBoundaryProvider>
{({ reset }) => (
<button onClick={reset} /* <-- error reset 해야 하는 부분 */ />
<AsyncBoundary /* <-- suspense + error boundary로 감싸져야 하는 부분 */
pendingFallback={<TableSkeleton title="상세내역" row={10} />}
errorFallback={({ error, reset }) => (
<ErrorAlert theme="yellow" error={error} message="다시 시도해주세요." onResetError={reset} />
)}
>
<DataViewer />
</AsyncBoundary>
)}
</ResetErrorBoundaryProvider>
Can I change AsyncBoundaryProvider like this? this will be BREAKING CHANGE, so I want to check it before starting code
Package name: @toss/utils
In docs example, clamp(3, 5)
returns 5
, but the actual return value is 3
.
If this is not a bug, please change the docs not to be confused!
Return value of clamp(3, 5)
to be 5
Change clamp.ts to
if (bound2 == null) {
return Math.max(value, bound1);
}
Package name: react-query
Support @tanstack/react-query v4 please
Package name: @toss/[email protected]
commaizeNumber
didn't work at Android which written by RN.
The function returns String(value).replace(/(\d)(?=(\d\d\d)+(?!\d))/g, '$1,')
when input argument value's type is string
, but, it's weired that convert string type variants to string.
Here is my code.
const SOME_NUMBER = 1000000;
return (
<Text>{commaizeNumber(SOME_NUMBER}/<Text>
);
I expected it works as same in Android and iOS, but it didn't work at Android.
It works when I change code above like below.
const SOME_NUMBER = 1000000;
return (
<Text>{commaizeNumber(String(SOME_NUMBER)}/<Text>
);
Change commaizeNumber
functions as below. Delete unnecessary type conversion. Converting value only when value type is number.
export function commaizeNumber(value: string | number) {
if (typeof value === 'number') {
return String(value).replace(/(\d)(?=(\d\d\d)+(?!\d))/g, '$1,');
}
return value.replace(/(\d)(?=(\d\d\d)+(?!\d))/g, '$1,');
}
I made PR to solve this issue #104 .
Package name: @toss/use-overlay
If I use the open
method in overlay to open overlay, the states used in the open method are remembered as the values at the time when the open method is called.
Even if the state is newly updated, overlaied component do not know the newly updated state. I think it's a closure problem, can we solve it?
Allows the changed states outside of the overlaid component to be immediately reflected in the overlaid component.
you can play this code sand box
import { useOverlay } from "@toss/use-overlay";
import { Dispatch, PropsWithChildren, SetStateAction, useState } from "react";
import "./styles.css";
const Dialog = ({
caution,
children
}: PropsWithChildren<{ caution: string }>) => {
return (
<div
style={{
width: "400px",
height: "400px",
backgroundColor: "blue",
borderRadius: "8px",
color: "red",
margin: "30px",
padding: "30px"
}}
>
{children}
this is {caution} // this is not updated when click button
</div>
);
};
const CustomDialog = ({
setCaution
}: {
setCaution: Dispatch<SetStateAction<string>>;
}) => {
return (
<button onClick={() => setCaution(new Date().toString())}>
CLICK TO CHANGE CAUTION
</button>
);
};
export default function App() {
const [caution, setCaution] = useState<string>("");
const overlay = useOverlay();
const onClickHandler = () => {
overlay.open(() => (
<Dialog caution={caution}>
<CustomDialog setCaution={setCaution} />
</Dialog>
));
};
return (
<>
<button
onClick={onClickHandler}
style={{
width: "200px",
height: "80px",
backgroundColor: "white",
borderRadius: "4px"
}}
>
OPEN MODAL
</button>
</>
);
}
Declaratively enable unmounting behavior by handing over the callback that you want to cause when the component is unmounted.
Usually, I want a specific function to work when component is unmounted, but it was inconvenient.
function useUnmoundEffect<F extends (...args: any[]) => void>(callback: F) {
const preservedCallback = usePreservedCallback(callback);
useEffect(() => {
return () => preservedCallback();
}, [preservedCallback]);
}
Package name: @toss/react
useStorageState
, a type error occurs. This is because defaultValue
is inferred as a literal type
rather than a primitive type
.defaultValue
without writing a generic
in useStorageState
, but I couldn't find a way. Please advise if there is any other waygeneric
must be created if the defaultValue
is a primitive type
(string, boolean, number).This is an issue about a type error occurring in the useStorageState
hook.
If you try to use the example in the document of useStorageState
hook as it is, the following type error occurs.
function MyComponent() {
const [state, setState, refresh] = useStorageState('@service/some-resource', {
defaultValue: 0,
});
useEffect(() => {
setState(x => x + 1);
// ^ type error
}, []);
...
}
However, if you write a generic
, type errors do not occur:
const [state, setState, refresh] = useStorageState<number>('@service/some-resource', {
defaultValue: 0,
});
useEffect(() => {
// No error
setState((x) => x + 1);
}, [setState]);
I confirmed that the state
among the return values of useStorageState
in the example above is not inferred as number
, but as literal type 0
. In addition, even when the defaultValue
is a primitive type such as boolean
or string
, it is inferred only as a literal type
:
// const state1: true
const [state1, setState1, refresh1] = useStorageState('boolean', {
defaultValue: true,
});
// const state2: "str"
const [state2, setState2, refresh2] = useStorageState('string', {
defaultValue: 'str',
});
Here, I want to make type inference without writing generic like React.useState
. However, because of the type constraint that prevents the symbol
value from entering the devalutValue
of the useStorageState
argument, type inference is not possible as a primitive type like React.useState
.
// const count: number
const [count, setCount] = useState(1);
// const state: number ✅ What I want
// const state: 0 😢 Actually
const [state, setState, refresh] = useStorageState('number', {
defaultValue: 0
})
In microsoft/TypeScript#10676, when inferring function arguments, type parameters are inferred as widened literal types only in the following situations:
During type argument inference for a call expression the type inferred for a type parameter T is widened to its widened literal type if:
- all inferences for T were made to top-level occurrences of T within the particular parameter type, and
- T has no constraint or its constraint does not include primitive or literal types, and
- T was fixed during inference or T does not occur at top-level in the return type.
In other words, since the primitive type is included in the type constraint of useStorageState
, the type inferred from the type parameter is a literal type:(Please check my playground)
// useStorageState.ts
// A conditional type constraint contains a primitive type
export type Serializable<T> = T extends string | number | boolean | unknown[] | Record<string, unknown> ? T : never;
...
Therefore, I concluded that the type parameter T
cannot be inferred as a primitive type (e.g. string
, number
or boolean
) because of the type constraint for defaultValue
in useStorageState
. Is there any other way?
If there is no other way, it seems that the phrase that a generic
must be created when a primitive type enters the defaultValue
should be added to the official document.
Please give me some advice on the issue and I'll fix the documentation.
Would you mind registering @toss/slash as a Hacktoberfest participant?
Your PR/MR was submitted to a repository not participating in Hacktoberfest. Maintainers need to add the
hacktoberfest
topic to the repository, or add thehacktoberfest-accepted
label to your PR/MR.For more information about how exactly we validate PR/MRs for contributors, check the details on our participation page.
Package name: all package
{
"name": "@toss/assert",
"version": "1.0.4",
"sideEffects": false,
"exports": {
".": {
"require": "./src/index.ts",
"import": "./src/index.ts"
},
"./package.json": "./package.json"
},
"main": "src/index.ts",
"scripts": {
},
"dependencies": {
"@toss/utils": "workspace:^1.0.4"
},
"devDependencies": {
"typescript": "4.8.3"
},
"publishConfig": {
"access": "public",
"exports": {
".": {
"require": "./dist/index.js",
"import": "./esm/index.mjs",
"types": "./dist/index.d.ts"
},
"./package.json": "./package.json"
},
"import": "./esm/index.mjs", // here
"main": "dist/index.js",
"module": "./esm/index.mjs",
"types": "dist/index.d.ts"
},
"gitHead": "..."
}
I think "import": "./esm/index.mjs",
field is not official field, and not used in anywhere.
I checked this in node and npm. But I couldn't find any explanation about the field.
It seems that even webpack and rollup are not using "import" field of package.json.
What's the purpose of the "import" field ?
Check please :D
related #241
I have reviewed but I still think this change is not appropriate. Regardless of the intention of
useQueryParam
, someone may have already used it like:const productIds = useQueryParam<string[]>('productIds'); const parsedProductIds = productIds.map((id) => parseInt(id));I understand that you want to contribute, but It would be better to keep the previous implementation.
Even in this case, there is an error when used with parser.
If url is https://example.com?productIds=1&productIds=2
const productIds = useQueryParam<string[]>('productIds', {
parser: (productIds) => { // productIds will be ["1", "2"], but typely this is string... then, what role is parser?
/* we can't use productIds.map((id) => parseInt(id)) */
}
});
You can see example typely invalid example or runtimely invalid example
Even though there are clearly edge cases in the code, It is difficult to understand why Pull Requests or other code suggestion cannot be accepted only because it is a BREAKING CHANGE. So what is BREAKING CHANGE for and why do other libraries do major bumps? If necessary, I think we should proceed with a BREAKING CHANGE.
Originally posted by @manudeli in #241 (comment)
slash/packages/common/utils/src/device/isServer.ts
Lines 4 to 6 in cbfb2eb
We reuse isServer many times in slash libraries, but I don't know why we should check global
in isServer. could I get slash's intention why check not only window
also global
please?
We can see no global checking in below links
all packages have unnecessary files like jest.config.js, etc.
Use files files in package.json
I added this PR #165 to solve this problem.
Package name: @toss/react
useOutsideClickEffect does not behave like a document
useOutsideClickEffect Document
Example 1
const ref = useRef<HTMLElement>(null);
// doesn't work
useOutsideClickEffect(ref, () => {
console.log('outside clicked!');
});
The useOutsideClickEffect function operates by receiving the return value RefObject of useRef
const ref = useRef<HTMLElement>(null);
// work!
useOutsideClickEffect(ref, () => {
console.log('outside clicked!');
});
"react": "^18.2.0",
Only the code generated by CRA, App.tsx, has been modified as follows
import { useRef } from "react";
import { useOutsideClickEffect } from "@toss/react";
function App() {
const ref = useRef<HTMLDivElement>(null);
useOutsideClickEffect(ref, () => {
console.log("hello");
});
return (
<div className="App">
<h1 ref={ref}>hello</h1>
</div>
);
}
export default App;
useOutsideClickEffect parameter 'container' should be as follows.
AS-IS
useOutsideClickEffect(container: OneOrMore<HTMLElement | null>, callback: () => void)
TO-BE
useOutsideClickEffect(container: OneOrMore<React.RefObject<HTMLElement> | null>, callback: () => void)
Package name: @toss/utils reverseKeyValue
below is always correct
expect(reverseKeyValue({ jbee: 'eebj' })).toEqual({ eebj: 'jbee' });
but how about this object which is multiple same value
reverseKeyValue({ jbee: 'eebj',jbee2:'eebj' }) // { "eebj": "jbee2"}
It is not bug,, but people can make human error I think
Why don't we put the same values together in an array?
reverseKeyValue({ jbee: 'eebj',jbee2:'eebj' }) // { "eebj": ["jbee","jbee2"]}
In the case above, please suggest if it can be handled in another good way👍
Package name: @toss/storage
TypedStorage is subpath exported module. You should use @toss/storage/typed to use it.
when I use that import statement type error occurs.
because there is no typed file in node_modules
import { TypedStorage } from "@toss/storage/typed"; // should not occur type error
I'm used classic yarn not yarn berry
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@toss/storage/typed": ["./node_modules/@toss/storage/dist/typed"]
}
}
}
but it is not good for DX
every project it should be considered
Package name: useDeviceInfo
WebView를 사용하거나 모바일, PC 모두 대응할때,
사용자의 기기가 PC, Mobile(IOS/AOS)인지 확인하기 위한 커스텀 훅 입니다.
util에 getOSByUserAgent, isMobileWeb 등이 있으나 분리되어 있어 통합하기 위해 만들었습니다.
Package name: @toss/utils
current get
function uses about two RegExp(/[,[\]]+?/
, /[,[\].]+?/
).
export const get = <T = any>(obj: Record<string, any>, path: string, defaultValue?: T): T => {
// ...
const result = travel(/[,[\]]+?/) || travel(/[,[\].]+?/);
// ...
};
I think the second RegExp can sufficiently replace the first RegExp like below.
export const get = <T = any>(obj: Record<string, any>, path: string, defaultValue?: T): T => {
// ...
const result = travel(/[,[\].]+?/);
// ...
};
If you need it because of another edge case that I don't know, could you let me know?
Package name: @toss/lottie
A props called stopOnExit
is only received, and the corresponding processing is not taking place in the function at all.
It seems that the stopOnExit
will disappear, or it will have to be implemented according to actual behavior.
Even if you set this value, it will not actually be reflected.
but in docs stopOnExit
is described like this
// 애니메이션이 화면 바깥으로 나갔을 때 애니메이션 재생을 잠시 일시정지하는지 여부
isNonEmptyArray 함수의 example 의 결과가 반대로 적혀있습니다.
https://github.com/toss/slash/blob/main/packages/common/utils/src/array/isNonEmptyArray.ts#L15-L16
Package name: @toss/utils
In clamp.ts
Currently, the function is only supposed to work if bound1 is less than bound2. If user unaware of this rule and can put a larger value in bound1 than bound2. In that case, this function will not function normally. For example, if value=3, bound1=10, bound2=1, the return value must be 3, but the error results in 1.
i think this code works well if you agree I will make Pull request
export function clamp(value: number, bound1: number, bound2?: number) {
if (bound2 == null) {
return Math.min(value, bound1);
}
if (bound1 > bound2) {
return Math.min(Math.max(value, bound2), bound1);
}
return Math.min(Math.max(value, bound1), bound2);
}
Package name: @toss/use-funnel
내부적으로 next/router
에 의존하고 있어, next/navigation
으로 마이그레이션이 필요한 App Directory 버전에서는 @toss/use-funnl 의 기능을 사용할 수 없습니다.
참고자료1 : https://stackoverflow.com/questions/74421327/nextrouter-was-not-mounted-next-js
참고자료2: https://nextjs.org/docs/messages/next-router-not-mounted
appdirectory
경로에서 App Directory 호환 버전을 불러올 수 있도록 합니다.
Package name: all
Currently, Many packages (for example, @toss/emotion-utils) after build can contain unnecessary **.test.d.ts in dist directory like below picture.
or if other case that don't contain **.test.d.ts, test.ts / test.tsx file, thery are excluded by tsconfig.json.
but, every contributors can encounter this error like below picture. (for example @toss/error-boundary)
exclude ["**/jest.setup.ts", "**/*.test.*", "**/*.spec.*", "**/*.stories.*", "**/__storybook__/*"]
only for build.
include ["**/jest.setup.ts", "**/*.test.*", "**/*.spec.*", "**/*.stories.*", "**/__storybook__/*"]
during anyone developing.
During adding test after this #157 (comment) , I met this problem.
after using little time to solve this problem, first time, I thought there's no configuration to test dom. but it isn't. ;(
Just, It's about excluded test file by tsconfig.json like below.
{
"extends": "./tsconfig.json",
"exclude": ["**/jest.setup.ts", "**/*.test.*", "**/*.spec.*", "**/*.stories.*", "**/__storybook__/*"]
}
so, I could solve this bug by this solution: I added Solution Details below
["**/jest.setup.ts", "**/*.test.*", "**/*.spec.*", "**/*.stories.*", "**/__storybook__/*"]
when developing.How about adopt this solution in every packages? or Is there other way to solve this problem?
Package name: @toss/react
I think is more convenient return value is Object not array
Array return value is up to user remember what position it is
// In this case developer stop coding, and check docs for
// where is it (such as where is the value, and where is the toggle function)
const [] = useBooleanState()
Array return value is inconvenient for using specific return value
// developer who wants to taking boolean value and toggle function
const [bool, _, _, toggle] = useBooleanState()
I Propose change the return value array to Object value
for example (for user interface)
const { value, toggle } = useBooleanState()
Package name: @toss/impression-area
A circular reference occurs between ImpressionArea and useImpressionRef.
How about defining ImpressionAreaProps in useImpressionRef?
Package name: @toss/use-overlay
Currently, if I am using useOverlay
, I can control isOpen to false through the close
function, but if I want to unmount the overlay using return value of the useOverlay
, the interface does not exist. how about make exit function to developer use that function to unmount overlay?
return useMemo(
() => ({
open: (overlayElement: CreateOverlayElement) => {
mount(
id,
<OverlayController
key={id}
ref={overlayRef}
overlayElement={overlayElement}
onExit={() => {
unmount(id);
}}
/>
);
},
close: () => {
overlayRef.current?.close();
}
}),
[id, mount, unmount]
);
return useMemo(
() => ({
open: (overlayElement: CreateOverlayElement) => {
mount(
id,
<OverlayController
key={id}
ref={overlayRef}
overlayElement={overlayElement}
onExit={() => {
unmount(id);
}}
/>
);
},
close: () => {
overlayRef.current?.close();
},
exit: () => {
unmount(id);
},
}),
[id, mount, unmount]
);
function App() {
const overlay = useOverlay();
const openFooConfirmDialog = () => {
overlay.open(({ isOpen, close, exit }) => (
<FooConfirmDialog
open={isOpen}
onClose={() => {
close();
}}
onConfirm={() => {
exit();
}}
/>
));
};
return (
<div>
<button onClick={overlay.close}>just set isOpen to false</button>
<button onClick={overlay.exit}>unmount</button> // you can use like this to unmount overlay
</div>
);
}
Package name: @toss/hangul josa
Hello there.
First of all, I've been using the useful hangul functions created by Toss, and I'd like to thank you for providing them.
I have been using the josa
function, but I have noticed that the use of the '이에/에'
option is a bit ambiguous.
So I read the spec file, but it was missing a test case for that option.
The reason I can't find a use case for this option is probably due to my poor Korean skills, but if proper test cases are added, people like me can easily understand the use case.
Add a test case for the '이에/에'
option to the test code of the josa
function.
-
If slash.page can provide more interactive playground in docs for who want to learn @toss/slash, more users will dive deeply to learn these libraries easily.
And It will make users better to understand what problem each libraries solved.
Package name: docs
Add codesandbox like https://beta.reactjs.org
New version of React docs keynote, YouTube video
Package name: react-query
add useSuspendedInfiniteQuery like useSuspendedQuery.
Make a function wrapping useInfiniteQuery like useSuspendedQuery of @toss/react-query wrapping useQuery
Package name: @toss/react
When enabled
was false
, onClick
event in ClickArea
isn't disabled
Now State: enabled
option in ClickArea
is false
Expected: onClick
function have been not called
Actual: onClick
function have been called
enabled
to false
from true
.I made PR to solve this issue #174.
문서에서 zip 함수에 대한 설명이 누락된 것을 확인했습니다.
/**
* @name zip
* Array의 zip 연산을 수행합니다.
* @example
* zip([1, 2], ['a', 'b']) --> [[1, 'a'], [2, 'b']]
*/
docs를 보며 code block의 몇가지 문제점을 발견했습니다.
'''[typescript 부재]
function isRRN() {}
'''
'''typescript
function isRRN() {}
Package name: @toss/react-query
const Component = () => {
const boolean = !!(Math.random() > 0.5)
const query = useSuspendedQuery(
["example"] as const,
async () => {
return "response" as const
},
{ enabled: boolean }
)
console.log(query.data) // BaseSuspendedUseQueryResult<"response" | undefined>.data: "response" | undefined
if (query.isSuccess) {
console.log(query.data) // BaseSuspendedUseQueryResult<"response" | undefined>.data: "response" | undefined
}
return ...
}
const Component = () => {
const boolean = !!(Math.random() > 0.5)
const query = useSuspendedQuery(
["example"] as const,
async () => {
return "response" as const
},
{ enabled: boolean }
)
console.log(query.data) // BaseSuspendedUseQueryResult<"response" | undefined>.data: "response" | undefined
if (query.isSuccess) {
console.log(query.data) // BaseSuspendedUseQueryResult<"response">.data: "response"
}
return ...
}
export declare function useSuspendedQuery<TQueryFnData = unknown, TError = unknown, TData = TQueryFnData, TQueryKey extends QueryKey = QueryKey>(queryKey: TQueryKey, queryFn: QueryFunction<TQueryFnData, TQueryKey>, options?: Omit<SuspendedUseQueryOptions<TQueryFnData, TError, TData, TQueryKey>, 'enabled'>): SuspendedUseQueryResultOnSuccess<TData>;
export declare function useSuspendedQuery<TQueryFnData = unknown, TError = unknown, TData = TQueryFnData, TQueryKey extends QueryKey = QueryKey>(queryKey: TQueryKey, queryFn: QueryFunction<TQueryFnData, TQueryKey>, options: Omit<SuspendedUseQueryOptions<TQueryFnData, TError, TData, TQueryKey>, 'enabled'> & {
enabled?: true;
}): SuspendedUseQueryResultOnSuccess<TData>;
export declare function useSuspendedQuery<TQueryFnData = unknown, TError = unknown, TData = TQueryFnData, TQueryKey extends QueryKey = QueryKey>(queryKey: TQueryKey, queryFn: QueryFunction<TQueryFnData, TQueryKey>, options: Omit<SuspendedUseQueryOptions<TQueryFnData, TError, TData, TQueryKey>, 'enabled'> & {
enabled: false;
}): SuspendedUseQueryResultOnIdle<undefined>
export declare function useSuspendedQuery<TQueryFnData = unknown, TError = unknown, TData = TQueryFnData, TQueryKey extends QueryKey = QueryKey>(queryKey: TQueryKey, queryFn: QueryFunction<TQueryFnData, TQueryKey>, options: SuspendedUseQueryOptions<TQueryFnData, TError, TData, TQueryKey>): BaseSuspendedUseQueryResult<TData | undefined>;
export declare function useSuspendedQuery<TQueryFnData = unknown, TError = unknown, TData = TQueryFnData, TQueryKey extends QueryKey = QueryKey>(queryKey: TQueryKey, queryFn: QueryFunction<TQueryFnData, TQueryKey>, options?: Omit<SuspendedUseQueryOptions<TQueryFnData, TError, TData, TQueryKey>, 'enabled'>): SuspendedUseQueryResultOnSuccess<TData>;
export declare function useSuspendedQuery<TQueryFnData = unknown, TError = unknown, TData = TQueryFnData, TQueryKey extends QueryKey = QueryKey>(queryKey: TQueryKey, queryFn: QueryFunction<TQueryFnData, TQueryKey>, options: Omit<SuspendedUseQueryOptions<TQueryFnData, TError, TData, TQueryKey>, 'enabled'> & {
enabled?: true;
}): SuspendedUseQueryResultOnSuccess<TData>;
export declare function useSuspendedQuery<TQueryFnData = unknown, TError = unknown, TData = TQueryFnData, TQueryKey extends QueryKey = QueryKey>(queryKey: TQueryKey, queryFn: QueryFunction<TQueryFnData, TQueryKey>, options: Omit<SuspendedUseQueryOptions<TQueryFnData, TError, TData, TQueryKey>, 'enabled'> & {
enabled: false;
}): SuspendedUseQueryResultOnIdle<undefined>
export declare function useSuspendedQuery<TQueryFnData = unknown, TError = unknown, TData = TQueryFnData, TQueryKey extends QueryKey = QueryKey>(queryKey: TQueryKey, queryFn: QueryFunction<TQueryFnData, TQueryKey>, options: SuspendedUseQueryOptions<TQueryFnData, TError, TData, TQueryKey>): SuspendedUseQueryResultOnSuccess<TData> | SuspendedUseQueryResultOnIdle<undefined>;
First, Thanks to release this repo 👍
@toss/[email protected]
.<ImpressionArea>
import "./App.css";
import { ImpressionArea } from "@toss/impression-area";
function App() {
return (
<div className="App">
<ImpressionArea onImpressionStart={() => console.log("start")}>
<div className="DummyBox" />
</ImpressionArea>
</div>
);
}
export default App;
cannot resolve modules
and I found wrong esm export path in dependencies modules package.json
./esm/index.js
./esm/index.mjs
so, to avoid the error, I tried to something:
- "module": "./esm/index.js",
+ "module": "./esm/index.mjs",
- "import": "./esm/index.js"
+ "import": "./esm/index.mjs"
after fixed, works well.
And lastly, I think it would be a good idea to check it all over again.
Once again, Really appreciate release this repo. 😄
Package name: @toss/utils
v1.0.4
16자리 수 넘는 순간부터 제대로 컴마가 찍히지 않는 것 같아요
console.log(commaizeNumber(1234123412341234)); // 1,234,123,412,341,234
console.log(commaizeNumber(12341234123412341)); // 12,341,234,123,412,341
console.log(commaizeNumber(123412341234123412)); // 123,412,341,234,123,412
console.log(commaizeNumber(1234123412341234123)); // 1,234,123,412,341,234,123
console.log(commaizeNumber(12341234123412341234)); // 12,341,234,123,412,341,234
@toss/utils
commaizeNumber
Package name:@toss/use-funnel
Idea Proposal for Supporting the 'App' Directory in Next.js 13(It is Linked issue #228)
I have attempted to make @toss/use-funnel
support the Next.js
's App directory.
Currently, @toss/use-funnel
does not provide full support for Next.js@^13
. The reason is that it does not support the App directory.
This is seem to Next.js
's App directory supports routing using the AppRouter provided by next/navigation
, while the Pages directory uses next/router
for routing.
Initially, I thought that to enable support for the App directory of Next.js 13 in @toss/use-funnel
, it might be possible to receive the useRouter
hook from an external source and return the Router object. Although there were slight differences in the signatures of the push and replace methods between the two Router objects, the existence of these methods seemed to make this approach possible.
During the process of testing this approach, I discovered that the useRouter
provided through next/navigation
returns an AppRouterInstance
that doesn't align adequately with the existing NextRouter
object from next/router
(notably lacking the query attribute). Furthermore, implementing this approach could lead to significant API changes and potentially impact @toss/use-query-param, which is used by @toss/use-funnel
. Additionally, I couldn't find a way to inject a router object into the useRouter
called within withState
.
As an alternative, I propose creating a custom router package named @toss/useRouter
. This approach could potentially allow both @toss/use-query-param
and @toss/use-funnel
to leverage a custom router, addressing these issues.
Another possible solution is temporarily segregating the implementation of useFunnel
to specifically support the App directory.
Package name: @tossteam/jest
When I clean yarn cache and I install package, error is occuried.
I expected the installation to be successful.
yarn cache clean
yarn
I don't know where is @tossteam/jest
package... is it private package ?
In my opinion, thanks to zero-install, unless the user deletes the cache folder himself, it won't be reproduced, but I posted it because I'm curious.
Package name: @toss/date
When trying to use utils from @toss/date
package, it throws error below.
Module not found: Error: Can't resolve 'date-fns/locale/ko' in '/Users/chanmin/react-test/node_modules/@toss/date/esm'
Did you mean 'index.js'?
BREAKING CHANGE: The request 'date-fns/locale/ko' failed to resolve only because it was resolved as fully specified
(probably because the origin is strict EcmaScript Module, e. g. a module with javascript mimetype, a '*.mjs' file, or a '*.js' file where the package.json contains '"type": "module"').
The extension in the request is mandatory for it to be fully specified.
Add the extension to the request.
@toss/date
should be available without any tweak, but this package cannot be imported as expected.
@toss/date
@toss/date
Add .js
extension on date-fns locale import
AS-IS
// packages/common/date/src/date.ts
// eslint-disable-next-line import/no-duplicates
import { format as _format, isAfter, isBefore, isEqual, isValid } from 'date-fns';
import locale from 'date-fns/locale/ko'; // => This import statement should be changed (to explicitly provide extension)
TO-BE
// eslint-disable-next-line import/no-duplicates
import { format as _format, isAfter, isBefore, isEqual, isValid } from 'date-fns';
import locale from 'date-fns/locale/ko/index.js';
Quotation
@manudeli
I think you're right about seprating to next PR.
And yes, you can open an issue, and you can setup up tsd tests in whole monorepo.
But with bottom-up approach,
how about adopting tsd only in @tossteam/react-query first and do the whole thing later?
Originally posted by @changyoungoh in #73 (comment)
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.