@wishket/design-system 2.2.0 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +58 -0
- package/dist/Components/Base/Layouts/Box/Box.d.ts +5 -5
- package/dist/Components/Base/Layouts/Box/Box.js +3 -2
- package/dist/Components/Base/Typography/Typography.d.ts +2 -1
- package/dist/Components/Base/Typography/Typography.js +1 -1
- package/dist/Components/Base/Typography/Typography.types.d.ts +4 -5
- package/dist/Components/Inputs/Calendar/Calendar.d.ts +2 -1
- package/dist/Components/Inputs/Calendar/Calendar.js +9 -8
- package/dist/Components/Inputs/Calendar/Calendar.parts.js +1 -1
- package/dist/Components/Inputs/Calendar/Calendar.types.d.ts +1 -0
- package/dist/Components/Navigations/GNBList/GNBList.d.ts +1 -1
- package/dist/Components/Navigations/GNBList/GNBList.parts.d.ts +3 -2
- package/dist/Components/Navigations/GNBList/GNBList.parts.js +10 -10
- package/dist/Components/Navigations/GNBList/GNBList.types.d.ts +8 -3
- package/dist/Components/Navigations/Menu/Menu.types.d.ts +53 -0
- package/dist/Components/Navigations/Menu/MenuBase.d.ts +21 -0
- package/dist/Components/Navigations/Menu/MenuBase.js +3 -0
- package/dist/Components/Navigations/Menu/MenuButton.d.ts +40 -0
- package/dist/Components/Navigations/Menu/MenuButton.js +39 -0
- package/dist/Components/Navigations/Menu/MenuLink.d.ts +43 -0
- package/dist/Components/Navigations/Menu/MenuLink.js +42 -0
- package/dist/Components/Navigations/Menu/index.d.ts +3 -1
- package/dist/Components/Navigations/TextLink/TextLink.d.ts +13 -35
- package/dist/Components/Navigations/TextLink/TextLink.js +11 -34
- package/dist/cjs/Components/Base/Layouts/Box/Box.js +3 -2
- package/dist/cjs/Components/Base/Typography/Typography.js +2 -2
- package/dist/cjs/Components/Inputs/Calendar/Calendar.js +7 -7
- package/dist/cjs/Components/Inputs/Calendar/Calendar.parts.js +6 -6
- package/dist/cjs/Components/Navigations/GNBList/GNBList.parts.js +11 -11
- package/dist/cjs/Components/Navigations/Menu/MenuBase.js +3 -0
- package/dist/cjs/Components/Navigations/Menu/MenuButton.js +39 -0
- package/dist/cjs/Components/Navigations/Menu/MenuLink.js +42 -0
- package/dist/cjs/Components/Navigations/TextLink/TextLink.js +11 -34
- package/dist/cjs/index.js +1 -1
- package/dist/index.js +1 -1
- package/package.json +7 -5
- package/scripts/codemods/README.md +178 -0
- package/scripts/codemods/__tests__/__fixtures__/add-as-link/already-has-as.input.tsx +6 -0
- package/scripts/codemods/__tests__/__fixtures__/add-as-link/already-has-as.output.tsx +6 -0
- package/scripts/codemods/__tests__/__fixtures__/add-as-link/basic.input.tsx +9 -0
- package/scripts/codemods/__tests__/__fixtures__/add-as-link/basic.output.tsx +10 -0
- package/scripts/codemods/__tests__/__fixtures__/add-as-link/existing-next-link-import.input.tsx +9 -0
- package/scripts/codemods/__tests__/__fixtures__/add-as-link/existing-next-link-import.output.tsx +9 -0
- package/scripts/codemods/__tests__/__fixtures__/add-as-link/menu-button-fallback.input.tsx +5 -0
- package/scripts/codemods/__tests__/__fixtures__/add-as-link/menu-button-fallback.output.tsx +5 -0
- package/scripts/codemods/__tests__/__fixtures__/add-as-link/unrelated-import.input.tsx +3 -0
- package/scripts/codemods/__tests__/__fixtures__/add-as-link/unrelated-import.output.tsx +3 -0
- package/scripts/codemods/__tests__/__fixtures__/menu-split/basic.input.tsx +8 -0
- package/scripts/codemods/__tests__/__fixtures__/menu-split/basic.output.tsx +8 -0
- package/scripts/codemods/__tests__/__fixtures__/menu-split/conflict.input.tsx +5 -0
- package/scripts/codemods/__tests__/__fixtures__/menu-split/conflict.output.tsx +6 -0
- package/scripts/codemods/__tests__/__fixtures__/menu-split/href-only.input.tsx +3 -0
- package/scripts/codemods/__tests__/__fixtures__/menu-split/href-only.output.tsx +3 -0
- package/scripts/codemods/__tests__/__fixtures__/menu-split/onclick-only.input.tsx +3 -0
- package/scripts/codemods/__tests__/__fixtures__/menu-split/onclick-only.output.tsx +3 -0
- package/scripts/codemods/__tests__/__fixtures__/menu-split/spread-props.input.tsx +3 -0
- package/scripts/codemods/__tests__/__fixtures__/menu-split/spread-props.output.tsx +4 -0
- package/scripts/codemods/__tests__/run-fixtures.cjs +100 -0
- package/scripts/codemods/add-as-link.ts +110 -0
- package/scripts/codemods/menu-split.ts +252 -0
- package/dist/Components/Navigations/Menu/Menu.d.ts +0 -81
- package/dist/Components/Navigations/Menu/Menu.js +0 -62
- package/dist/cjs/Components/Navigations/Menu/Menu.js +0 -2
package/README.md
CHANGED
|
@@ -82,6 +82,64 @@ export const Home = () => {
|
|
|
82
82
|
export default Home;
|
|
83
83
|
```
|
|
84
84
|
|
|
85
|
+
## Navigation 컴포넌트와 라우팅 라이브러리
|
|
86
|
+
|
|
87
|
+
`TextLink`, `Menu`, `GNBList.Item`은 기본적으로 `<a>` 태그로 렌더되며, `as` prop으로 라우팅 라이브러리의 Link를 주입할 수 있습니다.
|
|
88
|
+
|
|
89
|
+
### Next.js와 함께 사용
|
|
90
|
+
|
|
91
|
+
```tsx
|
|
92
|
+
import Link from 'next/link';
|
|
93
|
+
import { TextLink, Menu, GNBList } from '@wishket/design-system';
|
|
94
|
+
|
|
95
|
+
<TextLink as={Link} href="/about" text="About" />
|
|
96
|
+
<Menu as={Link} name="Settings" href="/settings" />
|
|
97
|
+
<GNBList.Item as={Link} href="/projects">프로젝트</GNBList.Item>
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
매 호출마다 `as`를 적기 번거롭다면 컨슈머 앱에서 wrapper를 한 번만 정의해두는 패턴을 권장합니다.
|
|
101
|
+
|
|
102
|
+
```tsx
|
|
103
|
+
// app/components/AppTextLink.tsx
|
|
104
|
+
import { ComponentProps } from 'react';
|
|
105
|
+
import Link from 'next/link';
|
|
106
|
+
import { TextLink } from '@wishket/design-system';
|
|
107
|
+
|
|
108
|
+
export const AppTextLink = (props: ComponentProps<typeof TextLink>) => (
|
|
109
|
+
<TextLink as={Link} {...props} />
|
|
110
|
+
);
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
### react-router와 함께 사용
|
|
114
|
+
|
|
115
|
+
`react-router`의 `Link`는 `to` prop을 쓰므로 `href` → `to` 어댑터가 필요합니다.
|
|
116
|
+
|
|
117
|
+
```tsx
|
|
118
|
+
import { Link as RouterLink } from 'react-router-dom';
|
|
119
|
+
|
|
120
|
+
const RouterLinkAdapter = ({
|
|
121
|
+
href,
|
|
122
|
+
...rest
|
|
123
|
+
}: { href: string } & React.ComponentProps<typeof RouterLink>) => (
|
|
124
|
+
<RouterLink to={href} {...rest} />
|
|
125
|
+
);
|
|
126
|
+
|
|
127
|
+
<TextLink as={RouterLinkAdapter} href="/about" text="About" />
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
### v3 마이그레이션
|
|
131
|
+
|
|
132
|
+
v3.0부터 위 컴포넌트들이 더 이상 자동으로 `next/link`를 사용하지 않습니다. 컨슈머 앱에서 일괄 변환을 원한다면 패키지에 포함된 jscodeshift codemod를 사용하세요.
|
|
133
|
+
|
|
134
|
+
```bash
|
|
135
|
+
npx jscodeshift \
|
|
136
|
+
-t node_modules/@wishket/design-system/scripts/codemods/add-as-link.ts \
|
|
137
|
+
--extensions=tsx,ts --parser=tsx \
|
|
138
|
+
src/
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
자세한 내용은 [`scripts/codemods/README.md`](./scripts/codemods/README.md)를 참고하세요.
|
|
142
|
+
|
|
85
143
|
## Customize Theme in Config File
|
|
86
144
|
|
|
87
145
|
```typescript
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export
|
|
3
|
-
as?:
|
|
4
|
-
}
|
|
1
|
+
import { ComponentPropsWithRef, ElementType, PropsWithChildren } from 'react';
|
|
2
|
+
export type BoxProps<T extends ElementType = 'div'> = {
|
|
3
|
+
as?: T;
|
|
4
|
+
} & PropsWithChildren<Omit<ComponentPropsWithRef<T>, 'as'>>;
|
|
5
5
|
/**
|
|
6
6
|
* @param {Object} props
|
|
7
7
|
* @param {ReactNode} props.children - 박스 내부에 렌더링할 컨텐츠
|
|
8
8
|
* @param {ElementType} [props.as='div'] - 렌더링할 HTML 요소
|
|
9
9
|
* @param {string} [props.className] - 추가적인 CSS 클래스
|
|
10
10
|
*/
|
|
11
|
-
declare const Box: import("react").ForwardRefExoticComponent<BoxProps & import("react").RefAttributes<
|
|
11
|
+
declare const Box: import("react").ForwardRefExoticComponent<Omit<BoxProps<ElementType>, "ref"> & import("react").RefAttributes<any>>;
|
|
12
12
|
export { Box };
|
|
@@ -4,5 +4,6 @@ import{jsx as e}from"react/jsx-runtime";import{twMerge as r}from"tailwind-merge"
|
|
|
4
4
|
* @param {ReactNode} props.children - 박스 내부에 렌더링할 컨텐츠
|
|
5
5
|
* @param {ElementType} [props.as='div'] - 렌더링할 HTML 요소
|
|
6
6
|
* @param {string} [props.className] - 추가적인 CSS 클래스
|
|
7
|
-
*/(e,r);if(Object.getOwnPropertySymbols){var c=Object.getOwnPropertySymbols(e);for(n=0;n<c.length;n++)t=c[n],r.indexOf(t)>=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(o[t]=e[t])}return o}const i=/*#__PURE__*/t(((t
|
|
8
|
-
|
|
7
|
+
*/(e,r);if(Object.getOwnPropertySymbols){var c=Object.getOwnPropertySymbols(e);for(n=0;n<c.length;n++)t=c[n],r.indexOf(t)>=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(o[t]=e[t])}return o}const i=/*#__PURE__*/t(((t,// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
8
|
+
i)=>{var{as:l,className:a,children:u}=t,b=c(t,["as","className","children"]);/*#__PURE__*/
|
|
9
|
+
return e(null!=l?l:"div",o(function(e){for(var r=1;r<arguments.length;r++){var t=null!=arguments[r]?arguments[r]:{},o=Object.keys(t);"function"==typeof Object.getOwnPropertySymbols&&(o=o.concat(Object.getOwnPropertySymbols(t).filter((function(e){return Object.getOwnPropertyDescriptor(t,e).enumerable})))),o.forEach((function(r){n(e,r,t[r])}))}return e}({ref:i,className:r("box-border",a)},b),{children:u}))}));i.displayName="Box";export{i as Box};
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { ElementType } from 'react';
|
|
1
2
|
import { TypographyProps } from './Typography.types';
|
|
2
3
|
/**
|
|
3
4
|
* Typography
|
|
@@ -7,5 +8,5 @@ import { TypographyProps } from './Typography.types';
|
|
|
7
8
|
* @param {string} [props.className] - 추가적인 CSS 클래스
|
|
8
9
|
* @param {keyof JSX.IntrinsicElements} [props.as='span'] - 렌더링할 HTML 요소
|
|
9
10
|
*/
|
|
10
|
-
declare const Typography: ({ children, variant, className, as, ...rest }: TypographyProps) => import("react/jsx-runtime").JSX.Element;
|
|
11
|
+
declare const Typography: <T extends ElementType = "span">({ children, variant, className, as, ...rest }: TypographyProps<T>) => import("react/jsx-runtime").JSX.Element;
|
|
11
12
|
export { Typography };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{jsx as t}from"react/jsx-runtime";import{twMerge as e}from"tailwind-merge";function n(t,e,n){return e in t?Object.defineProperty(t,e,{value:n,enumerable:!0,configurable:!0,writable:!0}):t[e]=n,t}function r(t,e){return e=null!=e?e:{},Object.getOwnPropertyDescriptors?Object.defineProperties(t,Object.getOwnPropertyDescriptors(e)):function(t){var e=Object.keys(t);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(t);e.push.apply(e,n)}return e}(Object(e)).forEach((function(n){Object.defineProperty(t,n,Object.getOwnPropertyDescriptor(e,n))})),t}function o(t,e){if(null==t)return{};var n,r,o=function(t,e){if(null==t)return{};var n,r,o={},c=Object.keys(t);for(r=0;r<c.length;r++)n=c[r],e.indexOf(n)>=0||(o[n]=t[n]);return o}(t,e);if(Object.getOwnPropertySymbols){var c=Object.getOwnPropertySymbols(t);for(r=0;r<c.length;r++)n=c[r],e.indexOf(n)>=0||Object.prototype.propertyIsEnumerable.call(t,n)&&(o[n]=t[n])}return o}const c=[{name:"title48",class:"typo-title48"},{name:"title32",class:"typo-title32"},{name:"title28",class:"typo-title28"},{name:"title24",class:"typo-title24"},{name:"subTitle20",class:"typo-subTitle20"},{name:"subTitle18",class:"typo-subTitle18"},{name:"contents18",class:"typo-contents18"},{name:"contents16",class:"typo-contents16"},{name:"body16",class:"typo-body16"},{name:"body14",class:"typo-body14"},{name:"body13",class:"typo-body13"},{name:"caption12",class:"typo-caption12"},{name:"caption11",class:"typo-caption11"}],a=a=>{var s,{children:l,variant:i,className:p,as:y
|
|
1
|
+
import{jsx as t}from"react/jsx-runtime";import{twMerge as e}from"tailwind-merge";function n(t,e,n){return e in t?Object.defineProperty(t,e,{value:n,enumerable:!0,configurable:!0,writable:!0}):t[e]=n,t}function r(t,e){return e=null!=e?e:{},Object.getOwnPropertyDescriptors?Object.defineProperties(t,Object.getOwnPropertyDescriptors(e)):function(t){var e=Object.keys(t);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(t);e.push.apply(e,n)}return e}(Object(e)).forEach((function(n){Object.defineProperty(t,n,Object.getOwnPropertyDescriptor(e,n))})),t}function o(t,e){if(null==t)return{};var n,r,o=function(t,e){if(null==t)return{};var n,r,o={},c=Object.keys(t);for(r=0;r<c.length;r++)n=c[r],e.indexOf(n)>=0||(o[n]=t[n]);return o}(t,e);if(Object.getOwnPropertySymbols){var c=Object.getOwnPropertySymbols(t);for(r=0;r<c.length;r++)n=c[r],e.indexOf(n)>=0||Object.prototype.propertyIsEnumerable.call(t,n)&&(o[n]=t[n])}return o}const c=[{name:"title48",class:"typo-title48"},{name:"title32",class:"typo-title32"},{name:"title28",class:"typo-title28"},{name:"title24",class:"typo-title24"},{name:"subTitle20",class:"typo-subTitle20"},{name:"subTitle18",class:"typo-subTitle18"},{name:"contents18",class:"typo-contents18"},{name:"contents16",class:"typo-contents16"},{name:"body16",class:"typo-body16"},{name:"body14",class:"typo-body14"},{name:"body13",class:"typo-body13"},{name:"caption12",class:"typo-caption12"},{name:"caption11",class:"typo-caption11"}],a=a=>{var s,{children:l,variant:i,className:p,as:y}=a,b=o(a,["children","variant","className","as"]);const u=null!=y?y:"span",m=(null===(s=c.find((t=>t.name===i)))||void 0===s?void 0:s.class)||"";/*#__PURE__*/
|
|
2
2
|
return t(u,r(function(t){for(var e=1;e<arguments.length;e++){var r=null!=arguments[e]?arguments[e]:{},o=Object.keys(r);"function"==typeof Object.getOwnPropertySymbols&&(o=o.concat(Object.getOwnPropertySymbols(r).filter((function(t){return Object.getOwnPropertyDescriptor(r,t).enumerable})))),o.forEach((function(e){n(t,e,r[e])}))}return t}({className:e("tracking-default",m,p)},b),{children:l}))};
|
|
3
3
|
/**
|
|
4
4
|
* Typography
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ElementType, PropsWithChildren } from 'react';
|
|
1
|
+
import { ComponentPropsWithoutRef, ElementType, PropsWithChildren } from 'react';
|
|
2
2
|
export declare const typographyVariants: {
|
|
3
3
|
readonly title48: "title48";
|
|
4
4
|
readonly title32: "title32";
|
|
@@ -15,9 +15,8 @@ export declare const typographyVariants: {
|
|
|
15
15
|
readonly caption11: "caption11";
|
|
16
16
|
};
|
|
17
17
|
export type TypographyVariants = (typeof typographyVariants)[keyof typeof typographyVariants];
|
|
18
|
-
export
|
|
18
|
+
export type TypographyProps<T extends ElementType = 'span'> = PropsWithChildren<{
|
|
19
19
|
variant: TypographyVariants;
|
|
20
20
|
className?: string;
|
|
21
|
-
as?:
|
|
22
|
-
|
|
23
|
-
}
|
|
21
|
+
as?: T;
|
|
22
|
+
}> & Omit<ComponentPropsWithoutRef<T>, 'as' | 'children' | 'className'>;
|
|
@@ -14,6 +14,7 @@ import { CalendarProps } from './Calendar.types';
|
|
|
14
14
|
* @param {boolean} [props.isError] - 에러 상태 표시 여부
|
|
15
15
|
* @param {string} [props.className] - 컨테이너에 머지될 클래스 (예: 부모 너비에 맞추기 위한 `w-full`)
|
|
16
16
|
* @param {string} [props.triggerClassName] - 트리거(TextFieldContainer)에 머지될 클래스
|
|
17
|
+
* @param {string} [props.dropdownClassName] - dropdown popup 영역에 머지될 클래스 (예: 모바일 풀너비 `w-full`)
|
|
17
18
|
* @param {string} [props.minDate] - 선택 가능한 최소 날짜 (YYYY-MM-DD). 이전 날짜 셀은 disabled 처리
|
|
18
19
|
* @param {string} [props.maxDate] - 선택 가능한 최대 날짜 (YYYY-MM-DD). 이후 날짜 셀은 disabled 처리
|
|
19
20
|
*
|
|
@@ -52,5 +53,5 @@ import { CalendarProps } from './Calendar.types';
|
|
|
52
53
|
* />
|
|
53
54
|
* ```
|
|
54
55
|
*/
|
|
55
|
-
declare const Calendar: ({ defaultDate, selected, onChange, disabled, placeholder, isError, className, triggerClassName, minDate, maxDate, }: CalendarProps) => import("react/jsx-runtime").JSX.Element;
|
|
56
|
+
declare const Calendar: ({ defaultDate, selected, onChange, disabled, placeholder, isError, className, triggerClassName, dropdownClassName, minDate, maxDate, }: CalendarProps) => import("react/jsx-runtime").JSX.Element;
|
|
56
57
|
export { Calendar };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"use client";import{jsxs as e,jsx as a}from"react/jsx-runtime";import{useState as t,useEffect as r}from"react";import{twMerge as s}from"tailwind-merge";import"../../DataDisplays/Avatar/Avatar.js";import{Typography as n}from"../../Base/Typography/Typography.js";import{Box as
|
|
1
|
+
"use client";import{jsxs as e,jsx as a}from"react/jsx-runtime";import{useState as t,useEffect as r}from"react";import{twMerge as s}from"tailwind-merge";import"../../DataDisplays/Avatar/Avatar.js";import{Typography as n}from"../../Base/Typography/Typography.js";import{Box as o}from"../../Base/Layouts/Box/Box.js";import"../../Base/Layouts/FullBleed/FullBleed.js";import{SystemIcon as i}from"../../DataDisplays/SystemIcon/SystemIcon.js";import"../../DataDisplays/SystemIcon/SystemIcon.constants.js";import"../../DataDisplays/Accordion/Accordion.js";import{TextFieldContainer as l}from"../TextFieldContainer/TextFieldContainer.js";import{SelectHeader as d,WeekHeader as m,DateBox as c}from"./Calendar.parts.js";import{generateDate as p,today as y,getKoreanTimeString as g,getMonthDate as x,isSameDate as h,isDateOutOfRange as u}from"./Calendar.utils.js";
|
|
2
2
|
/**
|
|
3
3
|
* 날짜를 선택할 수 있는 캘린더 컴포넌트입니다.
|
|
4
4
|
*
|
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
* @param {boolean} [props.isError] - 에러 상태 표시 여부
|
|
15
15
|
* @param {string} [props.className] - 컨테이너에 머지될 클래스 (예: 부모 너비에 맞추기 위한 `w-full`)
|
|
16
16
|
* @param {string} [props.triggerClassName] - 트리거(TextFieldContainer)에 머지될 클래스
|
|
17
|
+
* @param {string} [props.dropdownClassName] - dropdown popup 영역에 머지될 클래스 (예: 모바일 풀너비 `w-full`)
|
|
17
18
|
* @param {string} [props.minDate] - 선택 가능한 최소 날짜 (YYYY-MM-DD). 이전 날짜 셀은 disabled 처리
|
|
18
19
|
* @param {string} [props.maxDate] - 선택 가능한 최대 날짜 (YYYY-MM-DD). 이후 날짜 셀은 disabled 처리
|
|
19
20
|
*
|
|
@@ -51,12 +52,12 @@
|
|
|
51
52
|
* placeholder="시작일"
|
|
52
53
|
* />
|
|
53
54
|
* ```
|
|
54
|
-
*/const f=({defaultDate:f,selected:w,onChange:D,disabled:b,placeholder:j,isError:C,className:N,triggerClassName:$,
|
|
55
|
+
*/const f=({defaultDate:f,selected:w,onChange:D,disabled:b,placeholder:j,isError:C,className:N,triggerClassName:$,dropdownClassName:B,minDate:v,maxDate:A})=>{const[F,I]=t(!1),S=()=>{b||I((e=>!e))},T=f?p(f):y,[L,k]=t(w?p(w):T),z=w?p(w):T,{year:E,month:_,date:q}=g(z),{dateList:G}=x(L.year,L.month),H=[...Array.from({length:G[0].day},(()=>null)),...G],J=e=>{if(w&&h(e,z))return;if(u(e,v,A))return;const a=`${e.year}-${e.month}-${e.date}`;null==D||D(a),I(!1)};return r((()=>{!F&&w&&k(p(w));
|
|
55
56
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
56
|
-
}),[
|
|
57
|
-
/*#__PURE__*/a(
|
|
58
|
-
/*#__PURE__*/a(
|
|
59
|
-
/*#__PURE__*/a(n,{variant:"body16",className:s("text-w-gray-600 min-w-[178px]",!w&&"text-w-gray-300",b&&"text-w-gray-300"),"data-testid":"design-system-calendar--selected-date",children:w?`${
|
|
60
|
-
/*#__PURE__*/a(d,{visibleDate:
|
|
57
|
+
}),[F]),/*#__PURE__*/e(o,{className:s("relative h-fit w-fit select-none",N),"data-testid":"design-system-calendar--container",children:[
|
|
58
|
+
/*#__PURE__*/a(o,{className:"cursor-pointer",children:/*#__PURE__*/e(l,{isFocused:F,isError:C,isDisabled:b,testId:"design-system-calendar--trigger",onClick:S,className:$,children:[
|
|
59
|
+
/*#__PURE__*/a(i,{name:"medium_calendar",className:b||!w?"text-w-gray-300":"text-w-gray-400"}),
|
|
60
|
+
/*#__PURE__*/a(n,{variant:"body16",className:s("text-w-gray-600 min-w-[178px]",!w&&"text-w-gray-300",b&&"text-w-gray-300"),"data-testid":"design-system-calendar--selected-date",children:w?`${E} ${_} ${q}`:j})]})}),F&&/*#__PURE__*/a("div",{className:"fixed top-0 left-0 z-10 h-screen w-screen bg-transparent",onClick:S}),F&&/*#__PURE__*/e(o,{"data-testid":"design-system-calendar--content",className:s("border-w-gray-200 bg-w-white shadow-graymedium absolute top-[54px] z-30 flex w-[350px] flex-col gap-4 rounded-xl border px-[15px] py-[23px]",B),children:[
|
|
61
|
+
/*#__PURE__*/a(d,{visibleDate:L,onChange:e=>{k(e)}}),
|
|
61
62
|
/*#__PURE__*/a(m,{}),
|
|
62
|
-
/*#__PURE__*/a(
|
|
63
|
+
/*#__PURE__*/a(o,{className:"grid w-full grid-cols-7 place-content-center place-items-center gap-1",children:H.map(((e,t)=>{const r=!(!e||!w)&&h(e,z);return e?/*#__PURE__*/a(c,{date:e,selected:r,disabled:u(e,v,A),onChange:J},`${e.year}-${e.month}-${e.date}`):/*#__PURE__*/a(c,{disabled:!0},t)}))})]})]})};export{f as Calendar};
|
|
@@ -4,4 +4,4 @@ return e(l,{className:"flex h-[50px] w-full gap-4",children:[
|
|
|
4
4
|
/*#__PURE__*/t(l,{"data-testid":"design-system-calendar--to-prev-month",className:"size-6 cursor-pointer text-gray-600",onClick:()=>{i?null==o||o({year:a.year-1,month:12,date:1}):null==o||o({year:a.year,month:a.month-1,date:1})},children:/*#__PURE__*/t(n,{name:"large_arrow_left",className:"text-gray-600"})}),
|
|
5
5
|
/*#__PURE__*/e(r,{variant:"subTitle18",className:"h-fit w-full text-center leading-normal text-gray-900",children:[c," ",d]}),
|
|
6
6
|
/*#__PURE__*/t(l,{"data-testid":"design-system-calendar--to-next-month",className:"size-6 cursor-pointer text-gray-600",onClick:()=>{m?null==o||o({year:a.year+1,month:1,date:1}):null==o||o({year:a.year,month:a.month+1,date:1})},children:/*#__PURE__*/t(n,{name:"large_arrow_right",className:"text-gray-600"})})]})},c=({selected:e,date:n,disabled:s=!1,onChange:o})=>{const i=1===String(null==n?void 0:n.date).length?`0${null==n?void 0:n.date}`:null==n?void 0:n.date;/*#__PURE__*/
|
|
7
|
-
return t(l,{className:a("bg-w-white flex
|
|
7
|
+
return t(l,{className:a("bg-w-white flex aspect-square w-full max-w-[42px] cursor-pointer items-center justify-center rounded-full p-2 text-center",!s&&!e&&"hover:bg-primary-10",e&&"bg-primary",s&&"cursor-default"),onClick:()=>{s||null==o||o(n)},children:/*#__PURE__*/t(r,{variant:"body16",className:a("text-w-gray-900",e&&"text-w-white",s&&"text-w-gray-300"),children:i})})};export{c as DateBox,m as SelectHeader,i as WeekHeader};
|
|
@@ -51,6 +51,6 @@ declare const GNBList: {
|
|
|
51
51
|
UserInfo: ({ imgUrl, username, email, children, onClick, }: import("./GNBList.types").UserInfoProps) => import("react/jsx-runtime").JSX.Element;
|
|
52
52
|
List: ({ children }: import("react").PropsWithChildren) => import("react/jsx-runtime").JSX.Element;
|
|
53
53
|
SubList: ({ children }: import("react").PropsWithChildren) => import("react/jsx-runtime").JSX.Element;
|
|
54
|
-
Item: ({ hasNew, children, className, textClassName, href, ...rest }: import("./GNBList.types").GNBListItemProps) => import("react/jsx-runtime").JSX.Element;
|
|
54
|
+
Item: ({ hasNew, children, className, textClassName, href, as: LinkComponent, ...rest }: import("./GNBList.types").GNBListItemProps) => import("react/jsx-runtime").JSX.Element;
|
|
55
55
|
};
|
|
56
56
|
export { GNBList };
|
|
@@ -99,11 +99,12 @@ declare const SubList: ({ children }: PropsWithChildren) => import("react/jsx-ru
|
|
|
99
99
|
*
|
|
100
100
|
* @description
|
|
101
101
|
* 개별 메뉴 아이템을 렌더링합니다.
|
|
102
|
-
* - Next.js Link
|
|
102
|
+
* - 기본은 `<a>` 태그이며, `as` prop으로 Next.js Link 등 임의의 컴포넌트 주입 가능
|
|
103
103
|
* - 키보드 포커스 및 hover 스타일 지원
|
|
104
104
|
*
|
|
105
105
|
* @param {Object} props
|
|
106
106
|
* @param {string} props.href - 이동할 페이지 경로 (필수)
|
|
107
|
+
* @param {ElementType} [props.as='a'] - anchor로 렌더할 컴포넌트 (예: next/link)
|
|
107
108
|
* @param {ReactNode} props.children - 메뉴 텍스트
|
|
108
109
|
* @param {boolean} [props.hasNew=false] - New 뱃지 표시 여부
|
|
109
110
|
* @param {string} [props.className] - Link에 적용할 추가 CSS 클래스
|
|
@@ -131,5 +132,5 @@ declare const SubList: ({ children }: PropsWithChildren) => import("react/jsx-ru
|
|
|
131
132
|
* 특별 메뉴
|
|
132
133
|
* </Item>
|
|
133
134
|
*/
|
|
134
|
-
declare const Item: ({ hasNew, children, className, textClassName, href, ...rest }: GNBListItemProps) => import("react/jsx-runtime").JSX.Element;
|
|
135
|
+
declare const Item: ({ hasNew, children, className, textClassName, href, as: LinkComponent, ...rest }: GNBListItemProps) => import("react/jsx-runtime").JSX.Element;
|
|
135
136
|
export { Root, UserInfo, List, SubList, Item };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{jsx as e,jsxs as r}from"react/jsx-runtime";import{Children as a,Fragment as t}from"react";import{twMerge as l}from"tailwind-merge";import
|
|
1
|
+
import{jsx as e,jsxs as r}from"react/jsx-runtime";import{Children as a,Fragment as t}from"react";import{twMerge as l}from"tailwind-merge";import{Avatar as n}from"../../DataDisplays/Avatar/Avatar.js";import{Typography as o}from"../../Base/Typography/Typography.js";import{Box as s}from"../../Base/Layouts/Box/Box.js";import"../../Base/Layouts/FullBleed/FullBleed.js";import"../../DataDisplays/SystemIcon/SystemIcon.constants.js";import{NewBadge as i}from"../../DataDisplays/NewBadge/NewBadge.js";import{Divider as c}from"../../DataDisplays/Divider/Divider.js";import"../../DataDisplays/Accordion/Accordion.js";function m(e,r,a){return r in e?Object.defineProperty(e,r,{value:a,enumerable:!0,configurable:!0,writable:!0}):e[r]=a,e}function p(e){for(var r=1;r<arguments.length;r++){var a=null!=arguments[r]?arguments[r]:{},t=Object.keys(a);"function"==typeof Object.getOwnPropertySymbols&&(t=t.concat(Object.getOwnPropertySymbols(a).filter((function(e){return Object.getOwnPropertyDescriptor(a,e).enumerable})))),t.forEach((function(r){m(e,r,a[r])}))}return e}function f(e,r){return r=null!=r?r:{},Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(r)):function(e){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);r.push.apply(r,a)}return r}(Object(r)).forEach((function(a){Object.defineProperty(e,a,Object.getOwnPropertyDescriptor(r,a))})),e}function u(e,r){if(null==e)return{};var a,t,l=function(e,r){if(null==e)return{};var a,t,l={},n=Object.keys(e);for(t=0;t<n.length;t++)a=n[t],r.indexOf(a)>=0||(l[a]=e[a]);return l}
|
|
2
2
|
/**
|
|
3
3
|
* GNB 리스트의 루트 컴포넌트
|
|
4
4
|
*
|
|
@@ -31,16 +31,16 @@ import{jsx as e,jsxs as r}from"react/jsx-runtime";import{Children as a,Fragment
|
|
|
31
31
|
* <Item href="/logout">로그아웃</Item>
|
|
32
32
|
* </SubList>
|
|
33
33
|
* </Root>
|
|
34
|
-
*/(e,r);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);for(t=0;t<n.length;t++)a=n[t],r.indexOf(a)>=0||Object.prototype.propertyIsEnumerable.call(e,a)&&(l[a]=e[a])}return l}const
|
|
35
|
-
/*#__PURE__*/e(
|
|
36
|
-
return e(s,{as:"nav","aria-label":"네비게이션 메뉴",className:l("absolute flex flex-col rounded-xl bg-w-white shadow-graymedium",n?"w-[280px] pb-3 pt-5":"h-auto w-[200px] overflow-hidden py-3",i),children:
|
|
34
|
+
*/(e,r);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);for(t=0;t<n.length;t++)a=n[t],r.indexOf(a)>=0||Object.prototype.propertyIsEnumerable.call(e,a)&&(l[a]=e[a])}return l}const y=({withUserInfo:n=!1,children:o,className:i})=>{const m=a.map(o,((a,l)=>0===l?a:/*#__PURE__*/r(t,{children:[
|
|
35
|
+
/*#__PURE__*/e(c,{className:"my-2"}),a]})));/*#__PURE__*/
|
|
36
|
+
return e(s,{as:"nav","aria-label":"네비게이션 메뉴",className:l("absolute flex flex-col rounded-xl bg-w-white shadow-graymedium",n?"w-[280px] pb-3 pt-5":"h-auto w-[200px] overflow-hidden py-3",i),children:m})},b=({imgUrl:a,username:t,email:l,children:i,onClick:c})=>/*#__PURE__*/r(s,{role:"region","aria-label":"사용자 정보",className:"flex w-full flex-col gap-4 px-6 pb-4",children:[
|
|
37
37
|
/*#__PURE__*/r(s,{className:"flex w-full items-center gap-4",children:[
|
|
38
|
-
/*#__PURE__*/e(
|
|
38
|
+
/*#__PURE__*/e(n,{size:"lg",isEditable:!0,imgUrl:a,onClick:c}),
|
|
39
39
|
/*#__PURE__*/r(s,{className:"flex w-full flex-col gap-0.5",children:[
|
|
40
|
-
/*#__PURE__*/e(
|
|
41
|
-
/*#__PURE__*/e(
|
|
42
|
-
return e(s,{as:"li",children:/*#__PURE__*/r(
|
|
43
|
-
/*#__PURE__*/e(
|
|
40
|
+
/*#__PURE__*/e(o,{variant:"body16",className:"text-w-gray-900 font-medium",children:t}),
|
|
41
|
+
/*#__PURE__*/e(o,{variant:"body14",className:"text-w-gray-600 line-clamp-2 break-all",children:l})]})]}),i&&/*#__PURE__*/e(s,{className:"flex w-full flex-col gap-2",children:i})]}),d=({children:r})=>/*#__PURE__*/e(s,{as:"ul","aria-label":"메인 메뉴",className:"text-w-gray-900 w-full",children:r}),h=({children:r})=>/*#__PURE__*/e(s,{as:"ul","aria-label":"서브 메뉴",className:"text-w-gray-600 w-full",children:r}),g=a=>{var{hasNew:t=!1,children:n,className:c,textClassName:m,href:y,as:b="a"}=a,d=u(a,["hasNew","children","className","textClassName","href","as"]);/*#__PURE__*/
|
|
42
|
+
return e(s,{as:"li",children:/*#__PURE__*/r(b,f(p({href:y,className:l("hover:bg-primary-10 flex w-full cursor-pointer gap-1 px-6 py-2",c)},d),{children:[
|
|
43
|
+
/*#__PURE__*/e(o,{variant:"body14",className:m,children:n}),t&&/*#__PURE__*/e(i,{className:"mt-1","aria-label":"새 소식"})]}))})};
|
|
44
44
|
/**
|
|
45
45
|
* 사용자 정보 컴포넌트
|
|
46
46
|
*
|
|
@@ -64,4 +64,4 @@ return e(s,{as:"li",children:/*#__PURE__*/r(n,u(f({href:b,className:l("hover:bg-
|
|
|
64
64
|
* <Button size="sm">프로필 수정</Button>
|
|
65
65
|
* <Button size="sm" variant="outlined">내 프로젝트</Button>
|
|
66
66
|
* </UserInfo>
|
|
67
|
-
*/export{
|
|
67
|
+
*/export{g as Item,d as List,y as Root,h as SubList,b as UserInfo};
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { ComponentPropsWithoutRef, PropsWithChildren } from 'react';
|
|
1
|
+
import { ComponentPropsWithoutRef, ElementType, PropsWithChildren } from 'react';
|
|
3
2
|
export interface GNBListRootProps extends PropsWithChildren {
|
|
4
3
|
withUserInfo?: boolean;
|
|
5
4
|
className?: string;
|
|
@@ -10,7 +9,13 @@ export interface UserInfoProps extends PropsWithChildren {
|
|
|
10
9
|
email?: string;
|
|
11
10
|
onClick?: () => void;
|
|
12
11
|
}
|
|
13
|
-
export interface GNBListItemProps extends ComponentPropsWithoutRef<
|
|
12
|
+
export interface GNBListItemProps extends Omit<ComponentPropsWithoutRef<'a'>, 'href'> {
|
|
13
|
+
href: string;
|
|
14
14
|
hasNew?: boolean;
|
|
15
15
|
textClassName?: string;
|
|
16
|
+
/**
|
|
17
|
+
* Item에서 anchor로 렌더할 컴포넌트. 기본값은 일반 `<a>` 태그이며,
|
|
18
|
+
* Next.js의 Link 등을 주입할 수 있습니다.
|
|
19
|
+
*/
|
|
20
|
+
as?: ElementType;
|
|
16
21
|
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { ComponentPropsWithoutRef, ElementType, ReactNode } from 'react';
|
|
2
|
+
import { MediumSystemIconName, SmallSystemIconName } from '../../DataDisplays/SystemIcon';
|
|
3
|
+
import { IconButtonDropdownItem } from '../../Inputs';
|
|
4
|
+
/**
|
|
5
|
+
* `MenuLink`와 `MenuButton`이 공유하는 presentation props.
|
|
6
|
+
*
|
|
7
|
+
* - 시맨틱 분기(`href` vs `onClick`)는 각 컴포넌트의 별도 타입으로 표현되며,
|
|
8
|
+
* 이 타입에는 포함되지 않습니다.
|
|
9
|
+
*/
|
|
10
|
+
export interface MenuCommonProps {
|
|
11
|
+
type?: 'main' | 'sub';
|
|
12
|
+
variant?: 'white' | 'gray';
|
|
13
|
+
name: string;
|
|
14
|
+
badgeCount?: string;
|
|
15
|
+
isSelected?: boolean;
|
|
16
|
+
leadingIcon?: MediumSystemIconName;
|
|
17
|
+
iconButtonName?: SmallSystemIconName;
|
|
18
|
+
onOptionClick?: () => void;
|
|
19
|
+
children?: ReactNode;
|
|
20
|
+
items?: IconButtonDropdownItem[];
|
|
21
|
+
selectedItem?: IconButtonDropdownItem;
|
|
22
|
+
onItemClick?: (item: IconButtonDropdownItem) => void;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* `MenuLink`의 props.
|
|
26
|
+
*
|
|
27
|
+
* - `href`가 필수이며, 기본 anchor(`<a>`) 또는 `as`로 주입된 컴포넌트로 렌더링됩니다.
|
|
28
|
+
* - anchor 관련 native 속성(`target`, `rel`, `download` 등)을 그대로 받습니다.
|
|
29
|
+
*/
|
|
30
|
+
export type MenuLinkProps = MenuCommonProps & Omit<ComponentPropsWithoutRef<'a'>, 'href' | 'className' | 'children' | 'as'> & {
|
|
31
|
+
href: string;
|
|
32
|
+
/**
|
|
33
|
+
* anchor 자리에 렌더할 컴포넌트. 기본값은 일반 `<a>` 태그이며,
|
|
34
|
+
* Next.js의 Link 등을 주입할 수 있습니다.
|
|
35
|
+
*/
|
|
36
|
+
as?: ElementType;
|
|
37
|
+
};
|
|
38
|
+
/**
|
|
39
|
+
* `MenuButton`의 props.
|
|
40
|
+
*
|
|
41
|
+
* - `onClick`이 필수이며, 항상 `<button>`으로 렌더링됩니다.
|
|
42
|
+
* - button 관련 native 속성(`disabled`, `type` 등)을 그대로 받습니다.
|
|
43
|
+
*/
|
|
44
|
+
export type MenuButtonProps = MenuCommonProps & Omit<ComponentPropsWithoutRef<'button'>, 'onClick' | 'className' | 'children' | 'type'> & {
|
|
45
|
+
onClick: () => void;
|
|
46
|
+
/**
|
|
47
|
+
* HTML `<button>`의 native `type` 속성. `MenuCommonProps.type`(`'main' | 'sub'`)과
|
|
48
|
+
* 이름이 충돌하므로 별도 prop으로 전달하려면 `htmlType`을 사용하세요.
|
|
49
|
+
*
|
|
50
|
+
* 디자인 시스템의 메뉴 타입(`'main' | 'sub'`)은 `MenuCommonProps`의 `type`을 그대로 사용합니다.
|
|
51
|
+
*/
|
|
52
|
+
htmlType?: 'button' | 'submit' | 'reset';
|
|
53
|
+
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { ElementType, ReactNode } from 'react';
|
|
2
|
+
import { MenuCommonProps } from './Menu.types';
|
|
3
|
+
interface MenuBaseProps extends MenuCommonProps {
|
|
4
|
+
/**
|
|
5
|
+
* 자식 wrapper로 사용할 element 또는 컴포넌트.
|
|
6
|
+
* `MenuLink`에서는 `'a'` 또는 주입된 컴포넌트, `MenuButton`에서는 `'button'`이 들어옵니다.
|
|
7
|
+
*/
|
|
8
|
+
as: ElementType;
|
|
9
|
+
/**
|
|
10
|
+
* `as` 컴포넌트에 그대로 전달되는 native props (href, onClick, target 등).
|
|
11
|
+
*/
|
|
12
|
+
wrapperProps?: Record<string, unknown>;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* `MenuLink`와 `MenuButton`이 공유하는 내부 컴포넌트.
|
|
16
|
+
* presentation 로직(className 계산, leadingIcon, name, badge, trailing IconButton/Dropdown)을 담당합니다.
|
|
17
|
+
*
|
|
18
|
+
* 외부에 export 되지 않으며, `MenuLink` / `MenuButton`을 통해서만 사용됩니다.
|
|
19
|
+
*/
|
|
20
|
+
declare const MenuBase: ({ type, variant, name, isSelected, badgeCount, leadingIcon, iconButtonName, onOptionClick, items, selectedItem, onItemClick, as: Component, wrapperProps, }: MenuBaseProps) => ReactNode;
|
|
21
|
+
export { MenuBase };
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import{jsxs as t,jsx as e}from"react/jsx-runtime";import{twJoin as r,twMerge as o}from"tailwind-merge";import"../../DataDisplays/Avatar/Avatar.js";import{CountBadge as n}from"../../DataDisplays/CountBadge/CountBadge.js";import{Typography as s}from"../../Base/Typography/Typography.js";import"../../Base/Layouts/Box/Box.js";import"../../Base/Layouts/FullBleed/FullBleed.js";import"react";import{SystemIcon as i}from"../../DataDisplays/SystemIcon/SystemIcon.js";import"../../DataDisplays/SystemIcon/SystemIcon.constants.js";import"../../DataDisplays/Accordion/Accordion.js";import"@wishket/yogokit";import"../../Inputs/AutoCompleteList/AutoCompleteList.parts.js";import"../../Inputs/Input/Input.js";import"../../Inputs/Input/PasswordInput.js";import"../../Inputs/Input/LabelInput.js";import"../../Inputs/Input/InputTypeSelector.js";import"../../Inputs/Button/Button.js";import"../../Inputs/Calendar/Calendar.utils.js";import"../../Inputs/Checkbox/Checkbox.js";import"../../Inputs/ChoiceChip/ChoiceChip.js";import{IconButton as p}from"../../Inputs/IconButton/IconButton.js";import"../../Inputs/Radio/Radio.js";import"../../Inputs/TextField/TextField.js";import"../../Inputs/CommentArea/CommentArea.js";import{IconButtonDropdown as a}from"../../Inputs/IconButtonDropdown/IconButtonDropdown.js";import"../../Inputs/FilterChip/FilterChip.js";function m(t,e,r){return e in t?Object.defineProperty(t,e,{value:r,enumerable:!0,configurable:!0,writable:!0}):t[e]=r,t}function c(t,e){return e=null!=e?e:{},Object.getOwnPropertyDescriptors?Object.defineProperties(t,Object.getOwnPropertyDescriptors(e)):function(t){var e=Object.keys(t);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(t);e.push.apply(e,r)}return e}(Object(e)).forEach((function(r){Object.defineProperty(t,r,Object.getOwnPropertyDescriptor(e,r))})),t}const u=(t,e,n)=>{const s="sub"===t?"pl-12":"",i={white:r("hover:bg-w-gray-50",n&&"bg-primary-10 text-primary hover:bg-primary-10"),gray:r("hover:bg-w-gray-100",n&&"bg-w-gray-100 hover:bg-w-gray-100")};return o("flex w-full cursor-pointer items-center gap-2 rounded-xl px-4 py-3 text-w-gray-900 text-left",s,i[e])},l=(t,e)=>"white"!==t?"white_gray":e?"primary":"gray",y=({type:o="main",variant:y="white",name:d,isSelected:g=!1,badgeCount:j,leadingIcon:I,iconButtonName:b,onOptionClick:f,items:h,selectedItem:w,onItemClick:O,as:C,wrapperProps:x})=>{const B=!!(b&&h&&O&&w),D=!!b&&!!f;/*#__PURE__*/
|
|
2
|
+
return t(C,c(function(t){for(var e=1;e<arguments.length;e++){var r=null!=arguments[e]?arguments[e]:{},o=Object.keys(r);"function"==typeof Object.getOwnPropertySymbols&&(o=o.concat(Object.getOwnPropertySymbols(r).filter((function(t){return Object.getOwnPropertyDescriptor(r,t).enumerable})))),o.forEach((function(e){m(t,e,r[e])}))}return t}({"data-testid":"design-system-menu",className:u(o,y,g)},x),{children:[I&&/*#__PURE__*/e(i,{testId:"design-system-menu-leading-icon",name:I,className:r("white"===y&&g&&"text-primary")}),
|
|
3
|
+
/*#__PURE__*/e(s,{"data-testid":"design-system-menu-name",variant:"body16",className:"w-full select-none",children:d}),j&&/*#__PURE__*/e(n,{variant:l(y,g),text:j,className:"relative",showZero:!0}),B&&/*#__PURE__*/e(a,{size:"sm",icon:b,items:h,selectedItem:w,onItemClick:O}),D&&/*#__PURE__*/e(p,{size:"sm",className:"shrink-0",onClick:t=>{t.stopPropagation(),f()},children:/*#__PURE__*/e(i,{name:b})})]}))};export{y as MenuBase};
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { MenuButtonProps } from './Menu.types';
|
|
2
|
+
/**
|
|
3
|
+
* 네비게이션에서 사용되는 버튼형 메뉴 항목.
|
|
4
|
+
*
|
|
5
|
+
* @description
|
|
6
|
+
* - 항상 `<button>`으로 렌더링됩니다.
|
|
7
|
+
* - `onClick`이 반드시 필요합니다. 페이지 이동을 위한 anchor가 필요한 경우 `MenuLink`를 사용하세요.
|
|
8
|
+
*
|
|
9
|
+
* @param {Object} props
|
|
10
|
+
* @param {() => void} props.onClick - 메뉴 클릭 시 실행될 함수 (필수)
|
|
11
|
+
* @param {'main' | 'sub'} [props.type='main'] - 메뉴 타입 (HTML `<button>`의 native `type`과는 무관. native `type`을 지정하려면 `htmlType` prop 사용)
|
|
12
|
+
* @param {'button' | 'submit' | 'reset'} [props.htmlType] - `<button>`의 native `type` 속성
|
|
13
|
+
* @param {'white' | 'gray'} [props.variant='white'] - 메뉴 스타일 변형
|
|
14
|
+
* @param {string} props.name - 메뉴에 표시될 텍스트
|
|
15
|
+
* @param {string} [props.badgeCount] - 메뉴 항목에 표시될 뱃지 숫자
|
|
16
|
+
* @param {boolean} [props.isSelected=false] - 메뉴 선택 상태
|
|
17
|
+
* @param {SystemIconName} [props.leadingIcon] - 메뉴 앞쪽에 표시될 아이콘 (medium 사이즈)
|
|
18
|
+
* @param {SystemIconName} [props.iconButtonName] - IconButtonDropdown / IconButton 아이콘 (small 사이즈)
|
|
19
|
+
* @param {() => void} [props.onOptionClick] - 후행 아이콘 클릭 시 실행될 함수 (IconButton 옵션)
|
|
20
|
+
* @param {Item[]} [props.items] - IconButtonDropdown 사용 시 필요
|
|
21
|
+
* @param {Item} [props.selectedItem] - IconButtonDropdown 사용 시 필요
|
|
22
|
+
* @param {(item: Item) => void} [props.onItemClick] - IconButtonDropdown 사용 시 필요
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* // 기본 사용
|
|
26
|
+
* <MenuButton name="설정" onClick={() => openModal()} />
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* // IconButtonDropdown과 함께
|
|
30
|
+
* <MenuButton
|
|
31
|
+
* name="옵션"
|
|
32
|
+
* onClick={() => {}}
|
|
33
|
+
* iconButtonName="small_more_options"
|
|
34
|
+
* items={items}
|
|
35
|
+
* selectedItem={selectedItem}
|
|
36
|
+
* onItemClick={onItemClick}
|
|
37
|
+
* />
|
|
38
|
+
*/
|
|
39
|
+
declare const MenuButton: ({ type, variant, name, badgeCount, isSelected, leadingIcon, iconButtonName, onOptionClick, items, selectedItem, onItemClick, onClick, htmlType, children: _children, ...rest }: MenuButtonProps) => import("react/jsx-runtime").JSX.Element;
|
|
40
|
+
export { MenuButton };
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import{jsx as e}from"react/jsx-runtime";import{MenuBase as t}from"./MenuBase.js";function n(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function r(e){for(var t=1;t<arguments.length;t++){var r=null!=arguments[t]?arguments[t]:{},o=Object.keys(r);"function"==typeof Object.getOwnPropertySymbols&&(o=o.concat(Object.getOwnPropertySymbols(r).filter((function(e){return Object.getOwnPropertyDescriptor(r,e).enumerable})))),o.forEach((function(t){n(e,t,r[t])}))}return e}function o(e,t){if(null==e)return{};var n,r,o=function(e,t){if(null==e)return{};var n,r,o={},i=Object.keys(e);for(r=0;r<i.length;r++)n=i[r],t.indexOf(n)>=0||(o[n]=e[n]);return o}
|
|
2
|
+
/**
|
|
3
|
+
* 네비게이션에서 사용되는 버튼형 메뉴 항목.
|
|
4
|
+
*
|
|
5
|
+
* @description
|
|
6
|
+
* - 항상 `<button>`으로 렌더링됩니다.
|
|
7
|
+
* - `onClick`이 반드시 필요합니다. 페이지 이동을 위한 anchor가 필요한 경우 `MenuLink`를 사용하세요.
|
|
8
|
+
*
|
|
9
|
+
* @param {Object} props
|
|
10
|
+
* @param {() => void} props.onClick - 메뉴 클릭 시 실행될 함수 (필수)
|
|
11
|
+
* @param {'main' | 'sub'} [props.type='main'] - 메뉴 타입 (HTML `<button>`의 native `type`과는 무관. native `type`을 지정하려면 `htmlType` prop 사용)
|
|
12
|
+
* @param {'button' | 'submit' | 'reset'} [props.htmlType] - `<button>`의 native `type` 속성
|
|
13
|
+
* @param {'white' | 'gray'} [props.variant='white'] - 메뉴 스타일 변형
|
|
14
|
+
* @param {string} props.name - 메뉴에 표시될 텍스트
|
|
15
|
+
* @param {string} [props.badgeCount] - 메뉴 항목에 표시될 뱃지 숫자
|
|
16
|
+
* @param {boolean} [props.isSelected=false] - 메뉴 선택 상태
|
|
17
|
+
* @param {SystemIconName} [props.leadingIcon] - 메뉴 앞쪽에 표시될 아이콘 (medium 사이즈)
|
|
18
|
+
* @param {SystemIconName} [props.iconButtonName] - IconButtonDropdown / IconButton 아이콘 (small 사이즈)
|
|
19
|
+
* @param {() => void} [props.onOptionClick] - 후행 아이콘 클릭 시 실행될 함수 (IconButton 옵션)
|
|
20
|
+
* @param {Item[]} [props.items] - IconButtonDropdown 사용 시 필요
|
|
21
|
+
* @param {Item} [props.selectedItem] - IconButtonDropdown 사용 시 필요
|
|
22
|
+
* @param {(item: Item) => void} [props.onItemClick] - IconButtonDropdown 사용 시 필요
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* // 기본 사용
|
|
26
|
+
* <MenuButton name="설정" onClick={() => openModal()} />
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* // IconButtonDropdown과 함께
|
|
30
|
+
* <MenuButton
|
|
31
|
+
* name="옵션"
|
|
32
|
+
* onClick={() => {}}
|
|
33
|
+
* iconButtonName="small_more_options"
|
|
34
|
+
* items={items}
|
|
35
|
+
* selectedItem={selectedItem}
|
|
36
|
+
* onItemClick={onItemClick}
|
|
37
|
+
* />
|
|
38
|
+
*/(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(r=0;r<i.length;r++)n=i[r],t.indexOf(n)>=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}const i=n=>{var{type:i,variant:c,name:l,badgeCount:a,isSelected:u,leadingIcon:m,iconButtonName:p,onOptionClick:s,items:b,selectedItem:f,onItemClick:y,onClick:O,htmlType:d,children:g}=n,C=o(n,["type","variant","name","badgeCount","isSelected","leadingIcon","iconButtonName","onOptionClick","items","selectedItem","onItemClick","onClick","htmlType","children"]);/*#__PURE__*/
|
|
39
|
+
return e(t,{type:i,variant:c,name:l,badgeCount:a,isSelected:u,leadingIcon:m,iconButtonName:p,onOptionClick:s,items:b,selectedItem:f,onItemClick:y,as:"button",wrapperProps:r({onClick:O,type:d},C)})};export{i as MenuButton};
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { MenuLinkProps } from './Menu.types';
|
|
2
|
+
/**
|
|
3
|
+
* 네비게이션에서 사용되는 링크형 메뉴 항목.
|
|
4
|
+
*
|
|
5
|
+
* @description
|
|
6
|
+
* - 기본은 `<a>` 태그이며, `as` prop으로 Next.js의 Link 등 임의의 컴포넌트를 주입할 수 있습니다.
|
|
7
|
+
* - `href`가 반드시 필요합니다. 클릭 핸들러만 필요한 경우 `MenuButton`을 사용하세요.
|
|
8
|
+
*
|
|
9
|
+
* @param {Object} props
|
|
10
|
+
* @param {string} props.href - 메뉴 링크 주소 (필수)
|
|
11
|
+
* @param {ElementType} [props.as='a'] - anchor 자리에 렌더할 컴포넌트 (예: next/link)
|
|
12
|
+
* @param {'main' | 'sub'} [props.type='main'] - 메뉴 타입
|
|
13
|
+
* @param {'white' | 'gray'} [props.variant='white'] - 메뉴 스타일 변형
|
|
14
|
+
* @param {string} props.name - 메뉴에 표시될 텍스트
|
|
15
|
+
* @param {string} [props.badgeCount] - 메뉴 항목에 표시될 뱃지 숫자
|
|
16
|
+
* @param {boolean} [props.isSelected=false] - 메뉴 선택 상태
|
|
17
|
+
* @param {SystemIconName} [props.leadingIcon] - 메뉴 앞쪽에 표시될 아이콘 (medium 사이즈)
|
|
18
|
+
* @param {SystemIconName} [props.iconButtonName] - IconButtonDropdown / IconButton 아이콘 (small 사이즈)
|
|
19
|
+
* @param {() => void} [props.onOptionClick] - 후행 아이콘 클릭 시 실행될 함수 (IconButton 옵션)
|
|
20
|
+
* @param {Item[]} [props.items] - IconButtonDropdown 사용 시 필요
|
|
21
|
+
* @param {Item} [props.selectedItem] - IconButtonDropdown 사용 시 필요
|
|
22
|
+
* @param {(item: Item) => void} [props.onItemClick] - IconButtonDropdown 사용 시 필요
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* // 기본 사용 (일반 <a>)
|
|
26
|
+
* <MenuLink href="/projects" name="프로젝트" />
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* // Next.js Link 주입
|
|
30
|
+
* import Link from 'next/link';
|
|
31
|
+
* <MenuLink as={Link} href="/projects" name="프로젝트" />
|
|
32
|
+
*
|
|
33
|
+
* @example
|
|
34
|
+
* // 외부 링크
|
|
35
|
+
* <MenuLink
|
|
36
|
+
* href="https://example.com"
|
|
37
|
+
* name="외부 사이트"
|
|
38
|
+
* target="_blank"
|
|
39
|
+
* rel="noopener noreferrer"
|
|
40
|
+
* />
|
|
41
|
+
*/
|
|
42
|
+
declare const MenuLink: ({ type, variant, name, badgeCount, isSelected, leadingIcon, iconButtonName, onOptionClick, items, selectedItem, onItemClick, href, as: LinkComponent, children: _children, ...rest }: MenuLinkProps) => import("react/jsx-runtime").JSX.Element;
|
|
43
|
+
export { MenuLink };
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import{jsx as e}from"react/jsx-runtime";import{MenuBase as t}from"./MenuBase.js";function n(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function r(e){for(var t=1;t<arguments.length;t++){var r=null!=arguments[t]?arguments[t]:{},o=Object.keys(r);"function"==typeof Object.getOwnPropertySymbols&&(o=o.concat(Object.getOwnPropertySymbols(r).filter((function(e){return Object.getOwnPropertyDescriptor(r,e).enumerable})))),o.forEach((function(t){n(e,t,r[t])}))}return e}function o(e,t){if(null==e)return{};var n,r,o=function(e,t){if(null==e)return{};var n,r,o={},i=Object.keys(e);for(r=0;r<i.length;r++)n=i[r],t.indexOf(n)>=0||(o[n]=e[n]);return o}
|
|
2
|
+
/**
|
|
3
|
+
* 네비게이션에서 사용되는 링크형 메뉴 항목.
|
|
4
|
+
*
|
|
5
|
+
* @description
|
|
6
|
+
* - 기본은 `<a>` 태그이며, `as` prop으로 Next.js의 Link 등 임의의 컴포넌트를 주입할 수 있습니다.
|
|
7
|
+
* - `href`가 반드시 필요합니다. 클릭 핸들러만 필요한 경우 `MenuButton`을 사용하세요.
|
|
8
|
+
*
|
|
9
|
+
* @param {Object} props
|
|
10
|
+
* @param {string} props.href - 메뉴 링크 주소 (필수)
|
|
11
|
+
* @param {ElementType} [props.as='a'] - anchor 자리에 렌더할 컴포넌트 (예: next/link)
|
|
12
|
+
* @param {'main' | 'sub'} [props.type='main'] - 메뉴 타입
|
|
13
|
+
* @param {'white' | 'gray'} [props.variant='white'] - 메뉴 스타일 변형
|
|
14
|
+
* @param {string} props.name - 메뉴에 표시될 텍스트
|
|
15
|
+
* @param {string} [props.badgeCount] - 메뉴 항목에 표시될 뱃지 숫자
|
|
16
|
+
* @param {boolean} [props.isSelected=false] - 메뉴 선택 상태
|
|
17
|
+
* @param {SystemIconName} [props.leadingIcon] - 메뉴 앞쪽에 표시될 아이콘 (medium 사이즈)
|
|
18
|
+
* @param {SystemIconName} [props.iconButtonName] - IconButtonDropdown / IconButton 아이콘 (small 사이즈)
|
|
19
|
+
* @param {() => void} [props.onOptionClick] - 후행 아이콘 클릭 시 실행될 함수 (IconButton 옵션)
|
|
20
|
+
* @param {Item[]} [props.items] - IconButtonDropdown 사용 시 필요
|
|
21
|
+
* @param {Item} [props.selectedItem] - IconButtonDropdown 사용 시 필요
|
|
22
|
+
* @param {(item: Item) => void} [props.onItemClick] - IconButtonDropdown 사용 시 필요
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* // 기본 사용 (일반 <a>)
|
|
26
|
+
* <MenuLink href="/projects" name="프로젝트" />
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* // Next.js Link 주입
|
|
30
|
+
* import Link from 'next/link';
|
|
31
|
+
* <MenuLink as={Link} href="/projects" name="프로젝트" />
|
|
32
|
+
*
|
|
33
|
+
* @example
|
|
34
|
+
* // 외부 링크
|
|
35
|
+
* <MenuLink
|
|
36
|
+
* href="https://example.com"
|
|
37
|
+
* name="외부 사이트"
|
|
38
|
+
* target="_blank"
|
|
39
|
+
* rel="noopener noreferrer"
|
|
40
|
+
* />
|
|
41
|
+
*/(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(r=0;r<i.length;r++)n=i[r],t.indexOf(n)>=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}const i=n=>{var{type:i,variant:c,name:a,badgeCount:l,isSelected:u,leadingIcon:m,iconButtonName:f,onOptionClick:s,items:p,selectedItem:b,onItemClick:O,href:y,as:d="a",children:g}=n,j=o(n,["type","variant","name","badgeCount","isSelected","leadingIcon","iconButtonName","onOptionClick","items","selectedItem","onItemClick","href","as","children"]);/*#__PURE__*/
|
|
42
|
+
return e(t,{type:i,variant:c,name:a,badgeCount:l,isSelected:u,leadingIcon:m,iconButtonName:f,onOptionClick:s,items:p,selectedItem:b,onItemClick:O,as:d,wrapperProps:r({href:y},j)})};export{i as MenuLink};
|