Skip to content

Commit 85a8b39

Browse files
committed
temp
1 parent 92c4d3f commit 85a8b39

10 files changed

Lines changed: 553 additions & 31 deletions

File tree

Lines changed: 216 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,216 @@
1+
import React from 'react'
2+
import clsx from 'clsx'
3+
import {
4+
EnumSize,
5+
type Size,
6+
type Variant,
7+
type EnumVariant,
8+
} from '../../../types/enum'
9+
10+
export type ButtonVariant = Subset<
11+
Variant,
12+
| typeof EnumVariant.Primary
13+
| typeof EnumVariant.Secondary
14+
| typeof EnumVariant.Success
15+
| typeof EnumVariant.Danger
16+
| typeof EnumVariant.Warning
17+
| typeof EnumVariant.Alternative
18+
| typeof EnumVariant.Neutral
19+
| typeof EnumVariant.Info
20+
>
21+
22+
export type ButtonSize = Subset<
23+
Size,
24+
| typeof EnumSize.xs
25+
| typeof EnumSize.sm
26+
| typeof EnumSize.md
27+
| typeof EnumSize.lg
28+
>
29+
30+
export const EnumButtonShape = {
31+
Square: 'square',
32+
Rounded: 'rounded',
33+
Circle: 'circle',
34+
Pill: 'pill',
35+
} as const
36+
37+
export const EnumButtonFormat = {
38+
Solid: 'solid',
39+
Outline: 'outline',
40+
Ghost: 'ghost',
41+
Link: 'link',
42+
} as const
43+
44+
export type ButtonShape = (typeof EnumButtonShape)[keyof typeof EnumButtonShape]
45+
export type ButtonFormat =
46+
(typeof EnumButtonFormat)[keyof typeof EnumButtonFormat]
47+
48+
export interface PropsButton
49+
extends React.ButtonHTMLAttributes<HTMLButtonElement> {
50+
variant?: ButtonVariant
51+
size?: ButtonSize
52+
shape?: ButtonShape
53+
format?: ButtonFormat
54+
value?: string
55+
form?: string
56+
onClick?: (e: React.MouseEvent<HTMLButtonElement>) => void
57+
}
58+
59+
const VARIANT = new Map<ButtonVariant, string>([
60+
[
61+
'primary',
62+
'border-primary-500 bg-primary-500 hover:bg-primary-400 active:bg-primary-400 text-light',
63+
],
64+
[
65+
'alternative',
66+
'border-neutral-300 bg-neutral-5 hover:bg-neutral-20 active:bg-neutral-200 text-neutral-600',
67+
],
68+
[
69+
'secondary',
70+
'border-secondary-500 bg-secondary-500 hover:bg-secondary-600 active:bg-secondary-400 text-neutral-100',
71+
],
72+
[
73+
'success',
74+
'border-success-500 bg-success-500 hover:bg-success-600 active:bg-success-400 text-neutral-100',
75+
],
76+
[
77+
'danger',
78+
'border-danger-500 bg-danger-500 hover:bg-danger-600 active:bg-danger-400 text-neutral-100',
79+
],
80+
[
81+
'warning',
82+
'border-warning-500 bg-warning-500 hover:bg-warning-600 active:bg-warning-400 text-neutral-100',
83+
],
84+
[
85+
'neutral',
86+
'border-neutral-200 bg-neutral-200 hover:bg-neutral-300 active:bg-neutral-300 text-primary-900',
87+
],
88+
[
89+
'info',
90+
'border-transparent bg-neutral-10 dark:bg-neutral-20 active:bg-neutral-10 text-neutral-700 dark:text-neutral-200',
91+
],
92+
])
93+
94+
const SHAPE = new Map<ButtonShape, string>([
95+
['rounded', `rounded-md`],
96+
['square', `rounded-none`],
97+
['circle', `rounded-full`],
98+
])
99+
100+
const SIZE = new Map<ButtonSize, string>([
101+
[EnumSize.xs, `text-xs leading-2 border`],
102+
[EnumSize.sm, `px-2 py-[0.125rem] text-xs leading-4 border-2`],
103+
[EnumSize.md, `px-3 py-2 text-base leading-6 border-2`],
104+
[EnumSize.lg, `px-4 py-3 text-lg border-4`],
105+
])
106+
107+
const Button = makeButton(
108+
React.forwardRef<HTMLButtonElement, PropsButton>(ButtonPlain),
109+
)
110+
111+
const ButtonLink = makeButton(
112+
React.forwardRef<HTMLDivElement, PropsButton>(ButtonLinkPlain),
113+
)
114+
115+
export { VARIANT, SHAPE, SIZE, Button, ButtonLink, makeButton }
116+
117+
function ButtonPlain(
118+
{
119+
type = 'button',
120+
disabled = false,
121+
children = [],
122+
form,
123+
autoFocus,
124+
tabIndex,
125+
onClick,
126+
className,
127+
}: PropsButton,
128+
ref?: React.ForwardedRef<HTMLButtonElement>,
129+
): JSX.Element {
130+
return (
131+
<button
132+
ref={ref}
133+
type={type}
134+
autoFocus={autoFocus}
135+
tabIndex={tabIndex}
136+
form={form}
137+
disabled={disabled}
138+
onClick={onClick}
139+
onKeyDown={(e: React.KeyboardEvent<HTMLButtonElement>) => {
140+
if (e.key === 'Enter' || e.key === ' ') {
141+
e.preventDefault()
142+
e.stopPropagation()
143+
144+
onClick?.(e as unknown as React.MouseEvent<HTMLButtonElement>)
145+
}
146+
}}
147+
className={className}
148+
>
149+
{children}
150+
</button>
151+
)
152+
}
153+
154+
function ButtonLinkPlain(
155+
{ children = [], autoFocus, tabIndex, className }: PropsButton,
156+
ref?: React.ForwardedRef<HTMLDivElement>,
157+
): JSX.Element {
158+
return (
159+
<div
160+
ref={ref}
161+
autoFocus={autoFocus}
162+
tabIndex={tabIndex}
163+
className={className}
164+
>
165+
{children}
166+
</div>
167+
)
168+
}
169+
170+
function makeButton<TElement = HTMLButtonElement>(
171+
Component: React.ElementType,
172+
): React.ForwardRefExoticComponent<
173+
PropsButton & React.RefAttributes<TElement>
174+
> {
175+
return React.forwardRef<TElement, PropsButton>(function Wrapper(
176+
{
177+
type = 'button',
178+
disabled = false,
179+
variant = 'primary',
180+
shape = 'rounded',
181+
size = EnumSize.md,
182+
children = [],
183+
className,
184+
form,
185+
autoFocus,
186+
tabIndex,
187+
onClick,
188+
}: PropsButton,
189+
ref?: React.ForwardedRef<TElement>,
190+
): JSX.Element {
191+
return (
192+
<Component
193+
ref={ref}
194+
type={type}
195+
disabled={disabled}
196+
form={form}
197+
autoFocus={autoFocus}
198+
tabIndex={tabIndex}
199+
onClick={onClick}
200+
className={clsx(
201+
'whitespace-nowrap flex m-1 items-center justify-center font-bold',
202+
'focus:ring-4 focus:outline-none focus:border-secondary-500',
203+
'ring-secondary-300 ring-opacity-60 ring-offset ring-offset-secondary-100',
204+
SHAPE.get(shape),
205+
SIZE.get(size),
206+
disabled
207+
? 'opacity-50 bg-neutral-10 dark:bg-neutral-20 border-transparent text-prose cursor-not-allowed'
208+
: VARIANT.get(variant),
209+
className,
210+
)}
211+
>
212+
{children}
213+
</Component>
214+
)
215+
})
216+
}
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
import React from 'react'
2+
import { vi, describe, test, expect } from 'vitest'
3+
import { render, fireEvent, renderHook } from '../../../../tests/utils'
4+
import { EnumSize, EnumVariant } from '../../../../types/enum'
5+
import {
6+
Button,
7+
makeButton,
8+
VARIANT,
9+
SHAPE,
10+
SIZE,
11+
EnumButtonShape,
12+
} from '../Button'
13+
14+
describe('Button', () => {
15+
test('renders with default variant, shape, and size', () => {
16+
const { getByText } = render(<Button>Click me</Button>)
17+
const button = getByText('Click me')
18+
19+
expect(button).toHaveClass(VARIANT.get(EnumVariant.Primary) as string)
20+
expect(button).toHaveClass(SHAPE.get(EnumButtonShape.Rounded) as string)
21+
expect(button).toHaveClass(SIZE.get(EnumSize.md) as string)
22+
})
23+
24+
test('renders with custom variant, shape, and size', () => {
25+
const { getByText } = render(
26+
<Button
27+
variant={EnumVariant.Secondary}
28+
shape={EnumButtonShape.Square}
29+
size={EnumSize.sm}
30+
>
31+
Click me
32+
</Button>,
33+
)
34+
const button = getByText('Click me')
35+
36+
expect(button).toHaveClass(VARIANT.get(EnumVariant.Secondary) as string)
37+
expect(button).toHaveClass(SHAPE.get(EnumButtonShape.Square) as string)
38+
expect(button).toHaveClass(SIZE.get(EnumSize.sm) as string)
39+
})
40+
41+
test('calls onClick when clicked', () => {
42+
const onClick = vi.fn()
43+
const { getByText } = render(<Button onClick={onClick}>Click me</Button>)
44+
const button = getByText('Click me')
45+
46+
fireEvent.click(button)
47+
expect(onClick).toHaveBeenCalled()
48+
})
49+
})
50+
51+
describe('ButtonMenu', () => {
52+
test('renders with default variant, shape, and size', () => {
53+
const ButtonMenu = createButton()
54+
const { getByText } = render(<ButtonMenu>Click me</ButtonMenu>)
55+
const button = getByText('Click me')
56+
57+
expect(button).toHaveClass(VARIANT.get(EnumVariant.Primary) as string)
58+
expect(button).toHaveClass(SHAPE.get(EnumButtonShape.Rounded) as string)
59+
expect(button).toHaveClass(SIZE.get(EnumSize.md) as string)
60+
})
61+
62+
test('renders with custom variant, shape, and size', () => {
63+
const ButtonMenu = createButton()
64+
const { getByText } = render(
65+
<ButtonMenu
66+
variant={EnumVariant.Secondary}
67+
shape={EnumButtonShape.Square}
68+
size={EnumSize.sm}
69+
>
70+
Click me
71+
</ButtonMenu>,
72+
)
73+
const button = getByText('Click me')
74+
75+
expect(button).toHaveClass(VARIANT.get(EnumVariant.Secondary) as string)
76+
expect(button).toHaveClass(SHAPE.get(EnumButtonShape.Square) as string)
77+
expect(button).toHaveClass(SIZE.get(EnumSize.sm) as string)
78+
})
79+
80+
test('calls onClick when clicked', () => {
81+
const ButtonMenu = createButton()
82+
const onClick = vi.fn()
83+
const { getByText } = render(
84+
<ButtonMenu onClick={onClick}>Click me</ButtonMenu>,
85+
)
86+
const button = getByText('Click me')
87+
88+
fireEvent.click(button)
89+
expect(onClick).toHaveBeenCalled()
90+
})
91+
92+
test('get ref from component', () => {
93+
const ButtonMenu = createButton()
94+
const { result } = renderHook(() => React.useRef<HTMLDivElement>(null))
95+
const { getByText } = render(
96+
<ButtonMenu ref={result.current}>Click me</ButtonMenu>,
97+
)
98+
const button = getByText('Click me')
99+
100+
expect(result.current.current).toBe(button)
101+
})
102+
})
103+
104+
function createButton(): any {
105+
return makeButton(
106+
React.forwardRef<any, any>(function Button({ children, ...props }, ref) {
107+
return (
108+
<div
109+
{...props}
110+
role="button"
111+
ref={ref}
112+
>
113+
{children}
114+
</div>
115+
)
116+
}),
117+
)
118+
}

vscode/react/src/components/graph/ModelLineage.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,12 @@ import {
3535
import ModelLineageSearch from './ModelLineageSearch'
3636
import { Popover } from '@headlessui/react'
3737
import ModelLineageDetails from './ModelLineageDetails'
38-
import { Divider } from '@components/divider/Divider'
38+
import { Divider } from '@/components/divider/Divider'
3939
import { type ModelLineageApiLineageModelNameGet200 } from '@api/client'
4040

4141
const WITH_COLUMNS_LIMIT = 30
4242

43-
export default function ModelLineage({
43+
export function ModelLineage({
4444
model,
4545
highlightedNodes,
4646
}: {

vscode/react/src/components/graph/ModelLineageDetails.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { isFalse, isNil, isNotNil, truncate } from '@utils/index'
22
import { useLineageFlow } from './context'
33
import { useReactFlow, type Node } from 'reactflow'
4-
import { Button, EnumButtonFormat } from '@components/button/Button'
4+
import { Button, EnumButtonFormat } from '@/components/button/Button'
55
import { EnumSize, EnumVariant } from '~/types/enum'
66
import { EnumLineageNodeModelType } from './ModelNode'
77

0 commit comments

Comments
 (0)