>;
5 |
--------------------------------------------------------------------------------
/packages/card/src/utils/omitProps.ts:
--------------------------------------------------------------------------------
1 | const filterProps = (props: P, keys: K[]) => {
2 | const result = {} as Record]>;
3 | for (const prop in props) {
4 | if (!keys.includes(prop as unknown as K)) {
5 | result[prop] = props[prop];
6 | }
7 | }
8 | return result;
9 | };
10 |
11 | export default filterProps;
12 |
--------------------------------------------------------------------------------
/packages/card/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tsconfig.json",
3 | "include": ["./src"],
4 | "compilerOptions": {
5 | "declaration": true,
6 | "isolatedModules": false,
7 | "esModuleInterop": true, // es module이 아니어도 import export 쓸 수 있게 함
8 | "importHelpers": true,
9 | "types": ["@emotion/react/types/css-prop", "@types/jest", "@testing-library/jest-dom"],
10 | "jsx": "react-jsx",
11 | "jsxImportSource": "@emotion/react"
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/packages/checkbox/jest.config.ts:
--------------------------------------------------------------------------------
1 | import type { Config } from 'jest';
2 |
3 | const config: Config = {
4 | preset: 'ts-jest',
5 | testEnvironment: 'jsdom',
6 | setupFilesAfterEnv: ['/setup-jest.ts'],
7 | transform: {
8 | '^.+\\.[jt]sx?$': 'ts-jest',
9 | '^.+\\.(css|scss|sass|less)$': 'jest-preview/transforms/css',
10 | '^(?!.*\\.(js|jsx|mjs|cjs|ts|tsx|css|json)$)': 'jest-preview/transforms/file'
11 | }
12 | };
13 |
14 | export default config;
--------------------------------------------------------------------------------
/packages/checkbox/setup-jest.ts:
--------------------------------------------------------------------------------
1 | import '@testing-library/jest-dom/';
2 |
--------------------------------------------------------------------------------
/packages/checkbox/src/components/CheckboxGroup.tsx:
--------------------------------------------------------------------------------
1 | /** @jsxImportSource @emotion/react */
2 | import { createClassVariant } from '@jdesignlab/theme';
3 | import { CheckboxGroupContext } from '../context';
4 | import type { CheckboxGroupProps } from '../types';
5 |
6 | export const CheckboxGroup = (props: CheckboxGroupProps) => {
7 | const { children, defaultValue, ...otherProps } = props;
8 | const contextValue = {
9 | defaultValues: props.defaultValue ?? []
10 | };
11 |
12 | return (
13 |
14 |
15 | {children}
16 |
17 |
18 | );
19 | };
20 |
21 | CheckboxGroup.displayName = 'Checkbox.Group';
22 |
--------------------------------------------------------------------------------
/packages/checkbox/src/context.ts:
--------------------------------------------------------------------------------
1 | import { createContext } from 'react';
2 | import type { CheckboxValue } from './types';
3 | export const CheckboxGroupContext = createContext({
4 | defaultValues: undefined as CheckboxValue
5 | });
6 |
--------------------------------------------------------------------------------
/packages/checkbox/src/hooks/useKeyboardHandler.ts:
--------------------------------------------------------------------------------
1 | import { spaceKeyToggleHandler, arrowKeyNavigationHandler } from '@jdesignlab/react-utils';
2 |
3 | export const useKeyboardHandler = (props: {
4 | event: React.KeyboardEvent;
5 | parentScope: string;
6 | selectorOfList: string;
7 | }) => {
8 | const { event, parentScope, selectorOfList } = props;
9 | const el = event.target as HTMLInputElement;
10 |
11 | const spaceKeyAction = () => {
12 | el.checked = !el.checked;
13 | };
14 |
15 | spaceKeyToggleHandler({ event, action: spaceKeyAction });
16 | arrowKeyNavigationHandler({ event, parentScope, selectorOfList });
17 | };
18 |
--------------------------------------------------------------------------------
/packages/checkbox/src/index.ts:
--------------------------------------------------------------------------------
1 | export * from './components/Checkbox';
2 |
--------------------------------------------------------------------------------
/packages/checkbox/src/types.ts:
--------------------------------------------------------------------------------
1 | import type { ColorToken } from '@jdesignlab/theme';
2 |
3 | export type CheckboxSize = 'sm' | 'md' | 'lg' | 'xl';
4 | export type CheckboxValue = number[] | string[] | undefined;
5 |
6 | export interface CheckboxProps extends React.InputHTMLAttributes {
7 | children?: React.ReactNode;
8 | color?: ColorToken;
9 | value?: string | number;
10 | }
11 |
12 | export interface CheckboxGroupProps {
13 | children?: React.ReactNode;
14 | defaultValue?: string[] | number[];
15 | }
16 |
--------------------------------------------------------------------------------
/packages/checkbox/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tsconfig.json",
3 | "include": ["./src"],
4 | "compilerOptions": {
5 | "declaration": true,
6 | "isolatedModules": false,
7 | "esModuleInterop": true, // es module이 아니어도 import export 쓸 수 있게 함
8 | "importHelpers": true,
9 | "types": ["@emotion/react/types/css-prop", "@types/jest", "@testing-library/jest-dom"],
10 | "jsx": "react-jsx",
11 | "jsxImportSource": "@emotion/react"
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/packages/drawer/jest.config.ts:
--------------------------------------------------------------------------------
1 | import type { Config } from 'jest';
2 |
3 | const config: Config = {
4 | preset: 'ts-jest',
5 | testEnvironment: 'jsdom',
6 | setupFilesAfterEnv: ['/setup-jest.ts'],
7 | transform: {
8 | '^.+\\.[jt]sx?$': 'ts-jest',
9 | '^.+\\.(css|scss|sass|less)$': 'jest-preview/transforms/css',
10 | '^(?!.*\\.(js|jsx|mjs|cjs|ts|tsx|css|json)$)': 'jest-preview/transforms/file'
11 | }
12 | };
13 |
14 | export default config;
--------------------------------------------------------------------------------
/packages/drawer/setup-jest.ts:
--------------------------------------------------------------------------------
1 | import '@testing-library/jest-dom/';
2 |
--------------------------------------------------------------------------------
/packages/drawer/src/components/DrawerTrigger.tsx:
--------------------------------------------------------------------------------
1 | /** @jsxImportSource @emotion/react */
2 | import { Trigger } from '@jdesignlab/react-utils';
3 | import { useContext } from 'react';
4 | import { DrawerContext } from '../context';
5 |
6 | export const DrawerTrigger = (props: any) => {
7 | const { children } = props;
8 | const { id, onOpen } = useContext(DrawerContext);
9 |
10 | return (
11 |
12 | {children}
13 |
14 | );
15 | };
16 |
17 | DrawerTrigger.displayName = 'Drawer.Trigger';
18 |
--------------------------------------------------------------------------------
/packages/drawer/src/constants.ts:
--------------------------------------------------------------------------------
1 | import type { ColorToken } from '@jdesignlab/theme';
2 | import type { DrawerProps } from './types';
3 |
4 | type DrwaerOption = Pick;
5 |
6 | const DEFAULT_OPTIONS: Required = {
7 | open: false,
8 | full: false,
9 | placement: 'left'
10 | };
11 |
12 | const DRAWER_OVERRAY_BACKGROUND: ColorToken = 'shades-black';
13 | const DRAWER_BACKROUND: ColorToken = 'shades-white';
14 | const DRAWER_ID_PREFIX: string = 'jds-drawer';
15 |
16 | export { DEFAULT_OPTIONS, DRAWER_OVERRAY_BACKGROUND, DRAWER_BACKROUND, DRAWER_ID_PREFIX };
17 |
--------------------------------------------------------------------------------
/packages/drawer/src/context.ts:
--------------------------------------------------------------------------------
1 | import { createContext } from 'react';
2 | import { DrawerContextProps } from './types';
3 |
4 | export const defaultContextValues: DrawerContextProps = {
5 | id: '',
6 | isOpen: false,
7 | onOpen: () => {},
8 | onClose: () => {},
9 | hasCloseIcon: true,
10 | disableOverlayClose: false,
11 | placement: 'right',
12 | full: false
13 | };
14 |
15 | export const DrawerContext = createContext(defaultContextValues);
16 |
--------------------------------------------------------------------------------
/packages/drawer/src/hooks/useToggleLayer.ts:
--------------------------------------------------------------------------------
1 | import { useCallback, useEffect, useState } from 'react';
2 |
3 | export const useToggleLayer = (
4 | openProp: boolean | undefined,
5 | onOpenProp: (() => void) | undefined,
6 | onCloseProp: (() => void) | undefined
7 | ) => {
8 | const [isOpen, setIsOpen] = useState(!!openProp);
9 | const isControlled = openProp !== undefined;
10 |
11 | useEffect(() => {
12 | setIsOpen(!!openProp);
13 | }, [openProp]);
14 |
15 | const onToggle = () => {
16 | setIsOpen(prev => !prev);
17 | if (isOpen) onCloseProp?.();
18 | else onOpenProp?.();
19 | };
20 |
21 | const onOpen = () => {
22 | isControlled ? onOpenProp?.() : onToggle();
23 | };
24 |
25 | const onClose = () => {
26 | isControlled ? onCloseProp?.() : onToggle();
27 | };
28 |
29 | return { isOpen, onOpen, onClose };
30 | };
31 |
--------------------------------------------------------------------------------
/packages/drawer/src/index.ts:
--------------------------------------------------------------------------------
1 | export * from '../src/components/Drawer';
2 |
--------------------------------------------------------------------------------
/packages/drawer/src/types.ts:
--------------------------------------------------------------------------------
1 | export type Placement = 'top' | 'right' | 'bottom' | 'left';
2 |
3 | export interface DrawerContextProps {
4 | id: string;
5 | isOpen: boolean;
6 | onOpen(): void;
7 | onClose(): void;
8 | hasCloseIcon: boolean;
9 | disableOverlayClose: boolean;
10 | placement: Placement;
11 | full: boolean;
12 | }
13 |
14 | export interface DrawerProps {
15 | children?: React.ReactNode;
16 | open?: boolean;
17 | onOpen?: () => void;
18 | onClose?: () => void;
19 | hasCloseIcon?: boolean;
20 | disableOverlayClose?: boolean;
21 | placement?: Placement;
22 | full?: boolean;
23 | }
24 |
25 | export interface DrawerTriggerProps {
26 | children?: React.ReactNode;
27 | onClick?: () => void;
28 | }
29 |
--------------------------------------------------------------------------------
/packages/drawer/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tsconfig.json",
3 | "include": ["./src"],
4 | "compilerOptions": {
5 | "declaration": true,
6 | "isolatedModules": false,
7 | "esModuleInterop": true, // es module이 아니어도 import export 쓸 수 있게 함
8 | "importHelpers": true,
9 | "types": ["@emotion/react/types/css-prop", "@types/jest", "@testing-library/jest-dom"],
10 | "jsx": "react-jsx",
11 | "jsxImportSource": "@emotion/react"
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/packages/dropdown/jest.config.ts:
--------------------------------------------------------------------------------
1 | import type { Config } from 'jest';
2 |
3 | const config: Config = {
4 | preset: 'ts-jest',
5 | testEnvironment: 'jsdom',
6 | setupFilesAfterEnv: ['/setup-jest.ts'],
7 | transform: {
8 | '^.+\\.[jt]sx?$': 'ts-jest',
9 | '^.+\\.(css|scss|sass|less)$': 'jest-preview/transforms/css',
10 | '^(?!.*\\.(js|jsx|mjs|cjs|ts|tsx|css|json)$)': 'jest-preview/transforms/file'
11 | }
12 | };
13 |
14 | export default config;
--------------------------------------------------------------------------------
/packages/dropdown/setup-jest.ts:
--------------------------------------------------------------------------------
1 | import '@testing-library/jest-dom/';
2 |
--------------------------------------------------------------------------------
/packages/dropdown/src/components/DropdownDivider.tsx:
--------------------------------------------------------------------------------
1 | /** @jsxImportSource @emotion/react */
2 |
3 | import { dropdownDividerStyle } from '../style';
4 |
5 | export const Divider = () => {
6 | return ;
7 | };
8 |
9 | Divider.displayName = 'Dropdown.Divider'
--------------------------------------------------------------------------------
/packages/dropdown/src/constants.ts:
--------------------------------------------------------------------------------
1 | /** DOM */
2 | export const DROPDOWN_ROLE_QUERY = "[role='menu']";
3 | export const NOT_DISABLED_DROPDOWN_MENU_QUERY = '.menu_item:not([disabled])';
4 | export const NOT_DISABLED_DROPDOWN_SUB_ITEM_QUERY = '.menu_item:not([disabled])';
5 | export const DROPDOWN_MENU_WRAPPER_CLASS = '.menu_wrapper';
6 | export const DROPDOWN_MENU_OPEN_CLASS_NAME = 'menu_open';
7 |
--------------------------------------------------------------------------------
/packages/dropdown/src/context.ts:
--------------------------------------------------------------------------------
1 | import { createContext } from 'react';
2 |
3 | export const DropdownContext = createContext({
4 | width: 0,
5 | placement: 'top',
6 | triggerWidth: 0,
7 | setTriggerWidth: (w: any) => {},
8 | triggerHeight: 0,
9 | setTriggerHeight: (h: any) => {},
10 | gap: 0
11 | });
12 |
13 | export const DropdownSubContext = createContext({
14 | subOpen: false,
15 | setSubOpen: (value: boolean) => {}
16 | });
17 |
--------------------------------------------------------------------------------
/packages/dropdown/src/hooks/useCloseKeyDown.ts:
--------------------------------------------------------------------------------
1 | import React, { useContext, useCallback, RefObject } from 'react';
2 | import { useToggleOpen } from './useToggleOpen';
3 |
4 | const useCloseKeyDown = () => (event: React.KeyboardEvent) => {
5 | const el = event.currentTarget;
6 | switch (event.key) {
7 | case 'Escape':
8 | case 'Esc':
9 | event.preventDefault();
10 | useToggleOpen(el);
11 | return;
12 | }
13 | };
14 |
15 | export default useCloseKeyDown;
16 |
--------------------------------------------------------------------------------
/packages/dropdown/src/hooks/useKeyboardHandler.ts:
--------------------------------------------------------------------------------
1 | import type { Dispatch, SetStateAction } from 'react';
2 | import { spaceKeyToggleHandler, arrowKeyNavigationHandler } from '@jdesignlab/react-utils';
3 | import { useSelectItem } from './useSelectItem';
4 |
5 | export const useKeyboardHandler = (props: {
6 | event: React.KeyboardEvent;
7 | parentScope: string;
8 | selectorOfList: string;
9 | state?: boolean;
10 | setState?: Dispatch>;
11 | onClick?: () => void;
12 | }) => {
13 | const { event, parentScope, selectorOfList, setState, onClick } = props;
14 | if (event.key === 'Enter' && onClick) {
15 | useSelectItem(event, onClick);
16 | }
17 | spaceKeyToggleHandler({ event, setState });
18 | arrowKeyNavigationHandler({ event, parentScope, selectorOfList });
19 | };
20 |
--------------------------------------------------------------------------------
/packages/dropdown/src/hooks/useOpenKeyDown.ts:
--------------------------------------------------------------------------------
1 | import type { Dispatch, SetStateAction } from 'react';
2 | import React, { useContext, useCallback, RefObject } from 'react';
3 | import { useToggleOpen } from './useToggleOpen';
4 |
5 | const MENU_WRAPPER_SELECTOR = '.menu_wrapper';
6 | const MENU_ITEM_SELECTOR = '.menu_item:not([disabled])';
7 |
8 | const useOpenKeyDown = (event: React.KeyboardEvent) => {
9 | const el = event.currentTarget;
10 | switch (event.key) {
11 | case 'ArrowUp':
12 | case 'ArrowDown':
13 | case 'ArrowLeft':
14 | case 'ArrowRight':
15 | case 'Space':
16 | case ' ':
17 | case 'Enter':
18 | event.preventDefault();
19 | useToggleOpen(el);
20 | const firstItem = el.closest(MENU_WRAPPER_SELECTOR)?.querySelector(MENU_ITEM_SELECTOR);
21 | firstItem?.focus();
22 | }
23 | };
24 |
25 | export default useOpenKeyDown;
26 |
--------------------------------------------------------------------------------
/packages/dropdown/src/hooks/useSelectItem.ts:
--------------------------------------------------------------------------------
1 | import { useToggleOpen } from './useToggleOpen';
2 |
3 | export const useSelectItem = (
4 | event: React.MouseEvent | React.KeyboardEvent,
5 | onClick?: () => void
6 | ) => {
7 | if (onClick) onClick();
8 | useToggleOpen(event.currentTarget);
9 | };
10 |
--------------------------------------------------------------------------------
/packages/dropdown/src/hooks/useToggleOpen.ts:
--------------------------------------------------------------------------------
1 | export const useToggleOpen = (dropdownMenu: HTMLElement) => {
2 | if (dropdownMenu) {
3 | dropdownMenu.classList.toggle('menu_close');
4 | dropdownMenu.classList.toggle('menu_open');
5 | }
6 | };
7 |
--------------------------------------------------------------------------------
/packages/dropdown/src/index.ts:
--------------------------------------------------------------------------------
1 | export * from './components/Dropdown';
2 |
--------------------------------------------------------------------------------
/packages/dropdown/src/types/base.ts:
--------------------------------------------------------------------------------
1 | export type DropdownAnchor = 'top' | 'right' | 'bottom' | 'left';
2 |
--------------------------------------------------------------------------------
/packages/dropdown/src/types/index.ts:
--------------------------------------------------------------------------------
1 | export * from './base';
2 | export * from './props';
3 |
--------------------------------------------------------------------------------
/packages/dropdown/src/types/props.ts:
--------------------------------------------------------------------------------
1 | import { DropdownAnchor } from './base';
2 |
3 | export interface DropdownProps {
4 | children?: React.ReactNode;
5 | width?: number;
6 | placement?: DropdownAnchor;
7 | gap?: number | string;
8 | }
9 |
10 | export interface DropdownTriggerProps {
11 | children?: React.ReactNode;
12 | }
13 |
14 | export interface DropdownSubMenuProps {
15 | children?: React.ReactNode;
16 | }
17 |
18 | export interface DropdownMenuProps {
19 | children?: React.ReactNode;
20 | }
21 |
22 | export interface DropdownMenuItemProps {
23 | children?: React.ReactNode;
24 | disabled?: boolean;
25 | onClick?: () => void;
26 | hasSub?: boolean;
27 | }
28 |
29 | export interface DropdownSubMenuItemProps {
30 | children?: React.ReactNode;
31 | disabled?: boolean;
32 | onClick?: () => void;
33 | }
34 |
--------------------------------------------------------------------------------
/packages/dropdown/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tsconfig.json",
3 | "include": ["./src"],
4 | "compilerOptions": {
5 | "declaration": true,
6 | "isolatedModules": false,
7 | "esModuleInterop": true, // es module이 아니어도 import export 쓸 수 있게 함
8 | "importHelpers": true,
9 | "types": ["@emotion/react/types/css-prop", "@types/jest"],
10 | "jsx": "react-jsx",
11 | "jsxImportSource": "@emotion/react"
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/packages/flex/jest.config.ts:
--------------------------------------------------------------------------------
1 | import type { Config } from 'jest';
2 |
3 | const config: Config = {
4 | preset: 'ts-jest',
5 | testEnvironment: 'jsdom',
6 | setupFilesAfterEnv: ['/setup-jest.ts'],
7 | transform: {
8 | '^.+\\.[jt]sx?$': 'ts-jest',
9 | '^.+\\.(css|scss|sass|less)$': 'jest-preview/transforms/css',
10 | '^(?!.*\\.(js|jsx|mjs|cjs|ts|tsx|css|json)$)': 'jest-preview/transforms/file'
11 | }
12 | };
13 |
14 | export default config;
--------------------------------------------------------------------------------
/packages/flex/setup-jest.ts:
--------------------------------------------------------------------------------
1 | import '@testing-library/jest-dom/';
2 |
--------------------------------------------------------------------------------
/packages/flex/src/components/Flex.tsx:
--------------------------------------------------------------------------------
1 | /** @jsxImportSource @emotion/react */
2 | import { createClassVariant } from '@jdesignlab/theme';
3 | import { containerStyle } from '../styles';
4 | import type { FlexContainerProps } from '../types';
5 | import { FlexItem } from './FlexItem';
6 |
7 | export const Flex = (props: FlexContainerProps) => {
8 | const { children, style, as = 'div', ...otherProps } = props;
9 | const FlexContainer = as;
10 |
11 | return (
12 |
17 | {children}
18 |
19 | );
20 | };
21 |
22 | Flex.Item = FlexItem;
23 | Flex.displayName = 'Flex';
24 |
--------------------------------------------------------------------------------
/packages/flex/src/components/FlexItem.tsx:
--------------------------------------------------------------------------------
1 | /** @jsxImportSource @emotion/react */
2 | import { createClassVariant } from '@jdesignlab/theme';
3 | import { itemStyle } from '../styles';
4 | import type { FlexItemProps } from '../types';
5 |
6 | export const FlexItem = (props: FlexItemProps) => {
7 | const { children, as = 'div', style, flex, self, order, ...otherProps } = props;
8 | const FlexItemComponent = as;
9 |
10 | return (
11 |
16 | {children}
17 |
18 | );
19 | };
20 |
--------------------------------------------------------------------------------
/packages/flex/src/index.ts:
--------------------------------------------------------------------------------
1 | export * from './components/Flex';
2 |
--------------------------------------------------------------------------------
/packages/flex/src/styles.ts:
--------------------------------------------------------------------------------
1 | import { css } from '@emotion/react';
2 | import type { FlexContainerProps, Self } from './types';
3 |
4 | export const containerStyle = (props: FlexContainerProps) => {
5 | return css({
6 | ...props.style,
7 | display: 'flex',
8 | flexDirection: props.direction || 'row',
9 | flexWrap: props.wrap || 'nowrap',
10 | justifyContent: props.justify,
11 | alignItems: props.items,
12 | alignContent: props.content,
13 | gap: props.gap
14 | });
15 | };
16 |
17 | export const itemStyle = (flex?: number, self?: Self, order?: number) => {
18 | return css({
19 | flexGrow: flex,
20 | alignSelf: self,
21 | order: order
22 | });
23 | };
24 |
--------------------------------------------------------------------------------
/packages/flex/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tsconfig.json",
3 | "include": ["./src"],
4 | "compilerOptions": {
5 | "declaration": true,
6 | "isolatedModules": false,
7 | "esModuleInterop": true, // es module이 아니어도 import export 쓸 수 있게 함
8 | "importHelpers": true,
9 | "types": ["@emotion/react/types/css-prop", "@types/jest", "@testing-library/jest-dom"],
10 | "jsx": "react-jsx",
11 | "jsxImportSource": "@emotion/react"
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/packages/icons/.babelrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "presets": ["@babel/env", ["@babel/preset-react", { "runtime": "automatic", "importSource": "@emotion/react" }]],
3 | "plugins": ["@emotion/babel-plugin"]
4 | }
5 |
--------------------------------------------------------------------------------
/packages/icons/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # @jdesignlab/react-icons
2 |
3 | ## 0.7.0
4 |
5 | ### Minor Changes
6 |
7 | - allow to get rest properties
8 |
9 | ## 0.6.0
10 |
11 | ### Minor Changes
12 |
13 | - remove rollup dependency, added icons
14 |
15 | ## 0.5.0
16 |
17 | ### Minor Changes
18 |
19 | - remove clean-package
20 |
21 | ## 0.4.0
22 |
23 | ### Minor Changes
24 |
25 | - change publish config
26 |
27 | ## 0.3.0
28 |
29 | ### Minor Changes
30 |
31 | - minor
32 |
--------------------------------------------------------------------------------
/packages/icons/README.md:
--------------------------------------------------------------------------------
1 | # icons
2 |
--------------------------------------------------------------------------------
/packages/icons/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@jdesignlab/react-icons",
3 | "version": "0.7.0",
4 | "packageManager": "yarn@3.3.1",
5 | "main": "src/index.ts",
6 | "files": [
7 | "dist"
8 | ],
9 | "scripts": {
10 | "build": "tsup src --dts --format esm,cjs",
11 | "build:clean": "rimraf dist/"
12 | },
13 | "devDependencies": {
14 | "@emotion/react": "^11.10.6",
15 | "@types/react": "18.0.27",
16 | "@types/react-dom": "^18.0.10",
17 | "react": "^18.2.0",
18 | "rimraf": "4.1.2",
19 | "tslib": "^2.5.0",
20 | "tsup": "^6.7.0",
21 | "typescript": "^4.9.5"
22 | },
23 | "peerDependencies": {
24 | "@emtoion/react": "~11"
25 | },
26 | "publishConfig": {
27 | "access": "public",
28 | "directory": "_release/package",
29 | "main": "./dist/index.js",
30 | "module": "./dist/index.mjs",
31 | "types": "./dist/index.d.ts"
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/packages/icons/src/components/Activity.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | export const Activity = (props: React.SVGProps) => {
4 | return (
5 |
19 | );
20 | };
21 |
--------------------------------------------------------------------------------
/packages/icons/src/components/Alert.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | export const Alert = (props: React.SVGProps) => {
3 | return (
4 |
18 | );
19 | };
20 |
--------------------------------------------------------------------------------
/packages/icons/src/components/Archive.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | export const Archive = (props: React.SVGProps) => {
4 | return (
5 |
19 | );
20 | };
21 |
--------------------------------------------------------------------------------
/packages/icons/src/components/ArrowBottom.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | export const ArrowBottom = (props: React.SVGProps) => {
4 | return (
5 |
20 | );
21 | };
22 |
--------------------------------------------------------------------------------
/packages/icons/src/components/ArrowLeft.tsx:
--------------------------------------------------------------------------------
1 | export const ArrowLeft = (props: React.SVGProps) => {
2 | return (
3 |
17 | );
18 | };
19 |
--------------------------------------------------------------------------------
/packages/icons/src/components/ArrowRight.tsx:
--------------------------------------------------------------------------------
1 | export const ArrowRight = (props: React.SVGProps) => {
2 | return (
3 |
17 | );
18 | };
19 |
--------------------------------------------------------------------------------
/packages/icons/src/components/ArrowTop.tsx:
--------------------------------------------------------------------------------
1 | export const ArrowTop = (props: React.SVGProps) => {
2 | return (
3 |
17 | );
18 | };
19 |
--------------------------------------------------------------------------------
/packages/icons/src/components/BackWards.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | export const BackWards = (props: React.SVGProps) => {
3 | return (
4 |
17 | );
18 | };
19 |
--------------------------------------------------------------------------------
/packages/icons/src/components/Bag.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | export const Bag = (props: React.SVGProps) => {
3 | return (
4 |
17 | );
18 | };
19 |
--------------------------------------------------------------------------------
/packages/icons/src/components/Ban.tsx:
--------------------------------------------------------------------------------
1 | export const Ban = (props: React.SVGProps) => {
2 | return (
3 |
18 | );
19 | };
20 |
--------------------------------------------------------------------------------
/packages/icons/src/components/Bell.tsx:
--------------------------------------------------------------------------------
1 | export const Bell = (props: React.SVGProps) => {
2 | return (
3 |
17 | );
18 | };
19 |
--------------------------------------------------------------------------------
/packages/icons/src/components/Book.tsx:
--------------------------------------------------------------------------------
1 | export const Book = (props: React.SVGProps) => {
2 | return (
3 |
17 | );
18 | };
19 |
--------------------------------------------------------------------------------
/packages/icons/src/components/Bookmark.tsx:
--------------------------------------------------------------------------------
1 | export const Bookmark = (props: React.SVGProps) => {
2 | return (
3 |
17 | );
18 | };
19 |
--------------------------------------------------------------------------------
/packages/icons/src/components/Calendar.tsx:
--------------------------------------------------------------------------------
1 | export const Calendar = (props: React.SVGProps) => {
2 | return (
3 |
17 | );
18 | };
19 |
--------------------------------------------------------------------------------
/packages/icons/src/components/Camera.tsx:
--------------------------------------------------------------------------------
1 | export const Camera = (props: React.SVGProps) => {
2 | return (
3 |
18 | );
19 | };
20 |
--------------------------------------------------------------------------------
/packages/icons/src/components/CaretBottom.tsx:
--------------------------------------------------------------------------------
1 | export const CaretBottom = (props: React.SVGProps) => {
2 | return (
3 |
17 | );
18 | };
19 |
--------------------------------------------------------------------------------
/packages/icons/src/components/CaretLeft.tsx:
--------------------------------------------------------------------------------
1 | export const CaretLeft = (props: React.SVGProps) => {
2 | return (
3 |
17 | );
18 | };
19 |
--------------------------------------------------------------------------------
/packages/icons/src/components/CaretRight.tsx:
--------------------------------------------------------------------------------
1 | export const CaretRight = (props: React.SVGProps) => {
2 | return (
3 |
17 | );
18 | };
19 |
--------------------------------------------------------------------------------
/packages/icons/src/components/CaretTop.tsx:
--------------------------------------------------------------------------------
1 | export const CaretTop = (props: React.SVGProps) => {
2 | return (
3 |
17 | );
18 | };
19 |
--------------------------------------------------------------------------------
/packages/icons/src/components/Cart.tsx:
--------------------------------------------------------------------------------
1 | export const Cart = (props: React.SVGProps) => {
2 | return (
3 |
22 | );
23 | };
24 |
--------------------------------------------------------------------------------
/packages/icons/src/components/Checkmark.tsx:
--------------------------------------------------------------------------------
1 | export const Checkmark = (props: React.SVGProps) => {
2 | return (
3 |
17 | );
18 | };
19 |
--------------------------------------------------------------------------------
/packages/icons/src/components/ChevronBottom.tsx:
--------------------------------------------------------------------------------
1 | export const ChevronBottom = (props: React.SVGProps) => {
2 | return (
3 |
17 | );
18 | };
19 |
--------------------------------------------------------------------------------
/packages/icons/src/components/ChevronLeft.tsx:
--------------------------------------------------------------------------------
1 | export const ChevronLeft = (props: React.SVGProps) => {
2 | return (
3 |
17 | );
18 | };
19 |
--------------------------------------------------------------------------------
/packages/icons/src/components/ChevronRight.tsx:
--------------------------------------------------------------------------------
1 | export const ChevronRight = (props: React.SVGProps) => {
2 | return (
3 |
17 | );
18 | };
19 |
--------------------------------------------------------------------------------
/packages/icons/src/components/ChevronTop.tsx:
--------------------------------------------------------------------------------
1 | export const ChevronTop = (props: React.SVGProps) => {
2 | return (
3 |
17 | );
18 | };
19 |
--------------------------------------------------------------------------------
/packages/icons/src/components/Clipboard.tsx:
--------------------------------------------------------------------------------
1 | export const Clipboard = (props: React.SVGProps) => {
2 | return (
3 |
18 | );
19 | };
20 |
--------------------------------------------------------------------------------
/packages/icons/src/components/Clock.tsx:
--------------------------------------------------------------------------------
1 | export const Clock = (props: React.SVGProps) => {
2 | return (
3 |
18 | );
19 | };
20 |
--------------------------------------------------------------------------------
/packages/icons/src/components/Close.tsx:
--------------------------------------------------------------------------------
1 | export const Close = (props: React.SVGProps) => {
2 | return (
3 |
17 | );
18 | };
19 |
--------------------------------------------------------------------------------
/packages/icons/src/components/Code.tsx:
--------------------------------------------------------------------------------
1 | export const Code = (props: React.SVGProps) => {
2 | return (
3 |
19 | );
20 | };
21 |
--------------------------------------------------------------------------------
/packages/icons/src/components/Compose.tsx:
--------------------------------------------------------------------------------
1 | export const Compose = (props: React.SVGProps) => {
2 | return (
3 |
19 | );
20 | };
21 |
--------------------------------------------------------------------------------
/packages/icons/src/components/Creditcard.tsx:
--------------------------------------------------------------------------------
1 | export const Creditcard = (props: React.SVGProps) => {
2 | return (
3 |
18 | );
19 | };
20 |
--------------------------------------------------------------------------------
/packages/icons/src/components/Desktop.tsx:
--------------------------------------------------------------------------------
1 | export const Desktop = (props: React.SVGProps) => {
2 | return (
3 |
17 | );
18 | };
19 |
--------------------------------------------------------------------------------
/packages/icons/src/components/Download.tsx:
--------------------------------------------------------------------------------
1 | export const Download = (props: React.SVGProps) => {
2 | return (
3 |
19 | );
20 | };
21 |
--------------------------------------------------------------------------------
/packages/icons/src/components/Edit.tsx:
--------------------------------------------------------------------------------
1 | export const Edit = (props: React.SVGProps) => {
2 | return (
3 |
17 | );
18 | };
19 |
--------------------------------------------------------------------------------
/packages/icons/src/components/Eject.tsx:
--------------------------------------------------------------------------------
1 | export const Eject = (props: React.SVGProps) => {
2 | return (
3 |
17 | );
18 | };
19 |
--------------------------------------------------------------------------------
/packages/icons/src/components/EllipsisHorizontal.tsx:
--------------------------------------------------------------------------------
1 | export const EllipsisHorizontal = (props: React.SVGProps) => {
2 | return (
3 |
19 | );
20 | };
21 |
--------------------------------------------------------------------------------
/packages/icons/src/components/EllipsisVertical.tsx:
--------------------------------------------------------------------------------
1 | export const EllipsisVertical = (props: React.SVGProps) => {
2 | return (
3 |
19 | );
20 | };
21 |
--------------------------------------------------------------------------------
/packages/icons/src/components/End.tsx:
--------------------------------------------------------------------------------
1 | export const End = (props: React.SVGProps) => {
2 | return (
3 |
17 | );
18 | };
19 |
--------------------------------------------------------------------------------
/packages/icons/src/components/Export.tsx:
--------------------------------------------------------------------------------
1 | export const Export = (props: React.SVGProps) => {
2 | return (
3 |
19 | );
20 | };
21 |
--------------------------------------------------------------------------------
/packages/icons/src/components/External.tsx:
--------------------------------------------------------------------------------
1 | export const External = (props: React.SVGProps) => {
2 | return (
3 |
19 | );
20 | };
21 |
--------------------------------------------------------------------------------
/packages/icons/src/components/Eye.tsx:
--------------------------------------------------------------------------------
1 | export const Eye = (props: React.SVGProps) => {
2 | return (
3 |
19 | );
20 | };
21 |
--------------------------------------------------------------------------------
/packages/icons/src/components/Feed.tsx:
--------------------------------------------------------------------------------
1 | export const Feed = (props: React.SVGProps) => {
2 | return (
3 |
19 | );
20 | };
21 |
--------------------------------------------------------------------------------
/packages/icons/src/components/File.tsx:
--------------------------------------------------------------------------------
1 | export const File = (props: React.SVGProps) => {
2 | return (
3 |
17 | );
18 | };
19 |
--------------------------------------------------------------------------------
/packages/icons/src/components/Filter.tsx:
--------------------------------------------------------------------------------
1 | export const Filter = (props: React.SVGProps) => {
2 | return (
3 |
17 | );
18 | };
19 |
--------------------------------------------------------------------------------
/packages/icons/src/components/Flag.tsx:
--------------------------------------------------------------------------------
1 | export const Flag = (props: React.SVGProps) => {
2 | return (
3 |
17 | );
18 | };
19 |
--------------------------------------------------------------------------------
/packages/icons/src/components/Folder.tsx:
--------------------------------------------------------------------------------
1 | export const Folder = (props: React.SVGProps) => {
2 | return (
3 |
18 | );
19 | };
20 |
--------------------------------------------------------------------------------
/packages/icons/src/components/FolderOpen.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | export const FolderOpen = (props: React.SVGProps) => {
3 | return (
4 |
18 | );
19 | };
20 |
--------------------------------------------------------------------------------
/packages/icons/src/components/Forwards.tsx:
--------------------------------------------------------------------------------
1 | export const Forwards = (props: React.SVGProps) => {
2 | return (
3 |
17 | );
18 | };
19 |
--------------------------------------------------------------------------------
/packages/icons/src/components/Fullscreen.tsx:
--------------------------------------------------------------------------------
1 | export const Fullscreen = (props: React.SVGProps) => {
2 | return (
3 |
20 | );
21 | };
22 |
--------------------------------------------------------------------------------
/packages/icons/src/components/FullscreenExit.tsx:
--------------------------------------------------------------------------------
1 | export const FullscreenExit = (props: React.SVGProps) => {
2 | return (
3 |
20 | );
21 | };
22 |
--------------------------------------------------------------------------------
/packages/icons/src/components/Gift.tsx:
--------------------------------------------------------------------------------
1 | export const Gift = (props: React.SVGProps) => {
2 | return (
3 |
17 | );
18 | };
19 |
--------------------------------------------------------------------------------
/packages/icons/src/components/Github.tsx:
--------------------------------------------------------------------------------
1 | export const Github = (props: React.SVGProps) => {
2 | return (
3 |
6 | );
7 | };
8 |
--------------------------------------------------------------------------------
/packages/icons/src/components/Heart.tsx:
--------------------------------------------------------------------------------
1 | export const Heart = (props: React.SVGProps) => {
2 | return (
3 |
17 | );
18 | };
19 |
--------------------------------------------------------------------------------
/packages/icons/src/components/Home.tsx:
--------------------------------------------------------------------------------
1 | export const Home = (props: React.SVGProps) => {
2 | return (
3 |
17 | );
18 | };
19 |
--------------------------------------------------------------------------------
/packages/icons/src/components/Import.tsx:
--------------------------------------------------------------------------------
1 | export const Import = (props: React.SVGProps) => {
2 | return (
3 |
19 | );
20 | };
21 |
--------------------------------------------------------------------------------
/packages/icons/src/components/Inbox.tsx:
--------------------------------------------------------------------------------
1 | export const Inbox = (props: React.SVGProps) => {
2 | return (
3 |
17 | );
18 | };
19 |
--------------------------------------------------------------------------------
/packages/icons/src/components/Info.tsx:
--------------------------------------------------------------------------------
1 | export const Info = (props: React.SVGProps) => {
2 | return (
3 |
18 | );
19 | };
20 |
--------------------------------------------------------------------------------
/packages/icons/src/components/Lightning.tsx:
--------------------------------------------------------------------------------
1 | export const Lightning = (props: React.SVGProps) => {
2 | return (
3 |
17 | );
18 | };
19 |
--------------------------------------------------------------------------------
/packages/icons/src/components/Link.tsx:
--------------------------------------------------------------------------------
1 | export const Link = (props: React.SVGProps) => {
2 | return (
3 |
18 | );
19 | };
20 |
--------------------------------------------------------------------------------
/packages/icons/src/components/Location.tsx:
--------------------------------------------------------------------------------
1 | export const Location = (props: React.SVGProps) => {
2 | return (
3 |
18 | );
19 | };
20 |
--------------------------------------------------------------------------------
/packages/icons/src/components/Lock.tsx:
--------------------------------------------------------------------------------
1 | export const Lock = (props: React.SVGProps) => {
2 | return (
3 |
19 | );
20 | };
21 |
--------------------------------------------------------------------------------
/packages/icons/src/components/Mail.tsx:
--------------------------------------------------------------------------------
1 | export const Mail = (props: React.SVGProps) => {
2 | return (
3 |
17 | );
18 | };
19 |
--------------------------------------------------------------------------------
/packages/icons/src/components/Menu.tsx:
--------------------------------------------------------------------------------
1 | export const Menu = (props: React.SVGProps) => {
2 | return (
3 |
17 | );
18 | };
19 |
--------------------------------------------------------------------------------
/packages/icons/src/components/Message.tsx:
--------------------------------------------------------------------------------
1 | export const Message = (props: React.SVGProps) => {
2 | return (
3 |
17 | );
18 | };
19 |
--------------------------------------------------------------------------------
/packages/icons/src/components/Microphone.tsx:
--------------------------------------------------------------------------------
1 | export const Microphone = (props: React.SVGProps) => {
2 | return (
3 |
20 | );
21 | };
22 |
--------------------------------------------------------------------------------
/packages/icons/src/components/Minus.tsx:
--------------------------------------------------------------------------------
1 | export const Minus = (props: React.SVGProps) => {
2 | return (
3 |
17 | );
18 | };
19 |
--------------------------------------------------------------------------------
/packages/icons/src/components/Mobile.tsx:
--------------------------------------------------------------------------------
1 | export const Mobile = (props: React.SVGProps) => {
2 | return (
3 |
17 | );
18 | };
19 |
--------------------------------------------------------------------------------
/packages/icons/src/components/Moon.tsx:
--------------------------------------------------------------------------------
1 | export const Moon = (props: React.SVGProps) => {
2 | return (
3 |
17 | );
18 | };
19 |
--------------------------------------------------------------------------------
/packages/icons/src/components/Move.tsx:
--------------------------------------------------------------------------------
1 | export const Move = (props: React.SVGProps) => {
2 | return (
3 |
22 | );
23 | };
24 |
--------------------------------------------------------------------------------
/packages/icons/src/components/Music.tsx:
--------------------------------------------------------------------------------
1 | export const Music = (props: React.SVGProps) => {
2 | return (
3 |
20 | );
21 | };
22 |
--------------------------------------------------------------------------------
/packages/icons/src/components/Mute.tsx:
--------------------------------------------------------------------------------
1 | export const Mute = (props: React.SVGProps) => {
2 | return (
3 |
17 | );
18 | };
19 |
--------------------------------------------------------------------------------
/packages/icons/src/components/Options.tsx:
--------------------------------------------------------------------------------
1 | export const Options = (props: React.SVGProps) => {
2 | return (
3 |
17 | );
18 | };
19 |
--------------------------------------------------------------------------------
/packages/icons/src/components/Paperclip.tsx:
--------------------------------------------------------------------------------
1 | export const Paperclip = (props: React.SVGProps) => {
2 | return (
3 |
17 | );
18 | };
19 |
--------------------------------------------------------------------------------
/packages/icons/src/components/Pause.tsx:
--------------------------------------------------------------------------------
1 | export const Pause = (props: React.SVGProps) => {
2 | return (
3 |
17 | );
18 | };
19 |
--------------------------------------------------------------------------------
/packages/icons/src/components/Photo.tsx:
--------------------------------------------------------------------------------
1 | export const Photo = (props: React.SVGProps) => {
2 | return (
3 |
20 | );
21 | };
22 |
--------------------------------------------------------------------------------
/packages/icons/src/components/Play.tsx:
--------------------------------------------------------------------------------
1 | export const Play = (props: React.SVGProps) => {
2 | return (
3 |
17 | );
18 | };
19 |
--------------------------------------------------------------------------------
/packages/icons/src/components/Plus.tsx:
--------------------------------------------------------------------------------
1 | export const Plus = (props: React.SVGProps) => {
2 | return (
3 |
17 | );
18 | };
19 |
--------------------------------------------------------------------------------
/packages/icons/src/components/Portfolio.tsx:
--------------------------------------------------------------------------------
1 | export const Portfolio = (props: React.SVGProps) => {
2 | return (
3 |
21 | );
22 | };
23 |
--------------------------------------------------------------------------------
/packages/icons/src/components/Print.tsx:
--------------------------------------------------------------------------------
1 | export const Print = (props: React.SVGProps) => {
2 | return (
3 |
20 | );
21 | };
22 |
--------------------------------------------------------------------------------
/packages/icons/src/components/Reload.tsx:
--------------------------------------------------------------------------------
1 | export const Reload = (props: React.SVGProps) => {
2 | return (
3 |
18 | );
19 | };
20 |
--------------------------------------------------------------------------------
/packages/icons/src/components/Reply.tsx:
--------------------------------------------------------------------------------
1 | export const Reply = (props: React.SVGProps) => {
2 | return (
3 |
18 | );
19 | };
20 |
--------------------------------------------------------------------------------
/packages/icons/src/components/Search.tsx:
--------------------------------------------------------------------------------
1 | export const Search = (props: React.SVGProps) => {
2 | return (
3 |
18 | );
19 | };
20 |
--------------------------------------------------------------------------------
/packages/icons/src/components/Send.tsx:
--------------------------------------------------------------------------------
1 | export const Send = (props: React.SVGProps) => {
2 | return (
3 |
17 | );
18 | };
19 |
--------------------------------------------------------------------------------
/packages/icons/src/components/Settings.tsx:
--------------------------------------------------------------------------------
1 | export const Settings = (props: React.SVGProps) => {
2 | return (
3 |
18 | );
19 | };
20 |
--------------------------------------------------------------------------------
/packages/icons/src/components/SignIn.tsx:
--------------------------------------------------------------------------------
1 | export const SignIn = (props: React.SVGProps) => {
2 | return (
3 |
19 | );
20 | };
21 |
--------------------------------------------------------------------------------
/packages/icons/src/components/SignOut.tsx:
--------------------------------------------------------------------------------
1 | export const SignOut = (props: React.SVGProps) => {
2 | return (
3 |
19 | );
20 | };
21 |
--------------------------------------------------------------------------------
/packages/icons/src/components/Star.tsx:
--------------------------------------------------------------------------------
1 | export const Star = (props: React.SVGProps) => {
2 | return (
3 |
17 | );
18 | };
19 |
--------------------------------------------------------------------------------
/packages/icons/src/components/Start.tsx:
--------------------------------------------------------------------------------
1 | export const Start = (props: React.SVGProps) => {
2 | return (
3 |
17 | );
18 | };
19 |
--------------------------------------------------------------------------------
/packages/icons/src/components/Tag.tsx:
--------------------------------------------------------------------------------
1 | export const Tag = (props: React.SVGProps) => {
2 | return (
3 |
18 | );
19 | };
20 |
--------------------------------------------------------------------------------
/packages/icons/src/components/Telephone.tsx:
--------------------------------------------------------------------------------
1 | export const Telephone = (props: React.SVGProps) => {
2 | return (
3 |
18 | );
19 | };
20 |
--------------------------------------------------------------------------------
/packages/icons/src/components/Trash.tsx:
--------------------------------------------------------------------------------
1 | export const Trash = (props: React.SVGProps) => {
2 | return (
3 |
17 | );
18 | };
19 |
--------------------------------------------------------------------------------
/packages/icons/src/components/Twitter.tsx:
--------------------------------------------------------------------------------
1 | export const Twitter = (props: React.SVGProps) => {
2 | return (
3 |
6 | );
7 | };
8 |
--------------------------------------------------------------------------------
/packages/icons/src/components/Unlock.tsx:
--------------------------------------------------------------------------------
1 | export const Unlock = (props: React.SVGProps) => {
2 | return (
3 |
19 | );
20 | };
21 |
--------------------------------------------------------------------------------
/packages/icons/src/components/Upload.tsx:
--------------------------------------------------------------------------------
1 | export const Upload = (props: React.SVGProps) => {
2 | return (
3 |
19 | );
20 | };
21 |
--------------------------------------------------------------------------------
/packages/icons/src/components/User.tsx:
--------------------------------------------------------------------------------
1 | export const User = (props: React.SVGProps) => {
2 | return (
3 |
17 | );
18 | };
19 |
--------------------------------------------------------------------------------
/packages/icons/src/components/Video.tsx:
--------------------------------------------------------------------------------
1 | export const Video = (props: React.SVGProps) => {
2 | return (
3 |
17 | );
18 | };
19 |
--------------------------------------------------------------------------------
/packages/icons/src/components/Volume.tsx:
--------------------------------------------------------------------------------
1 | export const Volume = (props: React.SVGProps) => {
2 | return (
3 |
19 | );
20 | };
21 |
--------------------------------------------------------------------------------
/packages/icons/src/components/Work.tsx:
--------------------------------------------------------------------------------
1 | export const Work = (props: React.SVGProps) => {
2 | return (
3 |
17 | );
18 | };
19 |
--------------------------------------------------------------------------------
/packages/icons/src/components/ZoomIn.tsx:
--------------------------------------------------------------------------------
1 | export const ZoomIn = (props: React.SVGProps) => {
2 | return (
3 |
19 | );
20 | };
21 |
--------------------------------------------------------------------------------
/packages/icons/src/components/ZoomOut.tsx:
--------------------------------------------------------------------------------
1 | export const ZoomOut = (props: React.SVGProps) => {
2 | return (
3 |
19 | );
20 | };
21 |
--------------------------------------------------------------------------------
/packages/icons/src/components/ZoomReset.tsx:
--------------------------------------------------------------------------------
1 | export const ZoomReset = (props: React.SVGProps) => {
2 | return (
3 |
22 | );
23 | };
24 |
--------------------------------------------------------------------------------
/packages/icons/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tsconfig.json",
3 | "include": ["./src"],
4 | "compilerOptions": {
5 | "declaration": true,
6 | "isolatedModules": false,
7 | "esModuleInterop": true, // es module이 아니어도 import export 쓸 수 있게 함
8 | "importHelpers": true,
9 | "jsx": "react-jsx"
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/packages/input/jest.config.ts:
--------------------------------------------------------------------------------
1 | import type { Config } from 'jest';
2 |
3 | const config: Config = {
4 | preset: 'ts-jest',
5 | testEnvironment: 'jsdom',
6 | setupFilesAfterEnv: ['/setup-jest.ts'],
7 | transform: {
8 | '^.+\\.[jt]sx?$': 'ts-jest',
9 | '^.+\\.(css|scss|sass|less)$': 'jest-preview/transforms/css',
10 | '^(?!.*\\.(js|jsx|mjs|cjs|ts|tsx|css|json)$)': 'jest-preview/transforms/file'
11 | }
12 | };
13 |
14 | export default config;
--------------------------------------------------------------------------------
/packages/input/setup-jest.ts:
--------------------------------------------------------------------------------
1 | import '@testing-library/jest-dom/';
2 |
--------------------------------------------------------------------------------
/packages/input/src/components/InputLabel.tsx:
--------------------------------------------------------------------------------
1 | /** @jsxImportSource @emotion/react */
2 | import type { InputLabelProps } from '../types';
3 | import { useContext } from 'react';
4 | import { inputLabelStyle } from '../styles';
5 | import { InputContext } from '../context';
6 | import { createClassVariant } from '@jdesignlab/theme';
7 | import { combineClassNames } from '@jdesignlab/utils';
8 |
9 | export const Label = (props: InputLabelProps) => {
10 | const { id } = useContext(InputContext);
11 | const { children, className, ...otherProps } = props;
12 |
13 | return (
14 |
22 | );
23 | };
24 |
25 | Label.displayName = 'TextInput.Label';
26 |
--------------------------------------------------------------------------------
/packages/input/src/components/InputMessage.tsx:
--------------------------------------------------------------------------------
1 | /** @jsxImportSource @emotion/react */
2 | import type { InputMessageProps } from '../types';
3 | import { inputMessageStyle } from '../styles';
4 | import { createClassVariant } from '@jdesignlab/theme';
5 | import { combineClassNames } from '@jdesignlab/utils';
6 |
7 | export const Message = (props: InputMessageProps) => {
8 | const { className, consistent, ...otherProps } = props;
9 |
10 | return (
11 |
16 | {props.children}
17 |
18 | );
19 | };
20 |
21 | Message.displayName = 'TextInput.Message';
22 |
--------------------------------------------------------------------------------
/packages/input/src/constants.ts:
--------------------------------------------------------------------------------
1 | export const VISIBLE_ICON_CLASSNAME = 'input_visible_icon';
2 | export const CLEARABLE_ICON_CLASSNAME = 'input_clearable_icon';
3 |
--------------------------------------------------------------------------------
/packages/input/src/context.ts:
--------------------------------------------------------------------------------
1 | import { createContext } from 'react';
2 |
3 | export const InputContext = createContext({
4 | id: '',
5 | clearable: false
6 | });
7 |
--------------------------------------------------------------------------------
/packages/input/src/index.ts:
--------------------------------------------------------------------------------
1 | export * from './components/TextInput';
2 |
--------------------------------------------------------------------------------
/packages/input/src/types.ts:
--------------------------------------------------------------------------------
1 | import { ThemePreset } from '@jdesignlab/j-provider';
2 | import type { ColorToken } from '@jdesignlab/theme';
3 |
4 | export type InputSize = 'sm' | 'md' | 'lg';
5 |
6 | export interface InputProps extends Omit, 'size' | 'type'> {
7 | children?: React.ReactElement | React.ReactElement[];
8 | type?: 'text' | 'password';
9 | className?: string;
10 | size?: InputSize;
11 | clearable?: boolean;
12 | width?: number;
13 | maxLength?: number;
14 | icon?: JSX.Element;
15 | }
16 |
17 | export interface InputLabelProps {
18 | children?: string;
19 | className?: string;
20 | }
21 |
22 | export interface InputMessageProps {
23 | children?: string;
24 | className?: string;
25 | consistent?: boolean;
26 | }
27 |
28 | export interface InputStyleProps {
29 | themePreset: ThemePreset;
30 | size: InputSize;
31 | hasLabel: boolean;
32 | hasIcon: boolean;
33 | full?: boolean;
34 | width?: number;
35 | clearable?: boolean;
36 | type?: 'text' | 'password';
37 | color?: ColorToken;
38 | }
39 |
--------------------------------------------------------------------------------
/packages/input/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tsconfig.json",
3 | "include": ["./src"],
4 | "compilerOptions": {
5 | "declaration": true,
6 | "isolatedModules": false,
7 | "esModuleInterop": true, // es module이 아니어도 import export 쓸 수 있게 함
8 | "importHelpers": true,
9 | "types": ["@emotion/react/types/css-prop", "@types/jest", "@testing-library/jest-dom"],
10 | "jsx": "react-jsx",
11 | "jsxImportSource": "@emotion/react"
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/packages/j-provider/README.md:
--------------------------------------------------------------------------------
1 | # j-provider
2 |
--------------------------------------------------------------------------------
/packages/j-provider/public/fonts/NotoSansKR-Black-Alphabetic.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DesignSystemLab/design-system/b47e12d874498c1c44be23f41eda33f956311c16/packages/j-provider/public/fonts/NotoSansKR-Black-Alphabetic.woff2
--------------------------------------------------------------------------------
/packages/j-provider/public/fonts/NotoSansKR-Bold-Alphabetic.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DesignSystemLab/design-system/b47e12d874498c1c44be23f41eda33f956311c16/packages/j-provider/public/fonts/NotoSansKR-Bold-Alphabetic.woff2
--------------------------------------------------------------------------------
/packages/j-provider/public/fonts/NotoSansKR-Light-Alphabetic.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DesignSystemLab/design-system/b47e12d874498c1c44be23f41eda33f956311c16/packages/j-provider/public/fonts/NotoSansKR-Light-Alphabetic.woff2
--------------------------------------------------------------------------------
/packages/j-provider/public/fonts/NotoSansKR-Medium-Alphabetic.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DesignSystemLab/design-system/b47e12d874498c1c44be23f41eda33f956311c16/packages/j-provider/public/fonts/NotoSansKR-Medium-Alphabetic.woff2
--------------------------------------------------------------------------------
/packages/j-provider/public/fonts/NotoSansKR-Regular-Alphabetic.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DesignSystemLab/design-system/b47e12d874498c1c44be23f41eda33f956311c16/packages/j-provider/public/fonts/NotoSansKR-Regular-Alphabetic.woff2
--------------------------------------------------------------------------------
/packages/j-provider/public/fonts/NotoSansKR-Thin-Alphabetic.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DesignSystemLab/design-system/b47e12d874498c1c44be23f41eda33f956311c16/packages/j-provider/public/fonts/NotoSansKR-Thin-Alphabetic.woff2
--------------------------------------------------------------------------------
/packages/j-provider/src/ThemeProvider.tsx:
--------------------------------------------------------------------------------
1 | /** @jsxImportSource @emotion/react */
2 | import { Global } from '@emotion/react';
3 | import { ThemeContext } from './context';
4 | import { preset } from './preset';
5 | import reset from './styles/reset';
6 |
7 | export const ThemeProvider = (props: { children: React.ReactNode; presetConfig?: any }) => {
8 | return (
9 |
10 |
11 | {props.children}
12 |
13 | );
14 | };
15 |
--------------------------------------------------------------------------------
/packages/j-provider/src/context.ts:
--------------------------------------------------------------------------------
1 | import { preset } from './preset';
2 | import { createContext } from 'react';
3 | import type { Preset } from './types';
4 |
5 | export const themePreset = preset[preset.theme];
6 | export const ThemeContext = createContext(themePreset);
7 |
--------------------------------------------------------------------------------
/packages/j-provider/src/index.ts:
--------------------------------------------------------------------------------
1 | export * from './preset';
2 | export * from './context';
3 | export * from './ThemeProvider';
4 | export * from './types';
5 |
--------------------------------------------------------------------------------
/packages/j-provider/src/types.ts:
--------------------------------------------------------------------------------
1 | import type { HEX } from '@jdesignlab/theme';
2 | export interface ThemePreset {
3 | color: {
4 | background: HEX;
5 | fontColor: HEX;
6 | primary: HEX;
7 | secondary: HEX;
8 | success: HEX;
9 | info: HEX;
10 | warning: HEX;
11 | error: HEX;
12 | disabled: HEX;
13 | font: HEX;
14 | };
15 | effect: {
16 | disabledOpacity: string | number;
17 | hoverGhostOpacity: string | number;
18 | hoverSolidOpacity: string | number;
19 | focusOpacity: string | number;
20 | selectedOpacity: string | number;
21 | activatedOpacity: string | number;
22 | pressedOpacity: string | number;
23 | draggedOpacity: string | number;
24 | };
25 | }
26 | export interface Preset {
27 | theme: 'light' | 'dark';
28 | light: ThemePreset;
29 | dark: ThemePreset;
30 | }
31 |
--------------------------------------------------------------------------------
/packages/j-provider/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tsconfig.json",
3 | "include": ["./src"],
4 | "compilerOptions": {
5 | "declaration": true,
6 | "isolatedModules": false,
7 | "esModuleInterop": true, // es module이 아니어도 import export 쓸 수 있게 함
8 | "importHelpers": true,
9 | "types": ["@emotion/react/types/css-prop"],
10 | "jsx": "react-jsx",
11 | "jsxImportSource": "@emotion/react"
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/packages/modal/jest.config.ts:
--------------------------------------------------------------------------------
1 | import type { Config } from 'jest';
2 |
3 | const config: Config = {
4 | preset: 'ts-jest',
5 | testEnvironment: 'jsdom',
6 | setupFilesAfterEnv: ['/setup-jest.ts'],
7 | transform: {
8 | '^.+\\.[jt]sx?$': 'ts-jest',
9 | '^.+\\.(css|scss|sass|less)$': 'jest-preview/transforms/css',
10 | '^(?!.*\\.(js|jsx|mjs|cjs|ts|tsx|css|json)$)': 'jest-preview/transforms/file'
11 | }
12 | };
13 |
14 | export default config;
--------------------------------------------------------------------------------
/packages/modal/setup-jest.ts:
--------------------------------------------------------------------------------
1 | import '@testing-library/jest-dom/';
2 |
--------------------------------------------------------------------------------
/packages/modal/src/components/ModalTrigger.tsx:
--------------------------------------------------------------------------------
1 | /** @jsxImportSource @emotion/react */
2 | import { Trigger } from '@jdesignlab/react-utils';
3 | import { useContext } from 'react';
4 | import { ModalContext } from '../context';
5 | import { ModalTriggerProps } from '../types';
6 |
7 | export const ModalTrigger = (props: ModalTriggerProps) => {
8 | const { children } = props;
9 | const { id, onOpen } = useContext(ModalContext);
10 |
11 | return (
12 |
13 | {children}
14 |
15 | );
16 | };
17 |
18 | ModalTrigger.displayName = 'Modal.Trigger';
19 |
--------------------------------------------------------------------------------
/packages/modal/src/context.ts:
--------------------------------------------------------------------------------
1 | import { createContext } from 'react';
2 | interface ModalContext {
3 | id: string;
4 | isOpen: boolean;
5 | onOpen(): void;
6 | onClose(): void;
7 | hasCloseIcon: boolean;
8 | disableOverlayClose: boolean;
9 | }
10 |
11 | export const ModalContext = createContext({
12 | id: '',
13 | isOpen: false,
14 | onOpen: () => {},
15 | onClose: () => {},
16 | hasCloseIcon: true,
17 | disableOverlayClose: false
18 | });
19 |
--------------------------------------------------------------------------------
/packages/modal/src/hooks/useToggleLayer.ts:
--------------------------------------------------------------------------------
1 | import { useCallback, useEffect, useState } from 'react';
2 |
3 | export const useToggleLayer = (
4 | openProp: boolean | undefined,
5 | onOpenProp: (() => void) | undefined,
6 | onCloseProp: (() => void) | undefined
7 | ) => {
8 | const [isOpen, setIsOpen] = useState(!!openProp);
9 | const isControlled = openProp !== undefined;
10 |
11 | useEffect(() => {
12 | setIsOpen(!!openProp);
13 | }, [openProp]);
14 |
15 | const onToggle = useCallback(() => {
16 | setIsOpen(prev => !prev);
17 | if (isOpen) onCloseProp?.();
18 | else onOpenProp?.();
19 | }, [isOpen, onOpenProp, onCloseProp]);
20 |
21 | const onOpen = () => {
22 | isControlled ? onOpenProp?.() : onToggle();
23 | };
24 |
25 | const onClose = () => {
26 | isControlled ? onCloseProp?.() : onToggle();
27 | };
28 |
29 | return { isOpen, onOpen, onClose };
30 | };
31 |
--------------------------------------------------------------------------------
/packages/modal/src/index.ts:
--------------------------------------------------------------------------------
1 | export * from './components/Modal';
2 |
--------------------------------------------------------------------------------
/packages/modal/src/styles.ts:
--------------------------------------------------------------------------------
1 | import { css } from '@emotion/react';
2 | import { SEMATIC_COLOR_HOVER, SHADOW_MODAL, Z_INDEX_MODAL } from '@jdesignlab/theme';
3 |
4 | export const portal = (width: number, height: number) => {
5 | return css({
6 | zIndex: Z_INDEX_MODAL,
7 | position: 'fixed',
8 | top: '50%',
9 | left: '50%',
10 | transform: 'translate(-50%, -50%)',
11 | display: 'block',
12 | background: 'white',
13 | width: `${width}px`,
14 | height: `${height}px`,
15 | borderRadius: '6px',
16 | padding: '12px',
17 | boxShadow: SHADOW_MODAL
18 | });
19 | };
20 |
21 | export const closeIconWrapper = css({
22 | position: 'absolute',
23 | right: '6px',
24 | top: '6px',
25 | width: '24px',
26 | height: '24px',
27 | display: 'flex',
28 | justifyContent: 'center',
29 | alignItems: 'center',
30 | padding: '8px',
31 | borderRadius: '100%',
32 | cursor: 'pointer',
33 | '&:hover': {
34 | background: SEMATIC_COLOR_HOVER
35 | }
36 | });
37 |
38 | export const closeIcon = css({
39 | padding: 0
40 | });
41 |
--------------------------------------------------------------------------------
/packages/modal/src/types.ts:
--------------------------------------------------------------------------------
1 | export interface ModalProps {
2 | children?: React.ReactNode;
3 | hasCloseIcon?: boolean;
4 | open?: boolean;
5 | onClose?(): void;
6 | onOpen?(): void;
7 | disableOverlayClose?: boolean;
8 | }
9 |
10 | export interface ModalTriggerProps {
11 | children: React.ReactNode;
12 | }
13 |
14 | export interface ModalPortalProps {
15 | children: React.ReactNode;
16 | width?: number;
17 | height?: number;
18 | }
19 |
--------------------------------------------------------------------------------
/packages/modal/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tsconfig.json",
3 | "include": ["./src"],
4 | "compilerOptions": {
5 | "declaration": true,
6 | "isolatedModules": false,
7 | "esModuleInterop": true, // es module이 아니어도 import export 쓸 수 있게 함
8 | "importHelpers": true,
9 | "types": ["@emotion/react/types/css-prop"],
10 | "jsx": "react-jsx",
11 | "jsxImportSource": "@emotion/react"
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/packages/popover/jest.config.ts:
--------------------------------------------------------------------------------
1 | import type { Config } from 'jest';
2 |
3 | const config: Config = {
4 | preset: 'ts-jest',
5 | testEnvironment: 'jsdom',
6 | setupFilesAfterEnv: ['/setup-jest.ts'],
7 | snapshotSerializers: ['@emotion/jest/serializer'],
8 | transform: {
9 | '^.+\\.[jt]sx?$': 'ts-jest',
10 | '^.+\\.(css|scss|sass|less)$': 'jest-preview/transforms/css',
11 | '^(?!.*\\.(js|jsx|mjs|cjs|ts|tsx|css|json)$)': 'jest-preview/transforms/file'
12 | }
13 | };
14 |
15 | export default config;
16 |
--------------------------------------------------------------------------------
/packages/popover/setup-jest.ts:
--------------------------------------------------------------------------------
1 | import '@testing-library/jest-dom/';
2 |
--------------------------------------------------------------------------------
/packages/popover/src/components/PopoverBody.tsx:
--------------------------------------------------------------------------------
1 | /** @jsxImportSource @emotion/react */
2 | import * as Style from '../styles';
3 | import { createClassVariant } from '@jdesignlab/theme';
4 | import { POPOVER_BORDER_COLOR } from '../constants';
5 |
6 | export const PopoverBody = (props: { children: React.ReactNode }) => {
7 | return (
8 |
9 | {props.children}
10 |
11 | );
12 | };
13 |
14 | PopoverBody.displayName = 'PopoverBody';
15 |
--------------------------------------------------------------------------------
/packages/popover/src/components/PopoverFooter.tsx:
--------------------------------------------------------------------------------
1 | /** @jsxImportSource @emotion/react */
2 | import * as Style from '../styles';
3 | import { createClassVariant } from '@jdesignlab/theme';
4 |
5 | export const popoverFooter = (props: { children: React.ReactNode }) => {
6 | return (
7 |
10 | );
11 | };
12 |
13 | popoverFooter.displayName = 'PopoverFooter';
14 |
--------------------------------------------------------------------------------
/packages/popover/src/components/PopoverHeader.tsx:
--------------------------------------------------------------------------------
1 | /** @jsxImportSource @emotion/react */
2 | import * as Style from '../styles';
3 | import { createClassVariant } from '@jdesignlab/theme';
4 | import { POPOVER_BORDER_COLOR } from '../constants';
5 |
6 | export const PopoverHeader = (props: { children?: React.ReactNode }) => {
7 | return (
8 |
9 | {props.children}
10 |
11 | );
12 | };
13 |
14 | PopoverHeader.displayName = 'PopoverHeader';
15 |
--------------------------------------------------------------------------------
/packages/popover/src/components/PopoverOverlay.tsx:
--------------------------------------------------------------------------------
1 | /** @jsxImportSource @emotion/react */
2 | import * as Style from '../styles';
3 | import { useContext } from 'react';
4 | import { createClassVariant } from '@jdesignlab/theme';
5 | import { PopoverContext } from '../context';
6 | import usePopoverControl from '../hooks/usePopoverControl';
7 |
8 | export const PopoverOverlay = () => {
9 | const context = useContext(PopoverContext);
10 | const { onClosePopover } = usePopoverControl(context);
11 |
12 | return (
13 |
19 | );
20 | };
21 |
22 | PopoverOverlay.displayName = 'PopoverOverlay';
23 |
--------------------------------------------------------------------------------
/packages/popover/src/components/PopoverProvider.tsx:
--------------------------------------------------------------------------------
1 | import { RefObject, useState } from 'react';
2 | import { PopoverContext, defaultContextValues } from '../context';
3 |
4 | export const PopoverProvider = ({ ...props }) => {
5 | const [triggerRef, setTriggerRef] = useState | null>(null);
6 | const { popoverProps } = props;
7 | const [isOpen, setOpen] = useState(popoverProps.open);
8 | const defaultPopoverProps = defaultContextValues.popoverProps;
9 | const {
10 | open = defaultPopoverProps.open,
11 | placement = defaultPopoverProps.placement,
12 | arrow = defaultPopoverProps.arrow
13 | } = popoverProps;
14 |
15 | return (
16 |
25 | {props.children}
26 |
27 | );
28 | };
29 |
--------------------------------------------------------------------------------
/packages/popover/src/components/PopoverTrigger.tsx:
--------------------------------------------------------------------------------
1 | /** @jsxImportSource @emotion/react */
2 | import * as Style from '../styles';
3 | import React, { useContext, Children, useEffect, useRef } from 'react';
4 | import { createClassVariant } from '@jdesignlab/theme';
5 | import usePopoverControl from '../hooks/usePopoverControl';
6 | import { PopoverContext } from '../context';
7 |
8 | export const PopoverTrigger = (props: { children: React.ReactNode }) => {
9 | const context = useContext(PopoverContext);
10 | const children = Children.only(props.children);
11 | const triggerRef = useRef(null);
12 | const { onTogglePopover } = usePopoverControl(context);
13 |
14 | useEffect(() => {
15 | if (triggerRef.current) {
16 | context.setTriggerRef(triggerRef);
17 | }
18 | }, [triggerRef]);
19 |
20 | return (
21 |
29 | {children}
30 |
31 | );
32 | };
33 |
--------------------------------------------------------------------------------
/packages/popover/src/constants.ts:
--------------------------------------------------------------------------------
1 | import { getColorByToken } from '@jdesignlab/theme';
2 | import type { PopoverProps } from './types';
3 |
4 | type PopoverOption = Required>;
5 |
6 | const DEFAULT_OPTIONS: PopoverOption = {
7 | arrow: true,
8 | open: false,
9 | placement: 'bottom'
10 | };
11 |
12 | const POPOVER_BACKGROUND = getColorByToken('shades-white');
13 | const POPOVER_BORDER_COLOR = getColorByToken('grey-lighten1');
14 |
15 | export { DEFAULT_OPTIONS, POPOVER_BACKGROUND, POPOVER_BORDER_COLOR };
16 |
--------------------------------------------------------------------------------
/packages/popover/src/context.ts:
--------------------------------------------------------------------------------
1 | import { createContext, RefObject, useState } from 'react';
2 | import { DEFAULT_OPTIONS } from './constants';
3 | import type { ReturnContext } from './types';
4 |
5 | export const defaultContextValues: ReturnContext = {
6 | isOpen: false,
7 | setOpen: () => {},
8 | triggerRef: null,
9 | setTriggerRef: () => {},
10 | popoverProps: {
11 | onClose: () => {},
12 | onOpen: () => {},
13 | arrow: DEFAULT_OPTIONS.arrow,
14 | open: DEFAULT_OPTIONS.open,
15 | placement: DEFAULT_OPTIONS.placement
16 | }
17 | };
18 |
19 | export const PopoverContext = createContext(defaultContextValues);
20 |
--------------------------------------------------------------------------------
/packages/popover/src/hooks/useInitialRender.ts:
--------------------------------------------------------------------------------
1 | import { useRef } from 'react';
2 |
3 | const useInitialRender = () => {
4 | const isInitial = useRef(true);
5 |
6 | if (isInitial.current) {
7 | isInitial.current = false;
8 | return true;
9 | }
10 |
11 | return isInitial.current;
12 | };
13 |
14 | export default useInitialRender;
15 |
--------------------------------------------------------------------------------
/packages/popover/src/hooks/useOpenClosePopover.ts:
--------------------------------------------------------------------------------
1 | import { useEffect } from 'react';
2 | import type { ReturnContext } from '../types';
3 |
4 | const useOpenClosePopover = (context: ReturnContext, init: boolean) => {
5 | const { popoverProps, isOpen, setOpen } = context;
6 | const { onOpen, onClose, open } = popoverProps;
7 |
8 | useEffect(() => {
9 | setOpen(open);
10 | }, [open]);
11 |
12 | useEffect(() => {
13 | if (isOpen && onOpen) {
14 | onOpen();
15 | return;
16 | }
17 | if (!init) {
18 | if (!isOpen && onClose) {
19 | onClose();
20 | }
21 |
22 | if (isOpen && onOpen) {
23 | onOpen();
24 | }
25 | }
26 | }, [isOpen]);
27 | };
28 |
29 | export default useOpenClosePopover;
30 |
--------------------------------------------------------------------------------
/packages/popover/src/hooks/usePopoverControl.ts:
--------------------------------------------------------------------------------
1 | import { useCallback } from 'react';
2 | import type { ReturnContext } from '../types';
3 |
4 | const usePopoverControl = (context: ReturnContext) => {
5 | const { setOpen } = context;
6 |
7 | const onTogglePopover = useCallback(() => {
8 | setOpen(prev => !prev);
9 | }, [setOpen]);
10 |
11 | const onClosePopover = useCallback(() => {
12 | setOpen(false);
13 | }, [setOpen]);
14 |
15 | const onOpenPopover = useCallback(() => {
16 | setOpen(true);
17 | }, [setOpen]);
18 |
19 | return { onTogglePopover, onClosePopover, onOpenPopover };
20 | };
21 |
22 | export default usePopoverControl;
23 |
--------------------------------------------------------------------------------
/packages/popover/src/index.ts:
--------------------------------------------------------------------------------
1 | export * from './components/Popover';
2 |
--------------------------------------------------------------------------------
/packages/popover/src/types/base.ts:
--------------------------------------------------------------------------------
1 | import type { SerializedStyles } from '@emotion/react';
2 |
3 | export type StyleProps = Record;
4 | export type Placement = 'top' | 'right' | 'bottom' | 'left';
5 | export type PopoverTrigger = Record<'width' | 'height', number>;
6 |
--------------------------------------------------------------------------------
/packages/popover/src/types/context.ts:
--------------------------------------------------------------------------------
1 | import type { Dispatch, RefObject, SetStateAction } from 'react';
2 | import type { PopoverProps } from './props';
3 |
4 | export interface TriggerRef {
5 | triggerRef: RefObject | null;
6 | setTriggerRef: Dispatch>;
7 | }
8 |
9 | export interface ReturnContext extends TriggerRef {
10 | isOpen: boolean;
11 | setOpen: Dispatch>;
12 | popoverProps: Required>;
13 | }
14 |
--------------------------------------------------------------------------------
/packages/popover/src/types/index.ts:
--------------------------------------------------------------------------------
1 | export * from './base';
2 | export * from './context';
3 | export * from './props';
4 |
--------------------------------------------------------------------------------
/packages/popover/src/types/props.ts:
--------------------------------------------------------------------------------
1 | import type { Placement } from './base';
2 |
3 | export interface PopoverHandler {
4 | onOpen?: () => void;
5 | onClose?: () => void;
6 | }
7 |
8 | export interface PopoverProps extends PopoverHandler {
9 | children?: React.ReactNode;
10 | placement?: Placement;
11 | arrow?: boolean;
12 | open?: boolean;
13 | }
14 |
--------------------------------------------------------------------------------
/packages/popover/src/utils/calculateSize.ts:
--------------------------------------------------------------------------------
1 | import type { RefObject } from 'react';
2 |
3 | const calculateSize = (ref: RefObject | null) => {
4 | let height = 0;
5 | let width = 0;
6 | if (ref?.current) {
7 | width = parseFloat(getComputedStyle(ref.current).width);
8 | height = parseFloat(getComputedStyle(ref.current).height);
9 | }
10 |
11 | return {
12 | height: Math.round(height),
13 | width: Math.round(width)
14 | };
15 | };
16 |
17 | export default calculateSize;
18 |
--------------------------------------------------------------------------------
/packages/popover/src/utils/handleEscapeKey.ts:
--------------------------------------------------------------------------------
1 | import type { KeyboardEvent } from 'react';
2 |
3 | const handleEscapeKey = (event: React.KeyboardEvent, onClose: () => void) => {
4 | event.stopPropagation();
5 | if (event.key === 'Escape') {
6 | onClose();
7 | return;
8 | }
9 | };
10 | export default handleEscapeKey;
11 |
--------------------------------------------------------------------------------
/packages/popover/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tsconfig.json",
3 | "include": ["./src"],
4 | "compilerOptions": {
5 | "declaration": true,
6 | "isolatedModules": false,
7 | "esModuleInterop": true, // es module이 아니어도 import export 쓸 수 있게 함
8 | "importHelpers": true,
9 | "types": ["@emotion/react/types/css-prop", "@types/jest", "@testing-library/jest-dom"],
10 | "jsx": "react-jsx",
11 | "jsxImportSource": "@emotion/react"
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/packages/radio/jest.config.ts:
--------------------------------------------------------------------------------
1 | import type { Config } from 'jest';
2 |
3 | const config: Config = {
4 | preset: 'ts-jest',
5 | testEnvironment: 'jsdom',
6 | setupFilesAfterEnv: ['/setup-jest.ts'],
7 | transform: {
8 | '^.+\\.[jt]sx?$': 'ts-jest',
9 | '^.+\\.(css|scss|sass|less)$': 'jest-preview/transforms/css',
10 | '^(?!.*\\.(js|jsx|mjs|cjs|ts|tsx|css|json)$)': 'jest-preview/transforms/file'
11 | }
12 | };
13 |
14 | export default config;
15 |
--------------------------------------------------------------------------------
/packages/radio/setup-jest.ts:
--------------------------------------------------------------------------------
1 | import '@testing-library/jest-dom/';
2 |
--------------------------------------------------------------------------------
/packages/radio/src/components/RadioGroup.tsx:
--------------------------------------------------------------------------------
1 | import { forwardRef } from 'react';
2 | import { createClassVariant } from '@jdesignlab/theme';
3 | import { RadioProvider } from './RadioProvider';
4 | import useRadioGroup from '../hooks/useRadioGroup';
5 | import type { RadioGroupProps } from '../types';
6 |
7 | const RadioGroup = Object.assign(
8 | forwardRef((props: RadioGroupProps, ref) => {
9 | const { children, defaultValue = null, ...restProps } = props;
10 | const radioGroupRef = useRadioGroup(defaultValue, ref);
11 |
12 | return (
13 |
14 |
15 | {children}
16 |
17 |
18 | );
19 | })
20 | );
21 |
22 | RadioGroup.displayName = 'RadioGroup';
23 | export default RadioGroup;
24 |
--------------------------------------------------------------------------------
/packages/radio/src/components/RadioLabel.tsx:
--------------------------------------------------------------------------------
1 | /** @jsxImportSource @emotion/react */
2 | import * as Style from '../styles';
3 | import { createClassVariant } from '@jdesignlab/theme';
4 | import { DEFAULT_FONT_COLOR } from '../constants';
5 | import type { RadioLabelProps } from '../types';
6 |
7 | const RadioLabel = (props: RadioLabelProps) => {
8 | const { id, children, size } = props;
9 | const labelStyle = Style.createLabel(size, DEFAULT_FONT_COLOR);
10 | return (
11 |
14 | );
15 | };
16 |
17 | RadioLabel.displayName = 'RadioLabel';
18 | export default RadioLabel;
19 |
--------------------------------------------------------------------------------
/packages/radio/src/components/RadioProvider.tsx:
--------------------------------------------------------------------------------
1 | import { RadioContext } from '../context';
2 | import { useId, useState } from 'react';
3 | import { RADIO_NAME_PREFIX } from '../constants';
4 |
5 | export const RadioProvider = ({ ...props }) => {
6 | const { children, defaultValue = null, rootProps = null } = props;
7 | const defaultName = rootProps && rootProps.name ? rootProps.name : `${RADIO_NAME_PREFIX}_${useId()}`;
8 | const [value, setValue] = useState('');
9 |
10 | return (
11 |
20 | {children}
21 |
22 | );
23 | };
24 |
--------------------------------------------------------------------------------
/packages/radio/src/constants.ts:
--------------------------------------------------------------------------------
1 | import { themePreset } from '@jdesignlab/j-provider';
2 | import type { HEX } from '@jdesignlab/theme';
3 |
4 | const RADIO_ID_PREFIX: string = 'j-radio';
5 | const RADIO_NAME_PREFIX: string = 'j-radio-name';
6 | const DEFAULT_COLOR: HEX = themePreset.color.primary;
7 | const DEFAULT_FONT_COLOR: HEX = themePreset.color.fontColor;
8 | const DEFAULT_DISABLED_COLOR: HEX = themePreset.color.disabled;
9 |
10 | export { RADIO_ID_PREFIX, RADIO_NAME_PREFIX, DEFAULT_COLOR, DEFAULT_DISABLED_COLOR, DEFAULT_FONT_COLOR };
11 |
--------------------------------------------------------------------------------
/packages/radio/src/context.ts:
--------------------------------------------------------------------------------
1 | import { createContext } from 'react';
2 | import type { ReturnContext } from './types';
3 |
4 | export const RadioContext = createContext(null);
5 |
--------------------------------------------------------------------------------
/packages/radio/src/hooks/useRadioGroup.ts:
--------------------------------------------------------------------------------
1 | import { ForwardedRef, useCallback, useEffect, useRef } from 'react';
2 |
3 | const useRadioGroup = (defalutValue: string | null, externalRef?: ForwardedRef) => {
4 | const ref = useRef(null);
5 |
6 | const setDefaultValueCheck = useCallback(
7 | (el: HTMLInputElement, targetValue: string | null, externalRef?: ForwardedRef) => {
8 | const isUnavailable = el.hasAttribute('readonly') || el.hasAttribute('disabled');
9 | if (targetValue && targetValue === el.value && !isUnavailable) {
10 | el.checked = true;
11 | }
12 | if (externalRef && typeof externalRef === 'function') {
13 | externalRef(el);
14 | }
15 | },
16 | [ref]
17 | );
18 |
19 | useEffect(() => {
20 | if (ref.current) {
21 | const radioElements = ref.current.querySelectorAll('input[type="radio"]') as NodeListOf;
22 | radioElements.forEach(el => {
23 | setDefaultValueCheck(el, defalutValue, externalRef);
24 | });
25 | }
26 | }, [ref]);
27 |
28 | return ref;
29 | };
30 |
31 | export default useRadioGroup;
32 |
--------------------------------------------------------------------------------
/packages/radio/src/index.ts:
--------------------------------------------------------------------------------
1 | export * from './components/Radio';
2 |
--------------------------------------------------------------------------------
/packages/radio/src/types/base.ts:
--------------------------------------------------------------------------------
1 | export type RadioSize = 'sm' | 'md' | 'lg';
2 | export type RadioValueType = string | number | boolean;
3 |
--------------------------------------------------------------------------------
/packages/radio/src/types/context.ts:
--------------------------------------------------------------------------------
1 | import type { Dispatch, SetStateAction } from 'react';
2 | import type { EventType } from '@jdesignlab/utils';
3 | import type { RadioValueType } from './base';
4 |
5 | export type RadioAttributes = { [key: string]: string | ((event: EventType) => void) };
6 | export interface ReturnContext {
7 | defaultValue?: string;
8 | name: string;
9 | rootProps: RadioAttributes | null;
10 | setValue: Dispatch> | null;
11 | value: RadioValueType | null;
12 | }
13 |
--------------------------------------------------------------------------------
/packages/radio/src/types/index.ts:
--------------------------------------------------------------------------------
1 | export * from './base';
2 | export * from './context';
3 | export * from './props';
4 |
--------------------------------------------------------------------------------
/packages/radio/src/types/props.ts:
--------------------------------------------------------------------------------
1 | import { RadioSize, RadioValueType } from './base';
2 | import type { ColorToken } from '@jdesignlab/theme';
3 |
4 | export interface RadioLabelProps {
5 | id: string;
6 | size: RadioSize;
7 | children: React.ReactNode;
8 | }
9 |
10 | export interface RadioGroupProps extends React.HTMLAttributes {
11 | defaultValue?: string;
12 | }
13 |
14 | export interface RadioProps extends React.HTMLAttributes {
15 | children?: React.ReactNode;
16 | color?: ColorToken;
17 | disabled?: boolean;
18 | readonly?: boolean;
19 | size?: RadioSize;
20 | name?: string;
21 | value?: RadioValueType;
22 | }
23 |
--------------------------------------------------------------------------------
/packages/radio/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tsconfig.json",
3 | "include": ["./src"],
4 | "compilerOptions": {
5 | "declaration": true,
6 | "isolatedModules": false,
7 | "esModuleInterop": true, // es module이 아니어도 import export 쓸 수 있게 함
8 | "importHelpers": true,
9 | "types": ["@emotion/react/types/css-prop", "@types/jest", "@testing-library/jest-dom"],
10 | "jsx": "react-jsx",
11 | "jsxImportSource": "@emotion/react"
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/packages/react-utils/.babelrc.json:
--------------------------------------------------------------------------------
1 | // {
2 | // "presets": ["@babel/env", ["@babel/preset-react", { "runtime": "automatic", "importSource": "@emotion/react" }]],
3 | // "plugins": ["@emotion/babel-plugin"]
4 | // }
5 |
--------------------------------------------------------------------------------
/packages/react-utils/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # @jdesignlab/react-utils
2 |
3 | ## 0.9.0
4 |
5 | ### Minor Changes
6 |
7 | - Add useOutsideClick hook for external clicks
8 |
9 | ## 0.8.0
10 |
11 | ### Minor Changes
12 |
13 | - Remove rollup packages and configure files
14 |
15 | ## 0.7.0
16 |
17 | ### Minor Changes
18 |
19 | - supply react hook form
20 |
21 | ## 0.6.0
22 |
23 | ### Minor Changes
24 |
25 | - add number type from getComponentText
26 |
27 | ## 0.5.0
28 |
29 | ### Minor Changes
30 |
31 | - remove clean-package
32 |
33 | ### Patch Changes
34 |
35 | - Updated dependencies
36 | - @jdesignlab/utils@0.5.0
37 |
38 | ## 0.4.0
39 |
40 | ### Minor Changes
41 |
42 | - change publish config
43 |
44 | ### Patch Changes
45 |
46 | - Updated dependencies
47 | - @jdesignlab/utils@0.4.0
48 |
49 | ## 0.3.0
50 |
51 | ### Minor Changes
52 |
53 | - minor
54 |
55 | ### Patch Changes
56 |
57 | - Updated dependencies
58 | - @jdesignlab/utils@0.3.0
59 |
--------------------------------------------------------------------------------
/packages/react-utils/README.md:
--------------------------------------------------------------------------------
1 | # react-utils
2 |
--------------------------------------------------------------------------------
/packages/react-utils/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@jdesignlab/react-utils",
3 | "packageManager": "yarn@3.3.1",
4 | "version": "0.9.0",
5 | "main": "src/index.ts",
6 | "sideEffects": false,
7 | "files": [
8 | "dist"
9 | ],
10 | "scripts": {
11 | "build": "tsup src --dts --format esm,cjs",
12 | "build:clean": "rimraf dist/"
13 | },
14 | "devDependencies": {
15 | "@emotion/babel-plugin": "^11.10.5",
16 | "@emotion/babel-preset-css-prop": "^11.10.0",
17 | "@emotion/react": "^11.10.5",
18 | "@types/react": "18.0.27",
19 | "@types/react-dom": "^18.2.7",
20 | "react": "^18.2.0",
21 | "react-dom": "^18.2.0",
22 | "rimraf": "^4.1.2",
23 | "tslib": "^2.5.0",
24 | "tsup": "^6.7.0",
25 | "typescript": "^4.9.4"
26 | },
27 | "peerDependencies": {
28 | "@emotion/react": "~11",
29 | "react": "~18"
30 | },
31 | "dependencies": {
32 | "@jdesignlab/theme": "*",
33 | "@jdesignlab/utils": "*"
34 | },
35 | "publishConfig": {
36 | "access": "public",
37 | "directory": "_release/package",
38 | "main": "./dist/index.js",
39 | "module": "./dist/index.mjs",
40 | "types": "./dist/index.d.ts"
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/packages/react-utils/src/components/Overlay.tsx:
--------------------------------------------------------------------------------
1 | /** @jsxImportSource @emotion/react */
2 | import { css } from '@emotion/react';
3 | import { ClassNameVariant, SEMATIC_COLOR_OVERLAY, Z_INDEX_OVERLAY } from '@jdesignlab/theme';
4 |
5 | interface OverlayProps {
6 | onClick?(): void;
7 | className?: ClassNameVariant;
8 | }
9 |
10 | const overlayStyle = css({
11 | zIndex: Z_INDEX_OVERLAY,
12 | position: 'fixed',
13 | top: 0,
14 | left: 0,
15 | width: '100vw',
16 | height: '100vh',
17 | background: SEMATIC_COLOR_OVERLAY
18 | });
19 |
20 | export const Overlay = (props: OverlayProps) => {
21 | const { onClick, ...rest } = props;
22 | return ;
23 | };
24 |
--------------------------------------------------------------------------------
/packages/react-utils/src/components/Portal.tsx:
--------------------------------------------------------------------------------
1 | /** @jsxImportSource @emotion/react */
2 | import { ClassNameVariant } from '@jdesignlab/theme';
3 | import { ReactNode } from 'react';
4 | import ReactDOM from 'react-dom';
5 |
6 | interface PortalProps {
7 | children: ReactNode;
8 | className?: ClassNameVariant;
9 | }
10 | const PORTAL_CONTAINER = document?.body;
11 | export const Portal = (props: PortalProps) => {
12 | const { children } = props;
13 | return ReactDOM.createPortal(<>{children}>, PORTAL_CONTAINER);
14 | };
15 |
--------------------------------------------------------------------------------
/packages/react-utils/src/components/Trigger.tsx:
--------------------------------------------------------------------------------
1 | /** @jsxImportSource @emotion/react */
2 | import { css } from '@emotion/react';
3 | import { ReactNode } from 'react';
4 |
5 | interface TriggerProps {
6 | children: ReactNode;
7 | onClick(): void;
8 | id?: string;
9 | }
10 |
11 | const triggerStyle = css({
12 | display: 'inline-block',
13 | cursor: 'pointer'
14 | });
15 |
16 | export const Trigger = (props: TriggerProps) => {
17 | const { children, onClick, id, ...rest } = props;
18 | const ariaControl = id ? { 'aria-control': id } : {};
19 |
20 | return (
21 |
22 | {children}
23 |
24 | );
25 | };
26 |
27 | Trigger.displayName = 'Trigger';
28 |
--------------------------------------------------------------------------------
/packages/react-utils/src/hooks/useInitialRender.ts:
--------------------------------------------------------------------------------
1 | import { useRef } from 'react';
2 |
3 | export const useInitialRender = () => {
4 | const isInitial = useRef(true);
5 |
6 | if (isInitial.current) {
7 | isInitial.current = false;
8 | return true;
9 | }
10 |
11 | return isInitial.current;
12 | };
13 |
--------------------------------------------------------------------------------
/packages/react-utils/src/hooks/useOutsideClick.ts:
--------------------------------------------------------------------------------
1 | import { RefObject, useEffect } from 'react';
2 |
3 | type Props = {
4 | ref: RefObject;
5 | handler: (event: MouseEvent) => void;
6 | };
7 |
8 | export const useOutsideClick = ({ ref, handler }: Props) => {
9 | useEffect(() => {
10 | const listener = (event: MouseEvent) => {
11 | if (!ref.current || ref.current.contains(event.target as Node)) {
12 | return;
13 | }
14 | handler(event);
15 | };
16 |
17 | document.addEventListener('mousedown', listener);
18 | return () => {
19 | document.removeEventListener('mousedown', listener);
20 | };
21 | });
22 | };
23 |
--------------------------------------------------------------------------------
/packages/react-utils/src/index.ts:
--------------------------------------------------------------------------------
1 | /** components */
2 | export * from './components/Overlay';
3 | export * from './components/Portal';
4 | export * from './components/Trigger';
5 |
6 | /** mixins */
7 | export * from './mixins/transition/useRipple';
8 | export * from './mixins/keyboard/spaceKeyToggleHandler';
9 | export * from './mixins/keyboard/arrowKeyNavigationHandler';
10 | export * from './mixins/styles/usePlacementStyle';
11 |
12 | /** utils */
13 | export * from './utils/filterComponent';
14 | export * from './utils/getComponentText';
15 | export * from './utils/hasComponent';
16 | export * from './utils/getChildrenValidValues';
17 |
18 | /** types */
19 | export * from './types';
20 | export * from './mixins/styles/usePlacementStyle';
21 |
22 | /** hooks */
23 | export * from './hooks/useInitialRender';
24 | export * from './hooks/useOutsideClick';
25 |
--------------------------------------------------------------------------------
/packages/react-utils/src/mixins/keyboard/spaceKeyToggleHandler.ts:
--------------------------------------------------------------------------------
1 | import type { Dispatch, SetStateAction } from 'react';
2 |
3 | export const spaceKeyToggleHandler = (props: {
4 | event: React.KeyboardEvent;
5 | setState?: Dispatch>;
6 | action?: () => void;
7 | }) => {
8 | const { event, setState, action } = props;
9 | if (event.key === 'Space' || event.key === ' ') {
10 | event.preventDefault();
11 | action && action();
12 | setState && setState((prev: boolean) => !prev);
13 | }
14 | };
15 |
--------------------------------------------------------------------------------
/packages/react-utils/src/types.ts:
--------------------------------------------------------------------------------
1 | export type Ripple = {
2 | x: number;
3 | y: number;
4 | size: number;
5 | };
6 |
--------------------------------------------------------------------------------
/packages/react-utils/src/utils/filterComponent.ts:
--------------------------------------------------------------------------------
1 | import { Children, isValidElement } from 'react';
2 | import type { ReactNode } from 'react';
3 |
4 | export const filterComponent = (
5 | children: ReactNode | ReactNode[],
6 | compoenent: (props: any) => ReactNode,
7 | isEqual: boolean
8 | ) => {
9 | return Children.toArray(children).filter(child => {
10 | if (isValidElement(child)) {
11 | return isEqual ? child.type === compoenent : child.type !== compoenent;
12 | }
13 | });
14 | };
15 |
--------------------------------------------------------------------------------
/packages/react-utils/src/utils/getChildrenValidValues.ts:
--------------------------------------------------------------------------------
1 | export const getChildrenValidValues = (children: React.ReactElement | React.ReactElement[], componentName: string) => {
2 | const values = [] as any[];
3 | if (children) {
4 | if (Array.isArray(children)) {
5 | children.forEach((child: React.ReactElement) => {
6 | const tagName = typeof child.type === 'function' ? child.type.name : child.type;
7 | if (tagName === componentName && !child.props.disabled) {
8 | values.push(child.props.value);
9 | }
10 | });
11 | } else {
12 | const tagName = typeof children.type === 'function' ? children.type.name : children.type;
13 | if (tagName === componentName && !children.props.disabled) {
14 | values.push(children.props.value);
15 | }
16 | }
17 | }
18 | return values;
19 | };
20 |
--------------------------------------------------------------------------------
/packages/react-utils/src/utils/getComponentText.ts:
--------------------------------------------------------------------------------
1 | import { Children, isValidElement } from 'react';
2 | import type { ReactNode } from 'react';
3 |
4 | export const getComponentText = (children: ReactNode) => {
5 | let childText = '';
6 | if (children) {
7 | Children.forEach(children, child => {
8 | if (isValidElement(child)) {
9 | return typeof child.props.children === 'string'
10 | ? (childText += child.props.children)
11 | : (childText += getComponentText(child.props.children));
12 | } else if (typeof child === 'string') {
13 | childText += child;
14 | }
15 | });
16 | }
17 | return childText;
18 | };
19 |
--------------------------------------------------------------------------------
/packages/react-utils/src/utils/hasComponent.ts:
--------------------------------------------------------------------------------
1 | export const hasComponent = (children: React.ReactElement | React.ReactElement[], componentName: string) => {
2 | let having = false;
3 | if (children) {
4 | if (Array.isArray(children)) {
5 | children.forEach((child: React.ReactElement) => {
6 | const tagName = typeof child.type === 'function' ? child.type.name : child.type;
7 | if (tagName === componentName) having = true;
8 | });
9 | } else {
10 | const tagName = typeof children.type === 'function' ? children.type.name : children.type;
11 | if (tagName === componentName) having = true;
12 | }
13 | }
14 | return having;
15 | };
16 |
--------------------------------------------------------------------------------
/packages/react-utils/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tsconfig.json",
3 | "include": ["./src"],
4 | "compilerOptions": {
5 | "declaration": true,
6 | "isolatedModules": false,
7 | "esModuleInterop": true, // es module이 아니어도 import export 쓸 수 있게 함
8 | "importHelpers": true
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/packages/react/README.md:
--------------------------------------------------------------------------------
1 | # react
2 |
--------------------------------------------------------------------------------
/packages/react/src/index.ts:
--------------------------------------------------------------------------------
1 | export * from '@jdesignlab/box';
2 | export * from '@jdesignlab/button';
3 | export * from '@jdesignlab/card';
4 | export * from '@jdesignlab/checkbox';
5 | export * from '@jdesignlab/drawer';
6 | export * from '@jdesignlab/dropdown';
7 | export * from '@jdesignlab/flex';
8 | export * from '@jdesignlab/input';
9 | export * from '@jdesignlab/j-provider';
10 | export * from '@jdesignlab/modal';
11 | export * from '@jdesignlab/popover';
12 | export * from '@jdesignlab/radio';
13 | export * from '@jdesignlab/react-utils';
14 | export * from '@jdesignlab/select';
15 | export * from '@jdesignlab/stack';
16 | export * from '@jdesignlab/tabs';
17 | export * from '@jdesignlab/textarea';
18 | export * from '@jdesignlab/theme';
19 | export * from '@jdesignlab/tooltip';
20 | export * from '@jdesignlab/typography';
21 | export * from '@jdesignlab/j-provider';
22 |
--------------------------------------------------------------------------------
/packages/react/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tsconfig.json",
3 | "include": ["./src/**/*"],
4 | "compilerOptions": {
5 | "declaration": true,
6 | "importHelpers": true,
7 | "jsx": "react-jsx",
8 | "jsxImportSource": "react-jsx"
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/packages/select/jest.config.ts:
--------------------------------------------------------------------------------
1 | import type { Config } from 'jest';
2 |
3 | const config: Config = {
4 | preset: 'ts-jest',
5 | testEnvironment: 'jsdom',
6 | setupFilesAfterEnv: ['/setup-jest.ts'],
7 | transform: {
8 | '^.+\\.[jt]sx?$': 'ts-jest',
9 | '^.+\\.(css|scss|sass|less)$': 'jest-preview/transforms/css',
10 | '^(?!.*\\.(js|jsx|mjs|cjs|ts|tsx|css|json)$)': 'jest-preview/transforms/file'
11 | }
12 | };
13 |
14 | export default config;
15 |
--------------------------------------------------------------------------------
/packages/select/setup-jest.ts:
--------------------------------------------------------------------------------
1 | import '@testing-library/jest-dom/';
2 |
--------------------------------------------------------------------------------
/packages/select/src/components/SearchNotfound.tsx:
--------------------------------------------------------------------------------
1 | import { createSelectStyle } from '../styles/createSelectStyle';
2 |
3 | /** @jsxImportSource @emotion/react */
4 | export const SelectNotfound = () => {
5 | const { notfound } = createSelectStyle();
6 | return (
7 |
8 | 검색 결과가 없습니다.
9 |
10 | );
11 | };
12 |
--------------------------------------------------------------------------------
/packages/select/src/constants.ts:
--------------------------------------------------------------------------------
1 | import { ColorToken } from '@jdesignlab/theme';
2 |
3 | const SELECT_ID_PREFIX: string = 'jdesignlab-select-list';
4 | const FONT_COLOR: ColorToken = 'font';
5 | const BORDER_COLOR: ColorToken = 'border';
6 | const DISABLED_COLOR: ColorToken = 'disabled';
7 | const FOCUS_COLOR: ColorToken = 'primary-500';
8 | const BORDER_RADIUS: number = 4;
9 |
10 | export { FONT_COLOR, BORDER_COLOR, BORDER_RADIUS, DISABLED_COLOR, FOCUS_COLOR, SELECT_ID_PREFIX };
11 |
--------------------------------------------------------------------------------
/packages/select/src/index.ts:
--------------------------------------------------------------------------------
1 | export * from './components/Select';
2 |
--------------------------------------------------------------------------------
/packages/select/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tsconfig.json",
3 | "include": ["./src"],
4 | "compilerOptions": {
5 | "declaration": true,
6 | "isolatedModules": false,
7 | "esModuleInterop": true, // es module이 아니어도 import export 쓸 수 있게 함
8 | "importHelpers": true,
9 | "types": ["@emotion/react/types/css-prop", "@types/jest", "@testing-library/jest-dom"],
10 | "jsx": "react-jsx",
11 | "jsxImportSource": "@emotion/react"
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/packages/stack/jest.config.ts:
--------------------------------------------------------------------------------
1 | import type { Config } from 'jest';
2 |
3 | const config: Config = {
4 | preset: 'ts-jest',
5 | testEnvironment: 'jsdom',
6 | setupFilesAfterEnv: ['/setup-jest.ts'],
7 | transform: {
8 | '^.+\\.[jt]sx?$': 'ts-jest',
9 | '^.+\\.(css|scss|sass|less)$': 'jest-preview/transforms/css',
10 | '^(?!.*\\.(js|jsx|mjs|cjs|ts|tsx|css|json)$)': 'jest-preview/transforms/file'
11 | }
12 | };
13 |
14 | export default config;
15 |
--------------------------------------------------------------------------------
/packages/stack/setup-jest.ts:
--------------------------------------------------------------------------------
1 | import '@testing-library/jest-dom/';
2 |
--------------------------------------------------------------------------------
/packages/stack/src/components/Stack.tsx:
--------------------------------------------------------------------------------
1 | /** @jsxImportSource @emotion/react */
2 | import { jsx } from '@emotion/react';
3 | import { createClassVariant } from '@jdesignlab/theme';
4 | import { MAX_WIDTH_MEDIA_QUERY } from '../constants';
5 | import { createStackStyle } from '../styles/createStackStyle';
6 | import { createResponsiveStyle } from '../styles/createResponsiveStyle';
7 | import { setMarginStyle } from '../styles/setMarginStyle';
8 | import type { StackProps } from '../types';
9 |
10 | export const Stack = (stackProps: StackProps) => {
11 | const { as = 'div', children, ...styleProps } = stackProps;
12 | const baseStyle = createStackStyle(styleProps);
13 | const responsiveStyle = createResponsiveStyle(styleProps.responsive, MAX_WIDTH_MEDIA_QUERY);
14 | const cloneElements = setMarginStyle(styleProps, MAX_WIDTH_MEDIA_QUERY, children);
15 |
16 | return jsx(
17 | as,
18 | { css: [baseStyle, responsiveStyle], className: `${createClassVariant('stack', 'ul')}`, role: 'list' },
19 | cloneElements
20 | );
21 | };
22 |
--------------------------------------------------------------------------------
/packages/stack/src/constants.ts:
--------------------------------------------------------------------------------
1 | const MAX_WIDTH_MEDIA_QUERY = '@media (max-width: 480px)';
2 |
3 | export { MAX_WIDTH_MEDIA_QUERY };
4 |
--------------------------------------------------------------------------------
/packages/stack/src/index.ts:
--------------------------------------------------------------------------------
1 | export * from './components/Stack';
2 |
--------------------------------------------------------------------------------
/packages/stack/src/styles/createResponsiveStyle.ts:
--------------------------------------------------------------------------------
1 | import { css } from '@emotion/react';
2 |
3 | export const createResponsiveStyle = (responsive: boolean = false, mqMaxWidth: string) => {
4 | const responsiveStyle = () => {
5 | if (responsive) {
6 | return css({
7 | [mqMaxWidth]: {
8 | flexDirection: 'column'
9 | }
10 | });
11 | }
12 | return css({});
13 | };
14 |
15 | return responsiveStyle();
16 | };
17 |
--------------------------------------------------------------------------------
/packages/stack/src/types.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * @todo: Will be add to 'utils' package
3 | */
4 | type StyleUnit = '%' | 'px' | 'em' | 'vh' | 'vw';
5 | export type SpacingToken = 'xs' | 'sm' | 'md' | 'lg' | 'xl' | `${number}${StyleUnit}`;
6 | export type FlexToken = 'start' | 'end' | 'center' | 'between' | 'around' | 'stretch';
7 | export type AsElement = React.ElementType;
8 |
9 | export type Direction = 'horizontal' | 'vertical';
10 | export type FlexMap = Record;
11 | export type SpacingMap = Record;
12 |
13 | export type StyleProps = Omit;
14 |
15 | export interface StackProps {
16 | as?: AsElement;
17 | children?: React.ReactNode;
18 | spacing?: SpacingToken;
19 | align?: FlexToken;
20 | justify?: FlexToken;
21 | direction?: Direction;
22 | responsive?: boolean;
23 | wrap?: boolean;
24 | }
25 |
--------------------------------------------------------------------------------
/packages/stack/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tsconfig.json",
3 | "include": ["./src"],
4 | "compilerOptions": {
5 | "declaration": true,
6 | "isolatedModules": false,
7 | "esModuleInterop": true, // es module이 아니어도 import export 쓸 수 있게 함
8 | "importHelpers": true,
9 | "types": ["@emotion/react/types/css-prop", "@types/jest", "@testing-library/jest-dom"],
10 | "jsx": "react-jsx",
11 | "jsxImportSource": "@emotion/react"
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/packages/tabs/jest.config.ts:
--------------------------------------------------------------------------------
1 | import type { Config } from 'jest';
2 |
3 | const config: Config = {
4 | preset: 'ts-jest',
5 | testEnvironment: 'jsdom',
6 | setupFilesAfterEnv: ['/setup-jest.ts'],
7 | transform: {
8 | '^.+\\.[jt]sx?$': 'ts-jest',
9 | '^.+\\.(css|scss|sass|less)$': 'jest-preview/transforms/css',
10 | '^(?!.*\\.(js|jsx|mjs|cjs|ts|tsx|css|json)$)': 'jest-preview/transforms/file'
11 | }
12 | };
13 |
14 | export default config;
--------------------------------------------------------------------------------
/packages/tabs/setup-jest.ts:
--------------------------------------------------------------------------------
1 | import '@testing-library/jest-dom/';
2 |
--------------------------------------------------------------------------------
/packages/tabs/src/context.ts:
--------------------------------------------------------------------------------
1 | import type { TabVariant, TabSize } from './types';
2 | import { createContext } from 'react';
3 | import { ColorToken } from '@jdesignlab/theme';
4 |
5 | const TabsContext = createContext({
6 | defaultValue: '',
7 | selectedTab: '',
8 | setSelectedTab: (value: string) => {},
9 | variant: 'underline' as TabVariant,
10 | size: 'md' as TabSize,
11 | lazy: false,
12 | full: false,
13 | baseColor: 'primary-100' as ColorToken,
14 | accentColor: 'primary-600' as ColorToken
15 | });
16 |
17 | export default TabsContext;
18 |
--------------------------------------------------------------------------------
/packages/tabs/src/hooks/useSelectKeyDown.ts:
--------------------------------------------------------------------------------
1 | import type { Dispatch, SetStateAction } from 'react';
2 |
3 | export const useSelectKeyDown = (
4 | event: React.KeyboardEvent,
5 | value: string,
6 | setSelectedTab: Dispatch>
7 | ) => {
8 | if (event.key === 'Enter') {
9 | event.preventDefault();
10 | setSelectedTab(value);
11 | }
12 | };
13 |
--------------------------------------------------------------------------------
/packages/tabs/src/hooks/useTabChangeHandle.ts:
--------------------------------------------------------------------------------
1 | import { useEffect } from 'react';
2 | import type { TabChangeHandleProps } from '../types';
3 |
4 | const useTabChangeHandle = ({ onChange, setHasTouched, selectedTab, hasTouched }: TabChangeHandleProps) => {
5 | useEffect(() => {
6 | if (onChange && hasTouched) {
7 | onChange();
8 | }
9 | setHasTouched(true);
10 | }, [selectedTab]);
11 | };
12 |
13 | export default useTabChangeHandle;
14 |
--------------------------------------------------------------------------------
/packages/tabs/src/index.ts:
--------------------------------------------------------------------------------
1 | export * from './components/Tabs';
2 |
--------------------------------------------------------------------------------
/packages/tabs/src/types.ts:
--------------------------------------------------------------------------------
1 | import type { ColorToken } from '@jdesignlab/theme';
2 | import type { Dispatch, SetStateAction } from 'react';
3 |
4 | export type TabVariant = 'enclosed' | 'underline' | 'unstyled';
5 | export type TabSize = 'sm' | 'md' | 'lg';
6 |
7 | export interface TabsProps {
8 | children: React.ReactNode;
9 | defaultValue?: string;
10 | variant?: TabVariant;
11 | onChange?: () => void;
12 | size?: TabSize;
13 | lazy?: boolean;
14 | full?: boolean;
15 | baseColor?: ColorToken;
16 | accentColor?: ColorToken;
17 | }
18 |
19 | export interface TabsListProps {
20 | children: React.ReactNode;
21 | }
22 |
23 | export interface TabsTriggerProps {
24 | children: React.ReactNode;
25 | value: string;
26 | disabled?: boolean;
27 | }
28 |
29 | export interface TabsContentProps {
30 | children: React.ReactNode;
31 | value: string;
32 | }
33 |
34 | export interface TabChangeHandleProps {
35 | selectedTab: string | undefined;
36 | hasTouched: boolean;
37 | setHasTouched: Dispatch>;
38 | onChange?: () => void;
39 | }
40 |
--------------------------------------------------------------------------------
/packages/tabs/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tsconfig.json",
3 | "include": ["./src"],
4 | "compilerOptions": {
5 | "declaration": true,
6 | "isolatedModules": false,
7 | "esModuleInterop": true, // es module이 아니어도 import export 쓸 수 있게 함
8 | "importHelpers": true,
9 | "types": ["@emotion/react/types/css-prop"],
10 | "jsx": "react-jsx",
11 | "jsxImportSource": "@emotion/react"
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/packages/text/jest.config.ts:
--------------------------------------------------------------------------------
1 | import type { Config } from 'jest';
2 |
3 | const config: Config = {
4 | preset: 'ts-jest',
5 | testEnvironment: 'jsdom',
6 | setupFilesAfterEnv: ['/setup-jest.ts'],
7 | transform: {
8 | '^.+\\.[jt]sx?$': 'ts-jest',
9 | '^.+\\.(css|scss|sass|less)$': 'jest-preview/transforms/css',
10 | '^(?!.*\\.(js|jsx|mjs|cjs|ts|tsx|css|json)$)': 'jest-preview/transforms/file'
11 | }
12 | };
13 |
14 | export default config;
15 |
--------------------------------------------------------------------------------
/packages/text/setup-jest.ts:
--------------------------------------------------------------------------------
1 | import '@testing-library/jest-dom/';
2 |
--------------------------------------------------------------------------------
/packages/text/src/constants.ts:
--------------------------------------------------------------------------------
1 | import { LineHeightMapType, FontSizeMap, ElementMap } from './types';
2 | import { themePreset } from '@jdesignlab/j-provider';
3 | import type { HEX } from '@jdesignlab/theme';
4 |
5 | const DEFAULT_COLOR: HEX = themePreset.color.fontColor;
6 | const ELEMENT_MAP: ElementMap = {
7 | paragraph: 'p',
8 | label: 'p',
9 | 'heading-2xl': 'h1',
10 | 'heading-xl': 'h2',
11 | 'heading-lg': 'h3',
12 | 'heading-md': 'h4',
13 | 'heading-sm': 'h5'
14 | };
15 | const LINE_HEIGHT_MAP: LineHeightMapType = {
16 | heading: '1.4',
17 | label: '1.5',
18 | paragraph: '1.6'
19 | };
20 |
21 | const FONT_SIZE_MAP: FontSizeMap = {
22 | sm: '12',
23 | md: '16',
24 | lg: '21',
25 | xl: '28',
26 | '2xl': '38'
27 | };
28 |
29 | export { LINE_HEIGHT_MAP, FONT_SIZE_MAP, ELEMENT_MAP, DEFAULT_COLOR };
30 |
--------------------------------------------------------------------------------
/packages/text/src/index.ts:
--------------------------------------------------------------------------------
1 | export * from './Text';
2 |
--------------------------------------------------------------------------------
/packages/text/src/styles/createFontStyle.ts:
--------------------------------------------------------------------------------
1 | import { css } from '@emotion/react';
2 | import { HEX } from '@jdesignlab/theme';
3 | import type { FontTransformToken, FontStyleToken, FontDecoration, FontAlign } from '../types';
4 |
5 | export const createFontStyle = (
6 | transform: FontTransformToken,
7 | style: FontStyleToken,
8 | decoration: FontDecoration,
9 | align: FontAlign,
10 | color: HEX,
11 | truncate: boolean
12 | ) => {
13 | let truncateStyle = {};
14 | if (truncate) {
15 | truncateStyle = {
16 | whiteSpace: 'nowrap',
17 | overflow: 'hidden',
18 | textOverflow: 'ellipsis'
19 | };
20 | }
21 | return css({
22 | ...truncateStyle,
23 | textTransform: transform,
24 | fontStyle: style,
25 | textDecoration: decoration,
26 | textAlign: align,
27 | color
28 | });
29 | };
30 |
--------------------------------------------------------------------------------
/packages/text/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tsconfig.json",
3 | "include": ["./src"],
4 | "compilerOptions": {
5 | "declaration": true,
6 | "isolatedModules": false,
7 | "esModuleInterop": true, // es module이 아니어도 import export 쓸 수 있게 함
8 | "importHelpers": true,
9 | "types": ["@emotion/react/types/css-prop", "@types/jest", "@testing-library/jest-dom"],
10 | "jsx": "react-jsx",
11 | "jsxImportSource": "@emotion/react"
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/packages/textarea/jest.config.ts:
--------------------------------------------------------------------------------
1 | import type { Config } from 'jest';
2 |
3 | const config: Config = {
4 | preset: 'ts-jest',
5 | testEnvironment: 'jsdom',
6 | setupFilesAfterEnv: ['/setup-jest.ts'],
7 | transform: {
8 | '^.+\\.[jt]sx?$': 'ts-jest',
9 | '^.+\\.(css|scss|sass|less)$': 'jest-preview/transforms/css',
10 | '^(?!.*\\.(js|jsx|mjs|cjs|ts|tsx|css|json)$)': 'jest-preview/transforms/file'
11 | }
12 | };
13 |
14 | export default config;
15 |
--------------------------------------------------------------------------------
/packages/textarea/setup-jest.ts:
--------------------------------------------------------------------------------
1 | import '@testing-library/jest-dom/';
2 |
--------------------------------------------------------------------------------
/packages/textarea/src/components/Textarea.tsx:
--------------------------------------------------------------------------------
1 | /** @jsxImportSource @emotion/react */
2 | import { forwardRef } from 'react';
3 | import { filterComponent } from '@jdesignlab/react-utils';
4 | import { useTextarea } from '../hooks/useTextarea';
5 | import { TextareaProvider } from './TextareaContext';
6 | import { TextareaContainer } from './TextareaContainer';
7 | import { TextareaLabel } from './TextareaLabel';
8 | import type { TextAreaProps } from '../types';
9 |
10 | type ExtendedTextAreaProps = TextAreaProps & { Label?: typeof TextareaLabel };
11 | export const Textarea = Object.assign(
12 | forwardRef((textAreaProps, ref) => {
13 | const { children, ...propsWithoutChildren } = textAreaProps;
14 | const textareaLabel = filterComponent(children, TextareaLabel, true);
15 | return (
16 |
17 |
18 |
19 | );
20 | }),
21 | {
22 | Label: TextareaLabel
23 | }
24 | );
25 |
--------------------------------------------------------------------------------
/packages/textarea/src/components/TextareaLabel.tsx:
--------------------------------------------------------------------------------
1 | /** @jsxImportSource @emotion/react */
2 | import { useContext } from 'react';
3 | import { Text } from '@jdesignlab/typography';
4 | import { TEXTAREA_LABEL_COLOR } from '../constants';
5 | import { createLabelStyle } from '../styles/createLabelStyle';
6 | import { TextareaContext } from './TextareaContext';
7 | import { useTextarea } from '../hooks/useTextarea';
8 | import type { TextareaLabelProps } from '../types';
9 |
10 | export const TextareaLabel = (props: TextareaLabelProps) => {
11 | const { children, ...attributesWithoutChildren } = props;
12 | const { getChildText } = useTextarea();
13 | const { textareaId } = useContext(TextareaContext);
14 | const labelStype = createLabelStyle(TEXTAREA_LABEL_COLOR);
15 | const labelText = getChildText(props.children);
16 |
17 | return (
18 |
23 | );
24 | };
25 |
--------------------------------------------------------------------------------
/packages/textarea/src/constants.ts:
--------------------------------------------------------------------------------
1 | import { StyleProps } from './types';
2 | import type { ColorToken, HEX } from '@jdesignlab/theme';
3 |
4 | const DEFAULT_STYLE: Required = {
5 | label: '',
6 | resize: 'none',
7 | color: 'grey-base',
8 | appearance: 'standard',
9 | width: 320,
10 | height: 64,
11 | maxWidth: 480,
12 | maxHeight: 120,
13 | maxLength: null
14 | };
15 |
16 | const TEXTAREA_TEXT_COLOR: HEX = '#444444';
17 | const TEXTAREA_PLACEHOLDER_COLOR: ColorToken = 'grey-lighten1';
18 | const TEXTAREA_LABEL_COLOR: ColorToken = 'grey-darken2';
19 | const TEXTAREA_ID_PREFIX: string = 'jds-textarea';
20 |
21 | export { TEXTAREA_TEXT_COLOR, DEFAULT_STYLE, TEXTAREA_ID_PREFIX, TEXTAREA_LABEL_COLOR, TEXTAREA_PLACEHOLDER_COLOR };
22 |
--------------------------------------------------------------------------------
/packages/textarea/src/hooks/useSmart.ts:
--------------------------------------------------------------------------------
1 | import { useCallback, useRef } from 'react';
2 | import { callHandler } from '@jdesignlab/utils';
3 | import type { ChangeEvent, FormEventHandler } from 'react';
4 | import type { ResizeProps } from '../types';
5 |
6 | export const useSmart = (onChange: FormEventHandler | undefined, resize: ResizeProps) => {
7 | const textareaRef = useRef(null);
8 |
9 | const handleResizeHeight = useCallback(() => {
10 | const textArea = textareaRef.current;
11 | if (textArea) {
12 | textArea.style.height = '0px';
13 | textArea.style.height = `${textArea.scrollHeight}px`;
14 | }
15 | }, [textareaRef]);
16 |
17 | const handleChange = () => {
18 | if (resize === 'smart') {
19 | return callHandler(handleResizeHeight, onChange);
20 | }
21 | return onChange;
22 | };
23 |
24 | return { textareaRef, handleChange };
25 | };
26 |
--------------------------------------------------------------------------------
/packages/textarea/src/hooks/useTextarea.ts:
--------------------------------------------------------------------------------
1 | import { Children, isValidElement } from 'react';
2 |
3 | export const useTextarea = () => {
4 | const getChildText = (children: React.ReactNode) => {
5 | let childText = '';
6 | if (children) {
7 | Children.forEach(children, child => {
8 | if (isValidElement(child)) {
9 | return typeof child.props.children === 'string'
10 | ? (childText += child.props.children)
11 | : (childText += getChildText(child.props.children));
12 | } else if (typeof child === 'string') {
13 | childText += child;
14 | }
15 | });
16 | }
17 | return childText;
18 | };
19 |
20 | const getLabelId = (children: React.ReactNode) => {
21 | let labelId = '';
22 | Children.forEach(children, child => {
23 | if (isValidElement(child) && child.props.id) {
24 | labelId = child.props.id;
25 | }
26 | });
27 | return labelId || null;
28 | };
29 |
30 | return { getChildText, getLabelId };
31 | };
32 |
--------------------------------------------------------------------------------
/packages/textarea/src/index.ts:
--------------------------------------------------------------------------------
1 | export * from './components/Textarea';
2 |
--------------------------------------------------------------------------------
/packages/textarea/src/styles/createLabelStyle.ts:
--------------------------------------------------------------------------------
1 | import { css } from '@emotion/react';
2 | import { getColorByToken } from '@jdesignlab/theme';
3 | import type { ColorToken } from '@jdesignlab/theme';
4 |
5 | export const createLabelStyle = (labelColor: ColorToken) => {
6 | const upsideLabel = {
7 | top: 0,
8 | lineHeight: '0.3',
9 | fontSize: '14px',
10 | background: 'white',
11 | color: `${getColorByToken(labelColor)}`
12 | };
13 |
14 | return css({
15 | ...upsideLabel,
16 | fontWeight: 'bold',
17 | position: 'absolute',
18 | left: '16px',
19 | display: 'block',
20 | transform: 'translateY(-50%)',
21 | transition: 'all .15s'
22 | });
23 | };
24 |
--------------------------------------------------------------------------------
/packages/textarea/src/styles/createWrapperStyle.ts:
--------------------------------------------------------------------------------
1 | import { css } from '@emotion/react';
2 |
3 | export const createWrapperStyle = (width: number) => {
4 | return css({
5 | position: 'relative',
6 | display: 'inline-block',
7 | width: width ? `${width}px` : '100%'
8 | });
9 | };
10 |
--------------------------------------------------------------------------------
/packages/textarea/src/types.ts:
--------------------------------------------------------------------------------
1 | import type { ColorToken } from '@jdesignlab/theme';
2 | import type { ReactNode, HTMLAttributes } from 'react';
3 |
4 | export interface ReturnContext {
5 | textareaId: string;
6 | styleProps: Required;
7 | textareaProps: HTMLAttributes;
8 | }
9 | export type ResizeProps = 'vertical' | 'horizontal' | 'smart' | 'none';
10 | export type ApperanceProps = 'standard' | 'none';
11 | export type StyleProps = Pick<
12 | TextAreaProps,
13 | 'width' | 'maxWidth' | 'maxHeight' | 'maxLength' | 'color' | 'resize' | 'appearance' | 'label' | 'height'
14 | >;
15 |
16 | export interface TextareaLabelProps extends HTMLAttributes {
17 | children: ReactNode;
18 | }
19 |
20 | export interface TextAreaProps extends HTMLAttributes {
21 | label?: string;
22 | width?: number;
23 | height?: number;
24 | maxWidth?: number;
25 | maxHeight?: number;
26 | maxLength?: number | null;
27 | color?: ColorToken;
28 | resize?: ResizeProps;
29 | appearance?: ApperanceProps;
30 | children?: ReactNode;
31 | disabled?: boolean;
32 | }
33 |
--------------------------------------------------------------------------------
/packages/textarea/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tsconfig.json",
3 | "include": ["./src"],
4 | "compilerOptions": {
5 | "declaration": true,
6 | "isolatedModules": false,
7 | "esModuleInterop": true, // es module이 아니어도 import export 쓸 수 있게 함
8 | "importHelpers": true,
9 | "types": ["@emotion/react/types/css-prop", "@types/jest", "@testing-library/jest-dom"],
10 | "jsx": "react-jsx",
11 | "jsxImportSource": "@emotion/react"
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/packages/theme/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # @jdesignlab/theme
2 |
3 | ## 0.7.0
4 |
5 | ### Minor Changes
6 |
7 | - change text color by background
8 |
9 | ## 0.6.0
10 |
11 | ### Minor Changes
12 |
13 | - black color removal and colors token utilization
14 |
15 | ## 0.5.0
16 |
17 | ### Minor Changes
18 |
19 | - remove clean-package
20 |
21 | ## 0.4.0
22 |
23 | ### Minor Changes
24 |
25 | - change publish config
26 |
27 | ## 0.3.0
28 |
29 | ### Minor Changes
30 |
31 | - minor
32 |
--------------------------------------------------------------------------------
/packages/theme/README.md:
--------------------------------------------------------------------------------
1 | # theme
2 |
--------------------------------------------------------------------------------
/packages/theme/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@jdesignlab/theme",
3 | "version": "0.7.0",
4 | "packageManager": "yarn@3.3.1",
5 | "main": "src/index.ts",
6 | "sideEffects": false,
7 | "files": [
8 | "dist"
9 | ],
10 | "scripts": {
11 | "build": "tsup src --dts --format esm,cjs",
12 | "build:clean": "rimraf dist/"
13 | },
14 | "devDependencies": {
15 | "rimraf": "^5.0.1",
16 | "ts-node": "^10.9.1",
17 | "tslib": "^2.5.0",
18 | "tsup": "^6.7.0",
19 | "typescript": "^4.9.5"
20 | },
21 | "publishConfig": {
22 | "access": "public",
23 | "directory": "_release/package",
24 | "main": "./dist/index.js",
25 | "module": "./dist/index.mjs",
26 | "types": "./dist/index.d.ts"
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/packages/theme/src/index.ts:
--------------------------------------------------------------------------------
1 | /**types */
2 | export * from './types/color';
3 | export * from './types/spacings';
4 | export * from './types/classVariants';
5 | /**token constants */
6 | export * from './token/colors';
7 | export * from './token/opacity';
8 | export * from './token/spacings';
9 | export * from './token/zIndices';
10 | export * from './token/shadows';
11 | /**utils */
12 | export * from './utils/getColorbyToken';
13 | export * from './utils/getColorByTokenOrHex';
14 | export * from './utils/createClassVariant';
15 | export * from './utils/setTextColorByBackground';
16 |
--------------------------------------------------------------------------------
/packages/theme/src/token/opacity.ts:
--------------------------------------------------------------------------------
1 | export const OPACITY_0 = '00';
2 | export const OPACITY_10 = '1a';
3 | export const OPACITY_20 = '33';
4 | export const OPACITY_25 = '40';
5 | export const OPACITY_30 = '4d';
6 | export const OPACITY_40 = '66';
7 | export const OPACITY_50 = '7f';
8 | export const OPACITY_60 = '99';
9 | export const OPACITY_70 = 'b3';
10 | export const OPACITY_75 = 'bf';
11 | export const OPACITY_80 = 'cc';
12 | export const OPACITY_90 = 'e5';
13 | export const OPACITY_100 = 'ff';
14 |
--------------------------------------------------------------------------------
/packages/theme/src/token/spacings.ts:
--------------------------------------------------------------------------------
1 | import { SpacingType } from '../types/spacings';
2 |
3 | const BASE_SPACING: number = 4;
4 | const SAPCING_LENGTH: number = 16;
5 |
6 | const generateSpacingToken = (spacing: number) => {
7 | return `${spacing * BASE_SPACING}px`;
8 | };
9 |
10 | const spacingFactory = (length: number): SpacingType => {
11 | let spacingTokens: SpacingType = {};
12 | for (let i = 1; i <= length; i++) {
13 | spacingTokens[i] = generateSpacingToken(i);
14 | }
15 | return spacingTokens;
16 | };
17 |
18 | export default Object.freeze(spacingFactory(SAPCING_LENGTH));
19 |
--------------------------------------------------------------------------------
/packages/theme/src/token/zIndices.ts:
--------------------------------------------------------------------------------
1 | export const Z_INDEX_HIDE = 1;
2 | export const Z_INDEX_AUTO = 'auto';
3 | export const Z_INDEX_BASE = 0;
4 | export const Z_INDEX_DOCKED = 10;
5 | export const Z_INDEX_DROPDOWN = 1000;
6 | export const Z_INDEX_STICKY = 1100;
7 | export const Z_INDEX_BANNER = 1200;
8 | export const Z_INDEX_OVERLAY = 1300;
9 | export const Z_INDEX_MODAL = 1400;
10 | export const Z_INDEX_POPOVER = 1500;
11 | export const Z_INDEX_SKIPLINK = 1600;
12 | export const Z_INDEX_TOAST = 1700;
13 | export const Z_INDEX_TOOLTIP = 1800;
14 |
--------------------------------------------------------------------------------
/packages/theme/src/types/classVariants.ts:
--------------------------------------------------------------------------------
1 | export type JDesignSystemComponent =
2 | | 'box'
3 | | 'checkbox'
4 | | 'flex'
5 | | 'modal'
6 | | 'tabs'
7 | | 'tooltip'
8 | | 'button'
9 | | 'drawer'
10 | | 'select'
11 | | 'popover'
12 | | 'textarea'
13 | | 'card'
14 | | 'dropdown'
15 | | 'input'
16 | | 'radio'
17 | | 'stack';
18 |
19 | export type JDesignSystemElementRoles =
20 | | 'overlay'
21 | | 'wrapper'
22 | | 'group'
23 | | 'content'
24 | | 'label'
25 | | 'ul'
26 | | 'ol'
27 | | 'item'
28 | | 'footer'
29 | | 'header'
30 | | 'trigger'
31 | | 'message'
32 | | 'article'
33 | | 'button'
34 | | 'input'
35 | | 'portal'
36 | | 'icon';
37 |
38 | export type ClassNameVariant =
39 | | `j-${JDesignSystemComponent}__${string}-${JDesignSystemElementRoles}`
40 | | `j-${JDesignSystemComponent}__${JDesignSystemElementRoles}`;
41 |
--------------------------------------------------------------------------------
/packages/theme/src/types/spacings.ts:
--------------------------------------------------------------------------------
1 | export type SpacingType = { [key: number]: string };
2 |
--------------------------------------------------------------------------------
/packages/theme/src/utils/createClassVariant.ts:
--------------------------------------------------------------------------------
1 | import type { JDesignSystemComponent, JDesignSystemElementRoles, ClassNameVariant } from '../types/classVariants';
2 |
3 | export const createClassVariant = (
4 | component: JDesignSystemComponent,
5 | element: JDesignSystemElementRoles,
6 | modifier?: string
7 | ): ClassNameVariant => {
8 | return modifier ? `j-${component}__${modifier}-${element}` : `j-${component}__${element}`;
9 | };
10 |
--------------------------------------------------------------------------------
/packages/theme/src/utils/getColorByTokenOrHex.ts:
--------------------------------------------------------------------------------
1 | import { ColorToken, HEX } from '../types/color';
2 | import { getColorByToken } from './getColorbyToken';
3 |
4 | const isHexType = (color: ColorToken | HEX): color is HEX => {
5 | const hexRegex = /^#([A-Fa-f0-9]{3}){1,2}$/;
6 | return hexRegex.test(color);
7 | };
8 |
9 | export const getColorByTokenOrHex = (color: ColorToken | HEX) => {
10 | if (isHexType(color)) {
11 | return color;
12 | }
13 | return getColorByToken(color);
14 | };
15 |
--------------------------------------------------------------------------------
/packages/theme/src/utils/getColorbyToken.ts:
--------------------------------------------------------------------------------
1 | import { variantPresetColors } from '../token/colors';
2 | import type { HEX, ColorToken } from '../types/color';
3 |
4 | export const getColorByToken = (colorToken: ColorToken): HEX => {
5 | const [prefix, suffix] = colorToken.split('-');
6 | return prefix && suffix ? variantPresetColors[prefix][suffix] : variantPresetColors[prefix];
7 | };
8 |
9 | export const hexToRgba = (hex: HEX, opacity: number) => {
10 | return `rgba(${parseInt(hex.substring(1, 3), 16)},${parseInt(hex.substring(3, 5), 16)},${parseInt(
11 | hex.substring(5, 7),
12 | 16
13 | )},${opacity})`;
14 | };
15 |
--------------------------------------------------------------------------------
/packages/theme/src/utils/setTextColorByBackground.ts:
--------------------------------------------------------------------------------
1 | import { variantPresetColors } from '../token/colors';
2 | import type { HEX } from '../types/color';
3 |
4 | export const setTextColorByBackground = (color: HEX | string) => {
5 | const hexValue = color.replace('#', '');
6 | const rgbValues = hexValue.match(/.{1,2}/g)?.map(value => parseInt(value, 16)) ?? [];
7 | const brightness = (rgbValues[0] + rgbValues[1] + rgbValues[2]) / 3;
8 | if (brightness < 200) {
9 | return variantPresetColors.grey.lighten4;
10 | } else {
11 | return variantPresetColors.font;
12 | }
13 | };
14 |
--------------------------------------------------------------------------------
/packages/theme/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tsconfig.json",
3 | "include": ["./src"],
4 | "compilerOptions": {
5 | "declaration": true,
6 | "isolatedModules": false,
7 | "esModuleInterop": true, // es module이 아니어도 import export 쓸 수 있게 함
8 | "importHelpers": true
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/packages/tooltip/.babelrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "presets": ["@babel/env", ["@babel/preset-react", { "runtime": "automatic", "importSource": "@emotion/react" }]],
3 | "plugins": ["@emotion/babel-plugin"]
4 | }
5 |
--------------------------------------------------------------------------------
/packages/tooltip/README.md:
--------------------------------------------------------------------------------
1 | # Tooltip
2 |
3 | 사용자에게 모달(팝업) 형태로 컨텐츠를 표시하는 UI요소입니다.
4 |
5 | ## Usage
6 |
7 | [Storybook](https://designsystemlab.github.io/design-system/?path=/docs/data-display-tooltip--basic)
8 |
9 | ```jsx
10 |
11 |
12 |
13 |
14 | ```
15 |
16 | ## Props
17 |
18 | ### Tooltip
19 |
20 | | Property | Allow Types | Description | Default |
21 | | --------- | ------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------- | ------- |
22 | | placement | `top-left` `top` `top-right` `right` `right-top` `right-bottom` `left` `left-top` `left-bottom` `bottom-right` `bottom` `bottom-left` | 툴팁이 나타날 위치를 조정합니다. | `top` |
23 | | gap | `number` | 툴팁의 간격을 조정합니다. | `4` |
24 |
--------------------------------------------------------------------------------
/packages/tooltip/jest.config.ts:
--------------------------------------------------------------------------------
1 | import type { Config } from 'jest';
2 |
3 | const config: Config = {
4 | preset: 'ts-jest',
5 | testEnvironment: 'jsdom',
6 | setupFilesAfterEnv: ['/setup-jest.ts'],
7 | transform: {
8 | '^.+\\.[jt]sx?$': 'ts-jest',
9 | '^.+\\.(css|scss|sass|less)$': 'jest-preview/transforms/css',
10 | '^(?!.*\\.(js|jsx|mjs|cjs|ts|tsx|css|json)$)': 'jest-preview/transforms/file'
11 | }
12 | };
13 |
14 | export default config;
15 |
--------------------------------------------------------------------------------
/packages/tooltip/setup-jest.ts:
--------------------------------------------------------------------------------
1 | import '@testing-library/jest-dom/';
2 |
--------------------------------------------------------------------------------
/packages/tooltip/src/components/Tooltip.tsx:
--------------------------------------------------------------------------------
1 | /** @jsxImportSource @emotion/react */
2 | import { tooltipWrapperStyle } from '../styles';
3 | import type { TooltipProps } from '../types';
4 | import { useState, useRef, useId } from 'react';
5 | import TooltipContext from '../context';
6 | import Target from './TooltipTarget';
7 | import Content from './TooltipContent';
8 |
9 | export const Tooltip = (props: TooltipProps) => {
10 | const { children } = props;
11 | const [isHovering, setIsHovering] = useState(false);
12 | const [targetEl, setTargetEl] = useState(null);
13 | const id = useId();
14 | const gap = Number(props.gap) || 4;
15 |
16 | const providerValue = {
17 | id: `tooltip-${id}`,
18 | targetEl,
19 | setTargetEl,
20 | placement: props.placement ?? 'top',
21 | gap,
22 | isHovering,
23 | setIsHovering
24 | };
25 |
26 | return (
27 |
28 | {children}
29 |
30 | );
31 | };
32 |
33 | Tooltip.displayName = 'Tooltip';
34 | Tooltip.Target = Target;
35 | Tooltip.Content = Content;
36 |
--------------------------------------------------------------------------------
/packages/tooltip/src/components/TooltipTarget.tsx:
--------------------------------------------------------------------------------
1 | /** @jsxImportSource @emotion/react */
2 | import { tooltipTargetStyle } from '../styles';
3 | import type { TooltipTargetPrpos } from '../types';
4 | import { useContext } from 'react';
5 | import TooltipContext from '../context';
6 |
7 | const Target = (props: TooltipTargetPrpos) => {
8 | const { children } = props;
9 | const { id, setIsHovering, setTargetEl } = useContext(TooltipContext);
10 |
11 | const onMouseEnter = () => {
12 | setIsHovering(true);
13 | };
14 |
15 | const onMouseLeave = () => {
16 | setIsHovering(false);
17 | };
18 |
19 | return (
20 |
31 | {children}
32 |
33 | );
34 | };
35 |
36 | Target.displayName = 'Tooltip.Target';
37 | export default Target;
38 |
--------------------------------------------------------------------------------
/packages/tooltip/src/context.ts:
--------------------------------------------------------------------------------
1 | import { createContext } from 'react';
2 | import type { TooltipAnchor } from './types';
3 |
4 | const TooltipContext = createContext({
5 | id: '',
6 | targetEl: null,
7 | setTargetEl: (value: HTMLDivElement) => {},
8 | placement: 'top' as TooltipAnchor,
9 | isHovering: false,
10 | setIsHovering: (value: boolean) => {},
11 | gap: 0
12 | });
13 | export default TooltipContext;
14 |
--------------------------------------------------------------------------------
/packages/tooltip/src/index.ts:
--------------------------------------------------------------------------------
1 | export * from './components/Tooltip';
2 |
--------------------------------------------------------------------------------
/packages/tooltip/src/styles.ts:
--------------------------------------------------------------------------------
1 | import { css } from '@emotion/react';
2 |
3 | export const tooltipWrapperStyle = css({
4 | position: 'relative'
5 | });
6 | export const tooltipContentStyle = css({
7 | position: 'absolute',
8 | backgroundColor: '#000000ad',
9 | color: '#ffffffc7',
10 | zIndex: '100',
11 | display: 'none',
12 | padding: '4px 8px',
13 | border: 'solid gray 1px',
14 | borderRadius: '2px',
15 | whiteSpace: 'pre',
16 | '&.tooltip_open': {
17 | display: 'inline'
18 | }
19 | });
20 |
21 | export const tooltipTargetStyle = {};
22 |
--------------------------------------------------------------------------------
/packages/tooltip/src/types.ts:
--------------------------------------------------------------------------------
1 | import { CSSObject } from '@emotion/react';
2 |
3 | export type TooltipAnchor =
4 | | 'top-left'
5 | | 'top'
6 | | 'top-right'
7 | | 'right'
8 | | 'right-top'
9 | | 'right-bottom'
10 | | 'left'
11 | | 'left-top'
12 | | 'left-bottom'
13 | | 'bottom-right'
14 | | 'bottom'
15 | | 'bottom-left';
16 |
17 | export interface TooltipProps extends CSSObject {
18 | [propertiesName: string]: any;
19 | children?: React.ReactNode;
20 | placement?: TooltipAnchor;
21 | gap?: number | string;
22 | }
23 |
24 | export interface TooltipContentProps extends CSSObject {
25 | children?: string;
26 | style?: CSSObject;
27 | }
28 |
29 | export interface TooltipTargetPrpos {
30 | children?: React.ReactNode;
31 | }
32 |
--------------------------------------------------------------------------------
/packages/tooltip/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tsconfig.json",
3 | "include": ["./src"],
4 | "compilerOptions": {
5 | "declaration": true,
6 | "isolatedModules": false,
7 | "esModuleInterop": true, // es module이 아니어도 import export 쓸 수 있게 함
8 | "importHelpers": true,
9 | "types": ["@emotion/react/types/css-prop"],
10 | "jsx": "react-jsx",
11 | "jsxImportSource": "@emotion/react"
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/packages/utils/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # @jdesignlab/utils
2 |
3 | ## 0.5.0
4 |
5 | ### Minor Changes
6 |
7 | - remove clean-package
8 |
9 | ## 0.4.0
10 |
11 | ### Minor Changes
12 |
13 | - change publish config
14 |
15 | ## 0.3.0
16 |
17 | ### Minor Changes
18 |
19 | - minor
20 |
--------------------------------------------------------------------------------
/packages/utils/README.md:
--------------------------------------------------------------------------------
1 | # utils
2 |
--------------------------------------------------------------------------------
/packages/utils/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@jdesignlab/utils",
3 | "version": "0.5.0",
4 | "packageManager": "yarn@3.3.1",
5 | "main": "src/index.ts",
6 | "sideEffects": false,
7 | "files": [
8 | "dist"
9 | ],
10 | "scripts": {
11 | "build": "tsup src --dts --format esm,cjs",
12 | "build:clean": "rimraf dist/"
13 | },
14 | "devDependencies": {
15 | "@types/react": "^18.0.27",
16 | "@types/react-dom": "^18.0.10",
17 | "rimraf": "^5.0.1",
18 | "tslib": "^2.5.0",
19 | "tsup": "^6.7.0",
20 | "typescript": "^4.9.4"
21 | },
22 | "publishConfig": {
23 | "access": "public",
24 | "directory": "_release/package",
25 | "main": "./dist/index.js",
26 | "module": "./dist/index.mjs",
27 | "types": "./dist/index.d.ts"
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/packages/utils/src/calculateElementPosition.ts:
--------------------------------------------------------------------------------
1 | export const calculateElementPosition = (targetEl: HTMLElement, contentEl: HTMLElement, gap: number) => {
2 | const targetW = targetEl.offsetWidth;
3 | const targetH = targetEl.offsetHeight;
4 |
5 | const contentW = contentEl.offsetWidth;
6 | const contentH = contentEl.offsetHeight;
7 |
8 | const centerX = { left: targetW / 2, transform: `translateX(-${contentW / 2}px)` };
9 | const centerY = { bottom: targetH / 2, transform: `translateY(${contentH / 2}px)` };
10 | const moveTop = { bottom: `${targetH + gap}px` };
11 | const moveBottom = { top: `${targetH + gap}px` };
12 | const moveRight = { left: `${targetW + gap}px` };
13 | const moveLeft = { left: `-${contentW + gap}px` };
14 | const onRight = { left: targetW - contentW };
15 | const onBottom = { top: targetH - contentH };
16 |
17 | return { centerX, centerY, moveTop, moveBottom, moveRight, moveLeft, onRight, onBottom };
18 | };
19 |
--------------------------------------------------------------------------------
/packages/utils/src/combineClassNames.ts:
--------------------------------------------------------------------------------
1 | export const combineClassNames = (classVariant: string, customClass: string | undefined) => {
2 | if (!customClass) return classVariant;
3 | else return `${customClass} ${classVariant}`;
4 | };
5 |
--------------------------------------------------------------------------------
/packages/utils/src/event.ts:
--------------------------------------------------------------------------------
1 | import type { EventType } from './eventTypes';
2 |
3 | export const callHandler = void>(defaultHandler: T, handler: T | undefined) => {
4 | return (event: EventType) => {
5 | defaultHandler?.(event);
6 | handler?.(event);
7 | };
8 | };
9 |
--------------------------------------------------------------------------------
/packages/utils/src/eventTypes.ts:
--------------------------------------------------------------------------------
1 | export type EventType = React.ChangeEvent &
2 | React.MouseEvent &
3 | React.ChangeEvent &
4 | React.KeyboardEvent;
5 |
--------------------------------------------------------------------------------
/packages/utils/src/index.ts:
--------------------------------------------------------------------------------
1 | export * from './event';
2 | export * from './eventTypes';
3 | export { calculateElementPosition } from './calculateElementPosition';
4 | export { combineClassNames } from './combineClassNames';
5 |
--------------------------------------------------------------------------------
/packages/utils/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tsconfig.json",
3 | "include": ["./src"],
4 | "compilerOptions": {
5 | "outDir": "./dist",
6 | "declaration": true,
7 | "isolatedModules": false,
8 | "esModuleInterop": true, // es module이 아니어도 import export 쓸 수 있게 함
9 | "importHelpers": true
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/setup-jest.ts:
--------------------------------------------------------------------------------
1 | import '@testing-library/jest-dom/';
2 |
--------------------------------------------------------------------------------
/tsupconfig.ts:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'tsup';
2 |
3 | export default defineConfig({
4 | entry: ['src'],
5 | clean: true,
6 | format: ['esm', 'cjs']
7 | });
8 |
--------------------------------------------------------------------------------