Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(ui/system): HTMLFavolinkPropsWithout, ComponentPropsWithout type 추가, 내부 공통적인 파일들 병합 #309

Merged
merged 1 commit into from
Aug 13, 2024
Merged
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
46 changes: 0 additions & 46 deletions packages/ui/src/system/factory.ts

This file was deleted.

80 changes: 80 additions & 0 deletions packages/ui/src/system/factory.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import {
type ComponentPropsWithRef,
type ComponentPropsWithoutRef,
type ElementType,
type ForwardRefExoticComponent,
} from 'react';
import { forwardRef } from './forward-ref';
import { Slot } from './slot';

type JsxElements = keyof JSX.IntrinsicElements;

type AsChildProp = {
asChild?: boolean;
};

type FavolinkPropsWithRef<E extends ElementType> = AsChildProp &
ComponentPropsWithRef<E>;

type FavolinkForwardRefComponent<E extends ElementType> =
ForwardRefExoticComponent<FavolinkPropsWithRef<E>>;

type FavolinkComponents = {
[E in JsxElements]: FavolinkForwardRefComponent<E>;
};

export type HTMLProps<E extends JsxElements> = ComponentPropsWithoutRef<E>;

export type HTMLFavolinkProps<E extends JsxElements> = AsChildProp &
HTMLProps<E>;

export type HTMLFavolinkPropsWithout<
E extends JsxElements,
O extends
| Omit<string, keyof HTMLFavolinkProps<E>>
| keyof HTMLFavolinkProps<E>,
> = Omit<HTMLFavolinkProps<E>, O & string>;

export type ComponentPropsWithout<
T extends ElementType,
O extends
| Omit<string, keyof ComponentPropsWithoutRef<T>>
| keyof ComponentPropsWithoutRef<T>,
> = Omit<ComponentPropsWithoutRef<T>, O & string>;

export type RemovedProps = 'color' | 'defaultChecked' | 'defaultValue';

export type RightJoinProps<T extends object, O extends object> = O &
Omit<T, keyof O>;

function factory() {
const cache = new Map<JsxElements, FavolinkComponents[JsxElements]>();

return new Proxy(withAsChild, {
get: (_, element: JsxElements) => {
if (!cache.get(element)) {
cache.set(element, withAsChild(element));
}

return cache.get(element);
},
});
}

export const favolink = factory() as unknown as FavolinkComponents;

function withAsChild<E extends JsxElements>(element: E) {
const FavolinkComponent = forwardRef<HTMLFavolinkProps<E>, E>(
function FavolinkComponent(props, forwardedRef) {
const { asChild, ...restProps } = props;

const Comp: any = asChild ? Slot : element;

return <Comp ref={forwardedRef} {...restProps} />;
},
);

FavolinkComponent.displayName = `Favolink.${element}`;

return FavolinkComponent as FavolinkComponents[E];
}
2 changes: 0 additions & 2 deletions packages/ui/src/system/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,3 @@ export * from './create-context';
export * from './factory';
export * from './forward-ref';
export * from './slot';
export * from './slottable';
export * from './with-as-child';
61 changes: 35 additions & 26 deletions packages/ui/src/system/slot.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,34 +8,8 @@ import {
forwardRef,
isValidElement,
} from 'react';
import { Slottable, type SlottableProps } from './slottable';
import { composeRefs, mergeProps } from '../utils';

function isSlottable(child: ReactNode): child is ReactElement<SlottableProps> {
return isValidElement(child) && child.type === Slottable;
}

type ReactElementWithRef = ReactElement & { ref: Ref<HTMLElement> };

type SlotCloneProps = HTMLAttributes<HTMLElement> & {
children: ReactElementWithRef;
};

const SlotClone = forwardRef<HTMLElement, SlotCloneProps>(
function SlotClone(props, forwardedRef) {
const { children, ...slotProps } = props;

return isValidElement(children)
? cloneElement(children, {
...mergeProps(slotProps, children.props),
ref: forwardedRef
? composeRefs(forwardedRef, children.ref)
: children.ref,
})
: null;
},
);

type SlotProps = HTMLAttributes<HTMLElement> & {
children: ReactNode;
};
Expand Down Expand Up @@ -86,3 +60,38 @@ export const Slot = forwardRef<HTMLElement, SlotProps>(
);
},
);

type ReactElementWithRef = ReactElement & { ref: Ref<HTMLElement> };

type SlotCloneProps = HTMLAttributes<HTMLElement> & {
children: ReactElementWithRef;
};

const SlotClone = forwardRef<HTMLElement, SlotCloneProps>(
function SlotClone(props, forwardedRef) {
const { children, ...slotProps } = props;

return isValidElement(children)
? cloneElement(children, {
...mergeProps(slotProps, children.props),
ref: forwardedRef
? composeRefs(forwardedRef, children.ref)
: children.ref,
})
: null;
},
);

export type SlottableProps = {
children: ReactNode;
};

export function Slottable(props: SlottableProps) {
const { children } = props;

return children;
}

function isSlottable(child: ReactNode): child is ReactElement<SlottableProps> {
return isValidElement(child) && child.type === Slottable;
}
11 changes: 0 additions & 11 deletions packages/ui/src/system/slottable.tsx

This file was deleted.

21 changes: 0 additions & 21 deletions packages/ui/src/system/with-as-child.tsx

This file was deleted.

Loading