Skip to content

Commit

Permalink
feat(@react-ui/core): add system compnent & factory
Browse files Browse the repository at this point in the history
  • Loading branch information
vigor-13 committed Dec 5, 2023
1 parent 0d24d3b commit ea6d604
Show file tree
Hide file tree
Showing 13 changed files with 384 additions and 91 deletions.
2 changes: 1 addition & 1 deletion packages/ui/react/core/.eslintrc.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
module.exports = {
extends: ['custom/typescript'],
ignorePatterns: ['babel.config.js'],
ignorePatterns: [],
};
19 changes: 0 additions & 19 deletions packages/ui/react/core/babel.config.js

This file was deleted.

4 changes: 1 addition & 3 deletions packages/ui/react/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,12 @@
},
"devDependencies": {
"@storybook/react": "^7.6.0",
"@stylexjs/babel-plugin": "0.2.0-beta.27",
"@types/css-modules": "^1.0.5",
"@types/react": "^18.2.39",
"eslint-config-custom": "workspace:*",
"tsconfig": "workspace:*"
},
"dependencies": {
"@stylexjs/shared": "0.1.0-beta.1",
"@stylexjs/stylex": "0.2.0-beta.27",
"react": "^18.2.0"
}
}
41 changes: 32 additions & 9 deletions packages/ui/react/core/src/core/core.factory.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,43 @@
import { type DOMElements } from '../utils';
import { styled } from './core.styled';
import { type AnyObject, type DOMElements } from '../utils';
import { styled } from './core.system';
import {
type As,
type VigorComponent,
type HTMLVigorComponents,
} from './core.system.type';

class VigorFactory {
private readonly _cache = new Map<DOMElements, DOMElements>();
type VigorFactory = (<Element extends As, Props = AnyObject>(
element: Element,
options?: any, // TODO: 나중에 확인
) => VigorComponent<Element, Props>) &
HTMLVigorComponents;

public init = (): any => {
class Factory {
private readonly _cache = new Map<DOMElements, VigorComponent<DOMElements>>();

public build = (): VigorFactory => {
return new Proxy(styled, {
/**
* @example const Div = vigor('div');
*/
apply(_, __, args: [DOMElements, any]) {
return styled(...args);
},

/**
* @example <vigor.div>
*/
get: (_, element: DOMElements) => {
if (!this._cache.has(element)) this._cache.set(element, element);
if (!this._cache.has(element)) {
this._cache.set(element, styled(element));
}

return this._cache.get(element);
},
});
}) as VigorFactory;
};
}

const vigorFactory = new VigorFactory();
const factory = new Factory();

export const vigor = vigorFactory.init();
export const vigor = factory.build();
1 change: 0 additions & 1 deletion packages/ui/react/core/src/core/core.styled.ts

This file was deleted.

19 changes: 19 additions & 0 deletions packages/ui/react/core/src/core/core.system.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import React from 'react';
import { type AnyObject } from '../utils';
import { type VigorComponent, type As } from './core.system.type';

export function styled<Element extends As, Props = AnyObject>(
element: Element,
options?: any, // TODO: 나중에 확인
): any {
let _element = element;

const vigorComponent = React.forwardRef((props: AnyObject, ref) => {
const asElement = props.as as Element;
if (asElement !== undefined) _element = asElement;

return React.createElement(_element, { ref, ...props });
});

return vigorComponent as VigorComponent<Element, Props>;
}
66 changes: 66 additions & 0 deletions packages/ui/react/core/src/core/core.system.type.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import { type AnyObject, type Assign, type DOMElements } from '../utils';

export interface VigorProps {
csm?: CSSModule;
}

export type As = React.ElementType;

export type PropsOf<T extends As> = React.ComponentPropsWithoutRef<T> & {
as?: As;
};

export type OmitCommonProps<Target, OmitAdditionalProps> = Omit<
Target,
'as' | keyof OmitAdditionalProps
>;

export type RightJoinProps<
SourceProps = AnyObject,
OverrideProps = AnyObject,
> = OmitCommonProps<SourceProps, keyof OverrideProps> & OverrideProps;

export type MergeWithAs<
OriginalElementProps,
AsElementProps,
ComponentProps = AnyObject,
AsElement = As,
> = (
| RightJoinProps<OriginalElementProps, ComponentProps>
| RightJoinProps<AsElementProps, ComponentProps>
) & {
as?: AsElement;
};

export interface ComponentWithAs<
OriginalElement extends As,
ComponentProps = AnyObject,
> {
<AsElement extends As = OriginalElement>(
props: MergeWithAs<
React.ComponentProps<OriginalElement>,
React.ComponentProps<AsElement>,
ComponentProps,
AsElement
>,
): JSX.Element;
propTypes?: React.WeakValidationMap<ComponentProps>;
contextTypes?: React.ValidationMap<any>;
defaultProps?: Partial<ComponentProps>;
displayName?: string;
}

export interface VigorComponent<
OriginalElement extends As,
ComponentProps = AnyObject,
> extends ComponentWithAs<
OriginalElement,
Assign<VigorProps, ComponentProps>
> {}

export type HTMLVigorComponents = {
[Tag in DOMElements]: VigorComponent<Tag, AnyObject>;
};

export type HTMLVigorProps<Element extends As> = Omit<PropsOf<Element>, 'ref'> &
VigorProps;
1 change: 1 addition & 0 deletions packages/ui/react/core/src/utils/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export * from './util.type';
export * from './util.dom.type';
3 changes: 3 additions & 0 deletions packages/ui/react/core/src/utils/util.type.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export type AnyObject = Record<string, unknown>;

export type Assign<T, U> = Omit<T, keyof U> & U;
2 changes: 2 additions & 0 deletions packages/ui/react/example/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,13 @@
"clean": ""
},
"devDependencies": {
"@types/css-modules": "^1.0.5",
"@types/react": "^18.2.39",
"@types/react-dom": "^18.2.17",
"@vitejs/plugin-react": "^4.2.0",
"eslint-config-custom": "workspace:*",
"tsconfig": "workspace:*",
"typescript-plugin-css-modules": "^5.0.2",
"vite": "^5.0.2"
},
"dependencies": {
Expand Down
5 changes: 5 additions & 0 deletions packages/ui/react/example/src/app.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
.button {
width: 100px;
height: 100px;
background: coral;
}
7 changes: 6 additions & 1 deletion packages/ui/react/example/src/app.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
import React from 'react';
import { vigor } from '@react-ui/core/src';
import styles from './app.module.css';

export function App(): React.ReactNode {
return <vigor.div>example</vigor.div>;
return (
<>
<vigor.div className={styles.button}>example</vigor.div>
</>
);
}
Loading

0 comments on commit ea6d604

Please sign in to comment.