@xjur-ui/react 1.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/.turbo/turbo-build.log +57 -0
- package/dist/components/resources/icons.d.ts +4 -0
- package/dist/components/resources/icons.js +133 -0
- package/dist/components/resources/logo/horizontal.d.ts +12 -0
- package/dist/components/resources/logo/horizontal.js +107 -0
- package/dist/components/resources/logo/icon.d.ts +12 -0
- package/dist/components/resources/logo/icon.js +79 -0
- package/dist/components/resources/logo/index.d.ts +4 -0
- package/dist/components/resources/logo/index.js +291 -0
- package/dist/components/resources/logo/vertical.d.ts +12 -0
- package/dist/components/resources/logo/vertical.js +107 -0
- package/dist/components/ui/accordion.d.ts +5 -0
- package/dist/components/ui/accordion.js +8 -0
- package/dist/components/ui/button.d.ts +16 -0
- package/dist/components/ui/button.js +95 -0
- package/dist/components/ui/icon.d.ts +12 -0
- package/dist/components/ui/icon.js +158 -0
- package/dist/components/ui/index.d.ts +17 -0
- package/dist/components/ui/index.js +788 -0
- package/dist/components/ui/input/content.d.ts +9 -0
- package/dist/components/ui/input/content.js +183 -0
- package/dist/components/ui/input/index.d.ts +12 -0
- package/dist/components/ui/input/index.js +335 -0
- package/dist/components/ui/input/label.d.ts +12 -0
- package/dist/components/ui/input/label.js +165 -0
- package/dist/components/ui/input/message.d.ts +10 -0
- package/dist/components/ui/input/message.js +128 -0
- package/dist/components/ui/input/root.d.ts +18 -0
- package/dist/components/ui/input/root.js +163 -0
- package/dist/components/ui/input/slot.d.ts +10 -0
- package/dist/components/ui/input/slot.js +20 -0
- package/dist/components/ui/input/text.d.ts +10 -0
- package/dist/components/ui/input/text.js +195 -0
- package/dist/components/ui/logo.d.ts +10 -0
- package/dist/components/ui/logo.js +324 -0
- package/dist/components/ui/otp-input.d.ts +13 -0
- package/dist/components/ui/otp-input.js +47 -0
- package/dist/components/ui/typography.d.ts +17 -0
- package/dist/components/ui/typography.js +78 -0
- package/dist/index.css +770 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.js +788 -0
- package/eslint.config.js +3 -0
- package/package.json +41 -0
- package/postcss.config.js +5 -0
- package/prettier.config.js +7 -0
- package/src/components/resources/icons.ts +131 -0
- package/src/components/resources/logo/horizontal.tsx +70 -0
- package/src/components/resources/logo/icon.tsx +54 -0
- package/src/components/resources/logo/index.ts +3 -0
- package/src/components/resources/logo/vertical.tsx +70 -0
- package/src/components/ui/accordion.tsx +3 -0
- package/src/components/ui/button.tsx +105 -0
- package/src/components/ui/icon.tsx +29 -0
- package/src/components/ui/index.ts +13 -0
- package/src/components/ui/input/content.tsx +59 -0
- package/src/components/ui/input/index.ts +6 -0
- package/src/components/ui/input/label.tsx +41 -0
- package/src/components/ui/input/message.tsx +37 -0
- package/src/components/ui/input/root.tsx +57 -0
- package/src/components/ui/input/slot.tsx +21 -0
- package/src/components/ui/input/text.tsx +69 -0
- package/src/components/ui/logo.tsx +39 -0
- package/src/components/ui/otp-input.tsx +45 -0
- package/src/components/ui/typography.tsx +85 -0
- package/src/index.css +2 -0
- package/src/index.ts +2 -0
- package/src/types.d.ts +4 -0
- package/tsconfig.json +4 -0
- package/tsup.config.ts +12 -0
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { memo } from 'react'
|
|
2
|
+
import { cx } from '@xjur-ui/util'
|
|
3
|
+
import { Typography, type TypographyProps } from '../typography'
|
|
4
|
+
import { useInput } from './root'
|
|
5
|
+
|
|
6
|
+
export type InputMessageProps = TypographyProps
|
|
7
|
+
|
|
8
|
+
export const InputMessage = memo(
|
|
9
|
+
({
|
|
10
|
+
children,
|
|
11
|
+
className,
|
|
12
|
+
weight = 'normal',
|
|
13
|
+
variant = 'body',
|
|
14
|
+
size = 'sm-1x',
|
|
15
|
+
...props
|
|
16
|
+
}: InputMessageProps) => {
|
|
17
|
+
const { errorMessage } = useInput()
|
|
18
|
+
|
|
19
|
+
return (
|
|
20
|
+
<Typography
|
|
21
|
+
className={cx(
|
|
22
|
+
'text-neutral-dark data-[error=true]:text-danger-idle',
|
|
23
|
+
className
|
|
24
|
+
)}
|
|
25
|
+
data-error={!!errorMessage}
|
|
26
|
+
size={size}
|
|
27
|
+
variant={variant}
|
|
28
|
+
weight={weight}
|
|
29
|
+
{...props}
|
|
30
|
+
>
|
|
31
|
+
{children}
|
|
32
|
+
</Typography>
|
|
33
|
+
)
|
|
34
|
+
}
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
InputMessage.displayName = 'InputMessage'
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { type ComponentProps, createContext, use } from 'react'
|
|
2
|
+
import { cx } from '@xjur-ui/util'
|
|
3
|
+
import { InputMessage } from './message'
|
|
4
|
+
|
|
5
|
+
export type InputRoot = {
|
|
6
|
+
size?: 'md' | 'lg'
|
|
7
|
+
rounded?: boolean
|
|
8
|
+
errorMessage?: string
|
|
9
|
+
disabled?: boolean
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export const InputRootContext = createContext({} as InputRoot)
|
|
13
|
+
|
|
14
|
+
export function useInput() {
|
|
15
|
+
const context = use(InputRootContext)
|
|
16
|
+
|
|
17
|
+
if (!context) {
|
|
18
|
+
throw new Error(
|
|
19
|
+
'useInput must be called within <Input.Root> or <Select.Root>'
|
|
20
|
+
)
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
return context
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export type InputRootProps = ComponentProps<'div'> & {
|
|
27
|
+
children: ComponentProps<'div'>['children']
|
|
28
|
+
} & InputRoot
|
|
29
|
+
|
|
30
|
+
export function InputRoot({
|
|
31
|
+
children,
|
|
32
|
+
className,
|
|
33
|
+
errorMessage,
|
|
34
|
+
size = 'lg',
|
|
35
|
+
rounded = false,
|
|
36
|
+
disabled,
|
|
37
|
+
...props
|
|
38
|
+
}: InputRootProps) {
|
|
39
|
+
return (
|
|
40
|
+
<InputRootContext.Provider
|
|
41
|
+
value={{ errorMessage, disabled, size, rounded }}
|
|
42
|
+
>
|
|
43
|
+
<div
|
|
44
|
+
{...props}
|
|
45
|
+
className={cx(
|
|
46
|
+
'group gap-small relative flex flex-col data-[disabled=true]:opacity-60',
|
|
47
|
+
className
|
|
48
|
+
)}
|
|
49
|
+
data-disabled={disabled}
|
|
50
|
+
>
|
|
51
|
+
{children}
|
|
52
|
+
|
|
53
|
+
{errorMessage && <InputMessage>{errorMessage}</InputMessage>}
|
|
54
|
+
</div>
|
|
55
|
+
</InputRootContext.Provider>
|
|
56
|
+
)
|
|
57
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { type ComponentProps, memo } from 'react'
|
|
2
|
+
import { cx } from '@xjur-ui/util'
|
|
3
|
+
|
|
4
|
+
export type InputSlotProps = ComponentProps<'label'> & {
|
|
5
|
+
children: ComponentProps<'label'>['children']
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export const InputSlot = memo(
|
|
9
|
+
({ children, className, ...props }: InputSlotProps) => {
|
|
10
|
+
return (
|
|
11
|
+
<label
|
|
12
|
+
{...props}
|
|
13
|
+
className={cx('flex items-center justify-center', className)}
|
|
14
|
+
>
|
|
15
|
+
{children}
|
|
16
|
+
</label>
|
|
17
|
+
)
|
|
18
|
+
}
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
InputSlot.displayName = 'InputSlot'
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { InputMask, type MaskOptions } from '@react-input/mask'
|
|
2
|
+
import { type ComponentProps, useCallback, useEffect, useRef } from 'react'
|
|
3
|
+
import { cx } from '@xjur-ui/util'
|
|
4
|
+
import { useInput } from './root'
|
|
5
|
+
|
|
6
|
+
export type InputTextProps = ComponentProps<'input'> & { mask?: MaskOptions }
|
|
7
|
+
|
|
8
|
+
export function InputText({
|
|
9
|
+
className,
|
|
10
|
+
value,
|
|
11
|
+
mask,
|
|
12
|
+
...props
|
|
13
|
+
}: InputTextProps) {
|
|
14
|
+
const { errorMessage } = useInput()
|
|
15
|
+
const inputRef = useRef<HTMLInputElement>(null)
|
|
16
|
+
const InputComponent = mask ? InputMask : 'input'
|
|
17
|
+
|
|
18
|
+
const onCheckInputFilled = useCallback(
|
|
19
|
+
({ shouldUnfill = false }: { shouldUnfill: boolean }) => {
|
|
20
|
+
if (inputRef.current) {
|
|
21
|
+
if (shouldUnfill) inputRef.current.dataset.filled = 'false'
|
|
22
|
+
else {
|
|
23
|
+
const hasNotErrorAndHasValue =
|
|
24
|
+
!errorMessage && !!inputRef.current.value
|
|
25
|
+
inputRef.current.dataset.filled = String(hasNotErrorAndHasValue)
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
[errorMessage]
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
function setRef(ref: HTMLInputElement) {
|
|
33
|
+
inputRef.current = ref
|
|
34
|
+
|
|
35
|
+
if (typeof props.ref === 'function') {
|
|
36
|
+
props.ref(ref)
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
useEffect(() => {
|
|
41
|
+
onCheckInputFilled({ shouldUnfill: false })
|
|
42
|
+
}, [onCheckInputFilled])
|
|
43
|
+
|
|
44
|
+
return (
|
|
45
|
+
<InputComponent
|
|
46
|
+
{...props}
|
|
47
|
+
{...(mask && { ...mask })}
|
|
48
|
+
className={cx(
|
|
49
|
+
'h-full w-full bg-transparent',
|
|
50
|
+
'border-hidden outline-hidden',
|
|
51
|
+
'placeholder:text-placeholder-neutral font-normal',
|
|
52
|
+
'text-neutral-dark text-size-body-md overflow-hidden text-ellipsis',
|
|
53
|
+
className
|
|
54
|
+
)}
|
|
55
|
+
data-filled={!!value && !errorMessage}
|
|
56
|
+
readOnly={props.readOnly !== undefined && props.readOnly}
|
|
57
|
+
ref={setRef}
|
|
58
|
+
value={value}
|
|
59
|
+
onBlur={event => {
|
|
60
|
+
props.onBlur?.(event)
|
|
61
|
+
onCheckInputFilled({ shouldUnfill: false })
|
|
62
|
+
}}
|
|
63
|
+
onFocus={event => {
|
|
64
|
+
props.onFocus?.(event)
|
|
65
|
+
onCheckInputFilled({ shouldUnfill: true })
|
|
66
|
+
}}
|
|
67
|
+
/>
|
|
68
|
+
)
|
|
69
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { memo } from 'react'
|
|
2
|
+
import { Horizontal, Vertical, Icon } from '../resources/logo'
|
|
3
|
+
|
|
4
|
+
export interface LogoProps {
|
|
5
|
+
mode?: 'horizontal' | 'vertical' | 'icon'
|
|
6
|
+
variant?: 'colorful' | 'orange' | 'purple' | 'white' | 'gray'
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export const Logo = memo(
|
|
10
|
+
({ mode = 'horizontal', variant = 'colorful' }: LogoProps) => {
|
|
11
|
+
const colorToHex = {
|
|
12
|
+
orange: '#D68600',
|
|
13
|
+
purple: '#66127D',
|
|
14
|
+
white: '#FFFFFF',
|
|
15
|
+
gray: '#6B7280'
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
switch (mode) {
|
|
19
|
+
case 'icon':
|
|
20
|
+
if (variant === 'colorful') {
|
|
21
|
+
return <Icon.Colorful />
|
|
22
|
+
}
|
|
23
|
+
return <Icon.Solid color={colorToHex[variant]} />
|
|
24
|
+
case 'vertical':
|
|
25
|
+
if (variant === 'colorful') {
|
|
26
|
+
return <Vertical.Colorful />
|
|
27
|
+
}
|
|
28
|
+
return <Vertical.Solid color={colorToHex[variant]} />
|
|
29
|
+
case 'horizontal':
|
|
30
|
+
default:
|
|
31
|
+
if (variant === 'colorful') {
|
|
32
|
+
return <Horizontal.Colorful />
|
|
33
|
+
}
|
|
34
|
+
return <Horizontal.Solid color={colorToHex[variant]} />
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
Logo.displayName = 'Logo'
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import * as OTPPasswordField from '@radix-ui/react-one-time-password-field'
|
|
2
|
+
import { cx } from '@xjur-ui/util'
|
|
3
|
+
|
|
4
|
+
function Root({
|
|
5
|
+
children,
|
|
6
|
+
className,
|
|
7
|
+
...props
|
|
8
|
+
}: OTPPasswordField.OneTimePasswordFieldProps) {
|
|
9
|
+
return (
|
|
10
|
+
<OTPPasswordField.Root
|
|
11
|
+
className={cx(className, 'group gap-small flex items-center')}
|
|
12
|
+
{...props}
|
|
13
|
+
>
|
|
14
|
+
{children}
|
|
15
|
+
</OTPPasswordField.Root>
|
|
16
|
+
)
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function Input({
|
|
20
|
+
className,
|
|
21
|
+
...props
|
|
22
|
+
}: OTPPasswordField.OneTimePasswordFieldInputProps) {
|
|
23
|
+
return (
|
|
24
|
+
<OTPPasswordField.Input
|
|
25
|
+
className={cx(
|
|
26
|
+
className,
|
|
27
|
+
'text-neutral-dark h-large-6x bg-layer-2-hover rounded-small-1x w-full text-center outline-0',
|
|
28
|
+
'focus-within:border-primary-idle focus-within:shadow-focus-primary focus-within:border'
|
|
29
|
+
)}
|
|
30
|
+
{...props}
|
|
31
|
+
/>
|
|
32
|
+
)
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function HiddenInput({
|
|
36
|
+
...props
|
|
37
|
+
}: OTPPasswordField.OneTimePasswordFieldHiddenInputProps) {
|
|
38
|
+
return <OTPPasswordField.HiddenInput {...props} />
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export const OTPInput = {
|
|
42
|
+
Root,
|
|
43
|
+
Input,
|
|
44
|
+
HiddenInput
|
|
45
|
+
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { Slot } from '@radix-ui/react-slot'
|
|
2
|
+
import { cva, type ClassVariantProps } from '@xjur-ui/util'
|
|
3
|
+
import { memo, type ComponentProps } from 'react'
|
|
4
|
+
|
|
5
|
+
const typographyVariants = cva('', {
|
|
6
|
+
variants: {
|
|
7
|
+
variant: {
|
|
8
|
+
body: '',
|
|
9
|
+
label: '',
|
|
10
|
+
title: '',
|
|
11
|
+
headline: ''
|
|
12
|
+
},
|
|
13
|
+
size: {
|
|
14
|
+
'sm-2x': '',
|
|
15
|
+
'sm-1x': '',
|
|
16
|
+
sm: '',
|
|
17
|
+
md: '',
|
|
18
|
+
lg: ''
|
|
19
|
+
},
|
|
20
|
+
weight: {
|
|
21
|
+
thin: 'font-thin',
|
|
22
|
+
extraLight: 'font-extralight',
|
|
23
|
+
light: 'font-light',
|
|
24
|
+
normal: 'font-normal',
|
|
25
|
+
medium: 'font-medium',
|
|
26
|
+
semibold: 'font-semibold',
|
|
27
|
+
bold: 'font-bold',
|
|
28
|
+
extraBold: 'font-extrabold',
|
|
29
|
+
black: 'font-black'
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
compoundVariants: [
|
|
33
|
+
{ variant: 'body', size: 'sm-1x', class: 'text-size-body-sm-1x' },
|
|
34
|
+
{ variant: 'body', size: 'sm', class: 'text-size-body-sm' },
|
|
35
|
+
{ variant: 'body', size: 'md', class: 'text-size-body-md' },
|
|
36
|
+
{ variant: 'body', size: 'lg', class: 'text-size-body-lg' },
|
|
37
|
+
|
|
38
|
+
{ variant: 'label', size: 'sm-2x', class: 'text-size-label-sm-2x' },
|
|
39
|
+
{ variant: 'label', size: 'sm-1x', class: 'text-size-label-sm-1x' },
|
|
40
|
+
{ variant: 'label', size: 'sm', class: 'text-size-label-sm' },
|
|
41
|
+
{ variant: 'label', size: 'md', class: 'text-size-label-md' },
|
|
42
|
+
{ variant: 'label', size: 'lg', class: 'text-size-label-lg' },
|
|
43
|
+
|
|
44
|
+
{ variant: 'title', size: 'sm', class: 'text-size-title-sm' },
|
|
45
|
+
{ variant: 'title', size: 'md', class: 'text-size-title-md' },
|
|
46
|
+
{ variant: 'title', size: 'lg', class: 'text-size-title-lg' },
|
|
47
|
+
|
|
48
|
+
{ variant: 'headline', size: 'sm', class: 'text-size-headline-sm' },
|
|
49
|
+
{ variant: 'headline', size: 'md', class: 'text-size-headline-md' },
|
|
50
|
+
{ variant: 'headline', size: 'lg', class: 'text-size-headline-lg' }
|
|
51
|
+
],
|
|
52
|
+
defaultVariants: {
|
|
53
|
+
variant: 'body',
|
|
54
|
+
size: 'md',
|
|
55
|
+
weight: 'normal'
|
|
56
|
+
}
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
export interface TypographyProps
|
|
60
|
+
extends ComponentProps<'base'>,
|
|
61
|
+
ClassVariantProps<typeof typographyVariants> {
|
|
62
|
+
asChild?: boolean
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export const Typography = memo(
|
|
66
|
+
({
|
|
67
|
+
variant,
|
|
68
|
+
size,
|
|
69
|
+
weight,
|
|
70
|
+
asChild,
|
|
71
|
+
className,
|
|
72
|
+
...props
|
|
73
|
+
}: TypographyProps) => {
|
|
74
|
+
const Component = asChild ? Slot : 'span'
|
|
75
|
+
|
|
76
|
+
return (
|
|
77
|
+
<Component
|
|
78
|
+
className={typographyVariants({ variant, size, weight, className })}
|
|
79
|
+
{...props}
|
|
80
|
+
/>
|
|
81
|
+
)
|
|
82
|
+
}
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
Typography.displayName = 'Typography'
|
package/src/index.css
ADDED
package/src/index.ts
ADDED
package/src/types.d.ts
ADDED
package/tsconfig.json
ADDED
package/tsup.config.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { defineConfig } from 'tsup'
|
|
2
|
+
|
|
3
|
+
export default defineConfig({
|
|
4
|
+
// all js and ts
|
|
5
|
+
entry: ['src/index.ts', 'src/components/**/*.ts', 'src/components/**/*.tsx'],
|
|
6
|
+
format: ['esm'],
|
|
7
|
+
outDir: 'dist',
|
|
8
|
+
external: ['react', 'react-dom'],
|
|
9
|
+
dts: true,
|
|
10
|
+
splitting: false,
|
|
11
|
+
clean: true
|
|
12
|
+
})
|