@jongh/cli 1.1.0 → 1.1.1
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/dist/index.js +1 -1
- package/package.json +16 -3
- package/.lintstagedrc.json +0 -4
- package/CHANGELOG.md +0 -7
- package/dist/components/Accordion/Accordion.tsx +0 -281
- package/dist/components/Accordion/index.tsx +0 -37
- package/dist/components/Accordion/useAccordionHeight.ts +0 -25
- package/dist/components/Avatar/Avatar.tsx +0 -18
- package/dist/components/Avatar/useAvatar.ts +0 -73
- package/dist/components/Button/index.tsx +0 -32
- package/dist/components/Primitive/index.tsx +0 -58
- package/dist/components/RovingIndex/RovingItem.tsx +0 -47
- package/dist/components/RovingIndex/RovingTabIndexRoot.tsx +0 -92
- package/dist/components/RovingIndex/index.ts +0 -3
- package/dist/components/RovingIndex/useRovingTabIndex.tsx +0 -76
- package/dist/components/Select/index.tsx +0 -231
- package/dist/components/Slider/index.tsx +0 -141
- package/dist/components/Slider/style.ts +0 -29
- package/dist/components/Tabs/Tab.tsx +0 -39
- package/dist/components/Tabs/TabContent.tsx +0 -62
- package/dist/components/Tabs/TabIndicator.tsx +0 -6
- package/dist/components/Tabs/TabList.tsx +0 -117
- package/dist/components/Tabs/index.ts +0 -43
- package/dist/components/Tabs/useRovingTabIndex.tsx +0 -171
- package/dist/components/Tabs/useTabContext.ts +0 -11
- package/dist/components/TagButton/TagButton.tsx +0 -75
- package/dist/components/TagButton/style.ts +0 -35
- package/dist/components/core/Polymorphic/index.ts +0 -26
- package/dist/components/index.ts +0 -5
- package/src/copyComponent.ts +0 -29
- package/src/getConfig.ts +0 -56
- package/src/index.ts +0 -46
- package/tsconfig.json +0 -14
- package/tsup.config.ts +0 -14
|
@@ -1,117 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
type ReactNode,
|
|
3
|
-
type ReactElement,
|
|
4
|
-
type ComponentPropsWithRef,
|
|
5
|
-
forwardRef,
|
|
6
|
-
} from "react"
|
|
7
|
-
import { useTabContext } from "./useTabContext"
|
|
8
|
-
|
|
9
|
-
import { RovingTabIndexRoot, useRovingTabIndex } from "../RovingIndex"
|
|
10
|
-
|
|
11
|
-
import { Slot } from "@radix-ui/react-slot"
|
|
12
|
-
import { composeRefs } from "../../hooks/useComposedRefs"
|
|
13
|
-
import {
|
|
14
|
-
getNextFocusableId,
|
|
15
|
-
getPrevFocusableId,
|
|
16
|
-
} from "../../utils/getFocusableId"
|
|
17
|
-
|
|
18
|
-
export interface TabListProps {
|
|
19
|
-
children: ReactNode
|
|
20
|
-
className?: string
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
const setIndicatorStyle = (target: HTMLElement) => {
|
|
24
|
-
const targetRect = target.getBoundingClientRect()
|
|
25
|
-
const parent = target.parentElement //TabList
|
|
26
|
-
const parentRect = parent?.getBoundingClientRect()
|
|
27
|
-
|
|
28
|
-
if (!targetRect || !parentRect || !parent) {
|
|
29
|
-
return
|
|
30
|
-
}
|
|
31
|
-
const scrollLeft = parent.scrollLeft //overflow일때 고려
|
|
32
|
-
|
|
33
|
-
const indicatorLeft = targetRect.left - parentRect.left + scrollLeft
|
|
34
|
-
|
|
35
|
-
document.documentElement.style.setProperty(
|
|
36
|
-
"--indicator-left",
|
|
37
|
-
`${indicatorLeft}px`,
|
|
38
|
-
)
|
|
39
|
-
document.documentElement.style.setProperty(
|
|
40
|
-
"--indicator-width",
|
|
41
|
-
`${targetRect.width}px`,
|
|
42
|
-
)
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
export const TabList = ({ children, ...props }: TabListProps) => {
|
|
46
|
-
const { selected } = useTabContext("tab")
|
|
47
|
-
return (
|
|
48
|
-
<RovingTabIndexRoot active={selected}>
|
|
49
|
-
<div role="tablist" {...props}>
|
|
50
|
-
{children}
|
|
51
|
-
</div>
|
|
52
|
-
</RovingTabIndexRoot>
|
|
53
|
-
)
|
|
54
|
-
}
|
|
55
|
-
export interface TabItemProps extends ComponentPropsWithRef<"button"> {
|
|
56
|
-
value: string
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
export const RovingItem = ({
|
|
60
|
-
value,
|
|
61
|
-
children,
|
|
62
|
-
}: {
|
|
63
|
-
value: string
|
|
64
|
-
children: ReactElement
|
|
65
|
-
}) => {
|
|
66
|
-
const { getOrderedItems, getRovingProps } = useRovingTabIndex(value)
|
|
67
|
-
return (
|
|
68
|
-
<Slot
|
|
69
|
-
{...getRovingProps<"button">({
|
|
70
|
-
onKeyDown: (e) => {
|
|
71
|
-
const items = getOrderedItems()
|
|
72
|
-
let nextItem
|
|
73
|
-
if (e.key === "ArrowRight") {
|
|
74
|
-
nextItem = getNextFocusableId(items, value)
|
|
75
|
-
} else if (e.key === "ArrowLeft") {
|
|
76
|
-
nextItem = getPrevFocusableId(items, value)
|
|
77
|
-
}
|
|
78
|
-
nextItem?.element.focus()
|
|
79
|
-
},
|
|
80
|
-
})}
|
|
81
|
-
>
|
|
82
|
-
{children}
|
|
83
|
-
</Slot>
|
|
84
|
-
)
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
export const TabItem = forwardRef<HTMLButtonElement, TabItemProps>(
|
|
88
|
-
({ children, value, ...props }: TabItemProps, forwardRef) => {
|
|
89
|
-
const { selected, onSelect, tabId } = useTabContext("tab")
|
|
90
|
-
const isSelected = selected === value
|
|
91
|
-
|
|
92
|
-
const handleSelect = () => {
|
|
93
|
-
onSelect?.(value)
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
return (
|
|
97
|
-
<RovingItem value={value}>
|
|
98
|
-
<button
|
|
99
|
-
ref={composeRefs((node) => {
|
|
100
|
-
if (isSelected && node) {
|
|
101
|
-
setIndicatorStyle(node as HTMLElement)
|
|
102
|
-
}
|
|
103
|
-
}, forwardRef)}
|
|
104
|
-
onClick={handleSelect}
|
|
105
|
-
onFocus={handleSelect}
|
|
106
|
-
role="tab"
|
|
107
|
-
aria-selected={isSelected}
|
|
108
|
-
id={tabId + "-tabitem-" + value}
|
|
109
|
-
aria-controls={tabId + "-tabpanel-" + value}
|
|
110
|
-
{...props}
|
|
111
|
-
>
|
|
112
|
-
{children}
|
|
113
|
-
</button>
|
|
114
|
-
</RovingItem>
|
|
115
|
-
)
|
|
116
|
-
},
|
|
117
|
-
)
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
"use client"
|
|
2
|
-
import { Tab, TabProps } from "./Tab"
|
|
3
|
-
import { TabContent, TabContentProps } from "./TabContent"
|
|
4
|
-
import { TabIndicator, TabIndicatorProps } from "./TabIndicator"
|
|
5
|
-
import { TabList, TabListProps } from "./TabList"
|
|
6
|
-
import { TabItem, TabItemProps } from "./TabList"
|
|
7
|
-
import { type TabsVariantProps, tabs } from "styled-system/recipes"
|
|
8
|
-
import type { Assign, HTMLStyledProps } from "styled-system/types"
|
|
9
|
-
import { createStyleContext } from "../../utils/createStyleContext"
|
|
10
|
-
|
|
11
|
-
const { withProvider, withContext } = createStyleContext(tabs)
|
|
12
|
-
|
|
13
|
-
const Root = withProvider<
|
|
14
|
-
HTMLDivElement,
|
|
15
|
-
Assign<Assign<HTMLStyledProps<"div">, TabProps>, TabsVariantProps>
|
|
16
|
-
>(Tab, "root")
|
|
17
|
-
|
|
18
|
-
const Content = withContext<
|
|
19
|
-
HTMLDivElement,
|
|
20
|
-
Assign<HTMLStyledProps<"div">, TabContentProps>
|
|
21
|
-
>(TabContent, "content")
|
|
22
|
-
|
|
23
|
-
const Indicator = withContext<
|
|
24
|
-
HTMLDivElement,
|
|
25
|
-
Assign<HTMLStyledProps<"div">, TabIndicatorProps>
|
|
26
|
-
>(TabIndicator, "indicator")
|
|
27
|
-
|
|
28
|
-
const List = withContext<
|
|
29
|
-
HTMLDivElement,
|
|
30
|
-
Assign<HTMLStyledProps<"div">, TabListProps>
|
|
31
|
-
>(TabList, "list")
|
|
32
|
-
|
|
33
|
-
const Item = withContext<
|
|
34
|
-
HTMLButtonElement,
|
|
35
|
-
Assign<HTMLStyledProps<"button">, TabItemProps>
|
|
36
|
-
>(TabItem, "item")
|
|
37
|
-
|
|
38
|
-
export const Tabs = Object.assign(Root, {
|
|
39
|
-
Content,
|
|
40
|
-
List,
|
|
41
|
-
Item,
|
|
42
|
-
Indicator,
|
|
43
|
-
})
|
|
@@ -1,171 +0,0 @@
|
|
|
1
|
-
import isHotkey from "is-hotkey"
|
|
2
|
-
import {
|
|
3
|
-
ReactNode,
|
|
4
|
-
useCallback,
|
|
5
|
-
useRef,
|
|
6
|
-
useState,
|
|
7
|
-
FocusEvent,
|
|
8
|
-
MouseEvent,
|
|
9
|
-
KeyboardEvent,
|
|
10
|
-
ComponentPropsWithoutRef,
|
|
11
|
-
ElementType,
|
|
12
|
-
MutableRefObject,
|
|
13
|
-
} from "react"
|
|
14
|
-
import { useControlledState } from "../../hooks/useControllableState"
|
|
15
|
-
import { createContext } from "../../hooks/createContext"
|
|
16
|
-
import { composeRefs } from "../../hooks/useComposedRefs"
|
|
17
|
-
|
|
18
|
-
export type RovingTabIndexItem = {
|
|
19
|
-
value: string
|
|
20
|
-
element: HTMLElement
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
function onFocusFirst(candidates: HTMLElement[]) {
|
|
24
|
-
const previousFocus = document.activeElement
|
|
25
|
-
while (document.activeElement === previousFocus && candidates.length > 0) {
|
|
26
|
-
candidates.shift()?.focus()
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
type RovingTabIndexContext = {
|
|
31
|
-
currentFocusedValue: string | null
|
|
32
|
-
setFocusableId: (id: string) => void
|
|
33
|
-
onShiftTab: () => void
|
|
34
|
-
getOrderedItems: () => RovingTabIndexItem[]
|
|
35
|
-
elements: MutableRefObject<Map<string, HTMLElement>>
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
const [RovingTabIndexProvider, useRovingTabIndexContext] =
|
|
39
|
-
createContext<RovingTabIndexContext>("rovingTabIndex")
|
|
40
|
-
|
|
41
|
-
const NODE_SELECTOR = "data-roving-tabindex-node"
|
|
42
|
-
const ROOT_SELECTOR = "data-roving-tabindex-root"
|
|
43
|
-
const NOT_FOCUSABLE_SELECTOR = "data-roving-tabindex-not-focusable"
|
|
44
|
-
const SELECTOR_ACTIVE = `:where([${NODE_SELECTOR}=true]):not(:where([${NOT_FOCUSABLE_SELECTOR}=true] *))`
|
|
45
|
-
|
|
46
|
-
type RovingTabIndexRootBaseProps<T> = {
|
|
47
|
-
children: ReactNode | ReactNode[]
|
|
48
|
-
active?: string
|
|
49
|
-
setActive?: (value: string) => void
|
|
50
|
-
as?: T
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
type RovingTabIndexRootProps<T extends ElementType> =
|
|
54
|
-
RovingTabIndexRootBaseProps<T> &
|
|
55
|
-
Omit<ComponentPropsWithoutRef<T>, keyof RovingTabIndexRootBaseProps<T>>
|
|
56
|
-
|
|
57
|
-
export const RovingTabIndexRoot = <T extends ElementType>({
|
|
58
|
-
children,
|
|
59
|
-
active,
|
|
60
|
-
setActive,
|
|
61
|
-
as,
|
|
62
|
-
ref,
|
|
63
|
-
...props
|
|
64
|
-
}: RovingTabIndexRootProps<T>) => {
|
|
65
|
-
const Component = as || "div"
|
|
66
|
-
const [isShiftTabbing, setIsShiftTabbing] = useState(false)
|
|
67
|
-
|
|
68
|
-
const [value = null, setValue] = useControlledState({
|
|
69
|
-
prop: active,
|
|
70
|
-
onChange: setActive,
|
|
71
|
-
})
|
|
72
|
-
|
|
73
|
-
const rootRef = useRef<HTMLDivElement | null>(null)
|
|
74
|
-
const elementsRef = useRef<Map<string, HTMLElement>>(new Map())
|
|
75
|
-
const getOrderedItems = useCallback(() => {
|
|
76
|
-
if (!rootRef.current) return []
|
|
77
|
-
const activeElements = Array.from(
|
|
78
|
-
rootRef.current.querySelectorAll(SELECTOR_ACTIVE),
|
|
79
|
-
)
|
|
80
|
-
|
|
81
|
-
return Array.from(elementsRef.current)
|
|
82
|
-
.sort(
|
|
83
|
-
(a, b) => activeElements.indexOf(a[1]) - activeElements.indexOf(b[1]),
|
|
84
|
-
)
|
|
85
|
-
.map(([value, element]) => ({ value, element }))
|
|
86
|
-
}, [])
|
|
87
|
-
|
|
88
|
-
return (
|
|
89
|
-
<RovingTabIndexProvider
|
|
90
|
-
setFocusableId={(value: string) => {
|
|
91
|
-
setValue(value)
|
|
92
|
-
}}
|
|
93
|
-
onShiftTab={() => {
|
|
94
|
-
setIsShiftTabbing(true)
|
|
95
|
-
}}
|
|
96
|
-
currentFocusedValue={value}
|
|
97
|
-
getOrderedItems={getOrderedItems}
|
|
98
|
-
elements={elementsRef}
|
|
99
|
-
>
|
|
100
|
-
<Component
|
|
101
|
-
{...{ [ROOT_SELECTOR]: true }}
|
|
102
|
-
// tabIndex={isShiftTabbing ? -1 : 0}
|
|
103
|
-
onFocus={(e) => {
|
|
104
|
-
if (e.target !== e.currentTarget) return
|
|
105
|
-
if (isShiftTabbing) return
|
|
106
|
-
const orderedItems = getOrderedItems()
|
|
107
|
-
if (orderedItems.length === 0) return
|
|
108
|
-
|
|
109
|
-
const candidates = [
|
|
110
|
-
elementsRef.current.get(value ?? ""),
|
|
111
|
-
...orderedItems.map((i) => i.element),
|
|
112
|
-
].filter((element): element is HTMLElement => element != null)
|
|
113
|
-
|
|
114
|
-
onFocusFirst(candidates)
|
|
115
|
-
}}
|
|
116
|
-
onBlur={() => setIsShiftTabbing(false)}
|
|
117
|
-
ref={composeRefs(ref, rootRef)}
|
|
118
|
-
{...props}
|
|
119
|
-
>
|
|
120
|
-
{children}
|
|
121
|
-
</Component>
|
|
122
|
-
</RovingTabIndexProvider>
|
|
123
|
-
)
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
export const useRovingTabIndex = (value: string) => {
|
|
127
|
-
const {
|
|
128
|
-
currentFocusedValue,
|
|
129
|
-
setFocusableId,
|
|
130
|
-
onShiftTab,
|
|
131
|
-
getOrderedItems,
|
|
132
|
-
elements,
|
|
133
|
-
} = useRovingTabIndexContext("rovingTabIndex")
|
|
134
|
-
|
|
135
|
-
return {
|
|
136
|
-
getOrderedItems,
|
|
137
|
-
isFocusable: currentFocusedValue === value,
|
|
138
|
-
getRovingProps: <T extends ElementType>(
|
|
139
|
-
props?: ComponentPropsWithoutRef<T>,
|
|
140
|
-
) => ({
|
|
141
|
-
...props,
|
|
142
|
-
ref: (element: HTMLElement | null) => {
|
|
143
|
-
if (element) {
|
|
144
|
-
elements.current.set(value, element)
|
|
145
|
-
} else {
|
|
146
|
-
elements.current.delete(value)
|
|
147
|
-
}
|
|
148
|
-
},
|
|
149
|
-
onMouseDown: (e: MouseEvent) => {
|
|
150
|
-
props?.onMouseDown?.(e)
|
|
151
|
-
if (e.target !== e.currentTarget) return
|
|
152
|
-
setFocusableId(value)
|
|
153
|
-
},
|
|
154
|
-
onKeyDown: (e: KeyboardEvent) => {
|
|
155
|
-
props?.onKeyDown?.(e)
|
|
156
|
-
if (e.target !== e.currentTarget) return
|
|
157
|
-
if (isHotkey("shift+tab", e)) {
|
|
158
|
-
onShiftTab()
|
|
159
|
-
return
|
|
160
|
-
}
|
|
161
|
-
},
|
|
162
|
-
onFocus: (e: FocusEvent) => {
|
|
163
|
-
props?.onFocus?.(e)
|
|
164
|
-
if (e.target !== e.currentTarget) return
|
|
165
|
-
setFocusableId(value)
|
|
166
|
-
},
|
|
167
|
-
[NODE_SELECTOR]: true,
|
|
168
|
-
tabIndex: currentFocusedValue === value ? 0 : -1,
|
|
169
|
-
}),
|
|
170
|
-
}
|
|
171
|
-
}
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import { createContext } from "../../hooks/createContext"
|
|
2
|
-
|
|
3
|
-
type Value = string
|
|
4
|
-
|
|
5
|
-
export interface TabContext {
|
|
6
|
-
selected?: Value
|
|
7
|
-
onSelect?: (index: Value) => void
|
|
8
|
-
tabId: string
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
export const [TabProvider, useTabContext] = createContext<TabContext>("tab")
|
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
// import { cx } from "@styled-system/css"
|
|
2
|
-
// // import { tagButton, type TagButtonVariant } from "@styled-system/recipes"
|
|
3
|
-
// import { forwardRef } from "react"
|
|
4
|
-
// import { useControlledState } from "../../hooks/useControllableState"
|
|
5
|
-
|
|
6
|
-
// type TagButtonProps = Partial<TagButtonVariant> & {
|
|
7
|
-
// /** 버튼 내부에 표시될 텍스트 */
|
|
8
|
-
// children: string
|
|
9
|
-
|
|
10
|
-
// /** 버튼의 비활성화 여부를 지정합니다. true일 경우 버튼이 비활성화됩니다. */
|
|
11
|
-
// disabled?: boolean
|
|
12
|
-
|
|
13
|
-
// /** 버튼에 적용할 추가적인 CSS 클래스명 */
|
|
14
|
-
// className?: string
|
|
15
|
-
|
|
16
|
-
// /** 버튼의 고유 식별자 */
|
|
17
|
-
// id?: string
|
|
18
|
-
|
|
19
|
-
// /**
|
|
20
|
-
// * 버튼 클릭 시 실행될 함수
|
|
21
|
-
// * @param e 선택적 boolean 매개변수
|
|
22
|
-
// */
|
|
23
|
-
// onClick?: (e?: boolean) => void
|
|
24
|
-
|
|
25
|
-
// /** 버튼의 클릭 상태를 나타냅니다. true일 경우 클릭된 상태를 의미합니다. */
|
|
26
|
-
// isClicked?: boolean
|
|
27
|
-
|
|
28
|
-
// /** 버튼의 초기 클릭 상태를 설정합니다. true일 경우 처음부터 클릭된 상태로 시작합니다. */
|
|
29
|
-
// defaultClick?: boolean
|
|
30
|
-
// }
|
|
31
|
-
|
|
32
|
-
// export const TagButton = forwardRef<HTMLSpanElement, TagButtonProps>(
|
|
33
|
-
// (
|
|
34
|
-
// {
|
|
35
|
-
// children,
|
|
36
|
-
// disabled = false,
|
|
37
|
-
// className,
|
|
38
|
-
// id,
|
|
39
|
-
// onClick,
|
|
40
|
-
// isClicked,
|
|
41
|
-
// defaultClick = false,
|
|
42
|
-
// ...rest
|
|
43
|
-
// },
|
|
44
|
-
// ref,
|
|
45
|
-
// ) => {
|
|
46
|
-
// const [clicked, setClicked] = useControlledState({
|
|
47
|
-
// prop: isClicked,
|
|
48
|
-
// defaultProp: defaultClick,
|
|
49
|
-
// onChange: onClick,
|
|
50
|
-
// })
|
|
51
|
-
// //
|
|
52
|
-
// return (
|
|
53
|
-
// <span
|
|
54
|
-
// role="button"
|
|
55
|
-
// ref={ref}
|
|
56
|
-
// id={id}
|
|
57
|
-
// className={cx(tagButton({ ...rest }), className)}
|
|
58
|
-
// aria-disabled={disabled}
|
|
59
|
-
// aria-pressed={clicked}
|
|
60
|
-
// {...(disabled && { "data-invalid": "true" })}
|
|
61
|
-
// data-testid={id}
|
|
62
|
-
// onClick={() => {
|
|
63
|
-
// if (disabled) {
|
|
64
|
-
// return
|
|
65
|
-
// }
|
|
66
|
-
// setClicked((prev) => !prev)
|
|
67
|
-
// }}
|
|
68
|
-
// >
|
|
69
|
-
// {children}
|
|
70
|
-
// </span>
|
|
71
|
-
// )
|
|
72
|
-
// },
|
|
73
|
-
// )
|
|
74
|
-
|
|
75
|
-
// TagButton.displayName = "TagButton"
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import { define } from "../../../dev"
|
|
2
|
-
export const tagButtonRecipe = define.recipe({
|
|
3
|
-
className: "tagButton",
|
|
4
|
-
base: {
|
|
5
|
-
textAlign: "center",
|
|
6
|
-
borderRadius: "rounded",
|
|
7
|
-
padding: "4px 10px",
|
|
8
|
-
fontWeight: "normal",
|
|
9
|
-
cursor: "pointer",
|
|
10
|
-
border: "1px solid black",
|
|
11
|
-
color: "text_primary",
|
|
12
|
-
_hover: { boxShadow: "0px 0px 3px", boxShadowColor: "grey_300" },
|
|
13
|
-
_invalid: {
|
|
14
|
-
cursor: "not-allowed",
|
|
15
|
-
},
|
|
16
|
-
_pressed: {
|
|
17
|
-
borderWidth: "2px",
|
|
18
|
-
borderColor: "blue_300",
|
|
19
|
-
},
|
|
20
|
-
maxWidth: "screen",
|
|
21
|
-
},
|
|
22
|
-
variants: {
|
|
23
|
-
size: {
|
|
24
|
-
small: {
|
|
25
|
-
fontSize: "sm",
|
|
26
|
-
},
|
|
27
|
-
large: {
|
|
28
|
-
fontSize: "lg",
|
|
29
|
-
},
|
|
30
|
-
},
|
|
31
|
-
},
|
|
32
|
-
defaultVariants: {
|
|
33
|
-
size: "small",
|
|
34
|
-
},
|
|
35
|
-
})
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
// polymorphic.d.ts
|
|
2
|
-
import {
|
|
3
|
-
type ComponentPropsWithRef,
|
|
4
|
-
type ComponentPropsWithoutRef,
|
|
5
|
-
type ElementType,
|
|
6
|
-
} from "react"
|
|
7
|
-
|
|
8
|
-
type AsProp<C extends ElementType> = {
|
|
9
|
-
as?: C
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
export type AsRef<C extends ElementType> = ComponentPropsWithRef<C>["ref"]
|
|
13
|
-
|
|
14
|
-
export type AsComponentProps<
|
|
15
|
-
C extends ElementType,
|
|
16
|
-
Props = object,
|
|
17
|
-
> = AsProp<C> &
|
|
18
|
-
ComponentPropsWithoutRef<C> &
|
|
19
|
-
Props & {
|
|
20
|
-
ref?: AsRef<C>
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
export type AsComponentPropsWithRef<
|
|
24
|
-
C extends ElementType,
|
|
25
|
-
Props = object,
|
|
26
|
-
> = Props & { ref?: AsRef<C> }
|
package/dist/components/index.ts
DELETED
package/src/copyComponent.ts
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
// src/copy-components.ts
|
|
2
|
-
import path from "node:path"
|
|
3
|
-
import fs from "fs-extra"
|
|
4
|
-
import { fileURLToPath } from "node:url"
|
|
5
|
-
|
|
6
|
-
const __dirname = path.dirname(fileURLToPath(import.meta.url))
|
|
7
|
-
|
|
8
|
-
const COMPONENTS_DIR = path.join(__dirname, "./components/Button/index.tsx")
|
|
9
|
-
|
|
10
|
-
export async function copyComponent(componentName: string, outputPath: string) {
|
|
11
|
-
try {
|
|
12
|
-
// 1. 우리 패키지 안의 컴포넌트 경로
|
|
13
|
-
const sourceFile = COMPONENTS_DIR
|
|
14
|
-
|
|
15
|
-
// 2. 유저 프로젝트의 목적지 경로 (CLI 실행 위치 기준)
|
|
16
|
-
const targetFile = path.join(
|
|
17
|
-
process.cwd(),
|
|
18
|
-
outputPath,
|
|
19
|
-
`${componentName}.tsx`,
|
|
20
|
-
)
|
|
21
|
-
|
|
22
|
-
// 3. 복사 실행
|
|
23
|
-
await fs.copy(sourceFile, targetFile)
|
|
24
|
-
|
|
25
|
-
console.log(`${componentName} copied to ${outputPath}`)
|
|
26
|
-
} catch (error) {
|
|
27
|
-
throw new Error(`Failed to copy component: ${error}`)
|
|
28
|
-
}
|
|
29
|
-
}
|
package/src/getConfig.ts
DELETED
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
import path from "node:path"
|
|
2
|
-
import fs from "fs-extra"
|
|
3
|
-
import { packageDirectory } from "pkg-dir"
|
|
4
|
-
import * as p from "@clack/prompts"
|
|
5
|
-
//TODO: json schema 제공
|
|
6
|
-
|
|
7
|
-
const initialPath = "./src/components/ui"
|
|
8
|
-
const jsonFileName = "component.json"
|
|
9
|
-
|
|
10
|
-
export async function getConfig(): Promise<{ outputPath: string }> {
|
|
11
|
-
const packageDir = await packageDirectory()
|
|
12
|
-
const configPath = path.join(packageDir || process.cwd(), jsonFileName)
|
|
13
|
-
try {
|
|
14
|
-
// 1. 프로젝트 루트 디렉토리 찾기
|
|
15
|
-
|
|
16
|
-
// 2. 설정 파일 읽기 시도
|
|
17
|
-
const config = await fs.readJSON(configPath)
|
|
18
|
-
return config
|
|
19
|
-
} catch {
|
|
20
|
-
p.note("설정 파일이 존재하지 않습니다")
|
|
21
|
-
const config = await promptConfig() //3. 사용자에게 경로 관련 입력 받기
|
|
22
|
-
|
|
23
|
-
// 4. 새 설정 파일 저장
|
|
24
|
-
await fs.outputJSON(
|
|
25
|
-
configPath,
|
|
26
|
-
{
|
|
27
|
-
...config,
|
|
28
|
-
},
|
|
29
|
-
{ spaces: 2 },
|
|
30
|
-
)
|
|
31
|
-
|
|
32
|
-
return config
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
const promptConfig = async () =>
|
|
37
|
-
p.group(
|
|
38
|
-
{
|
|
39
|
-
outputPath: () =>
|
|
40
|
-
p.text({
|
|
41
|
-
message: "컴포넌트 저장 경로를 설정해주세요",
|
|
42
|
-
initialValue: initialPath,
|
|
43
|
-
validate: (value) => {
|
|
44
|
-
if (!value) return "Please enter a path."
|
|
45
|
-
if (!value.startsWith("."))
|
|
46
|
-
return "Please enter a relative path to the project root."
|
|
47
|
-
},
|
|
48
|
-
}),
|
|
49
|
-
},
|
|
50
|
-
{
|
|
51
|
-
onCancel: () => {
|
|
52
|
-
p.cancel("Operation cancelled.")
|
|
53
|
-
process.exit(0)
|
|
54
|
-
},
|
|
55
|
-
},
|
|
56
|
-
)
|
package/src/index.ts
DELETED
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
import yargs from "yargs"
|
|
4
|
-
import { hideBin } from "yargs/helpers"
|
|
5
|
-
import { getConfig } from "./getConfig"
|
|
6
|
-
import * as p from "@clack/prompts"
|
|
7
|
-
import { copyComponent } from "./copyComponent"
|
|
8
|
-
|
|
9
|
-
const main = async () => {
|
|
10
|
-
await yargs(hideBin(process.argv))
|
|
11
|
-
.command(
|
|
12
|
-
"components add [components..]",
|
|
13
|
-
"Add components to your project",
|
|
14
|
-
(yargs) => {
|
|
15
|
-
return yargs
|
|
16
|
-
.positional("components", {
|
|
17
|
-
describe: "List of components to add",
|
|
18
|
-
type: "string",
|
|
19
|
-
array: true,
|
|
20
|
-
default: [],
|
|
21
|
-
})
|
|
22
|
-
.option("all", {
|
|
23
|
-
type: "boolean",
|
|
24
|
-
description: "Add all components",
|
|
25
|
-
default: false,
|
|
26
|
-
})
|
|
27
|
-
},
|
|
28
|
-
async (argv) => {
|
|
29
|
-
// 컴포넌트가 없고 --all 플래그도 없으면 에러
|
|
30
|
-
if (argv.components.length === 0 && !argv.all) {
|
|
31
|
-
p.cancel(
|
|
32
|
-
"Error: You need to specify at least one component or use the --all flag",
|
|
33
|
-
)
|
|
34
|
-
console.log('Run "cli --help" for more information')
|
|
35
|
-
return
|
|
36
|
-
}
|
|
37
|
-
const config = await getConfig()
|
|
38
|
-
await copyComponent(argv.components[0], config.outputPath)
|
|
39
|
-
},
|
|
40
|
-
)
|
|
41
|
-
.demandCommand(1, "You need at least one command before moving on")
|
|
42
|
-
.strict()
|
|
43
|
-
.help().argv
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
main()
|
package/tsconfig.json
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"extends": "../../tsconfig.json",
|
|
3
|
-
"compilerOptions": {
|
|
4
|
-
"emitDeclarationOnly": true,
|
|
5
|
-
"noImplicitAny": true,
|
|
6
|
-
"declaration": true,
|
|
7
|
-
"noEmit": false,
|
|
8
|
-
"declarationMap": true,
|
|
9
|
-
"declarationDir": "dist",
|
|
10
|
-
"outDir": "dist",
|
|
11
|
-
"baseUrl": "./"
|
|
12
|
-
},
|
|
13
|
-
"include": ["src"]
|
|
14
|
-
}
|
package/tsup.config.ts
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import { defineConfig } from "tsup"
|
|
2
|
-
import fs from "fs-extra"
|
|
3
|
-
|
|
4
|
-
export default defineConfig({
|
|
5
|
-
entry: ["src/index.ts"],
|
|
6
|
-
format: ["esm"],
|
|
7
|
-
dts: true,
|
|
8
|
-
clean: true,
|
|
9
|
-
sourcemap: false,
|
|
10
|
-
minify: true,
|
|
11
|
-
async onSuccess() {
|
|
12
|
-
await fs.copy("../ui/src/components", "./dist/components")
|
|
13
|
-
},
|
|
14
|
-
})
|