@xjur-ui/react 1.0.6 → 2.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 +97 -45
- package/CHANGELOG.md +44 -0
- package/README.md +146 -0
- package/dist/chunk-CBFC4QME.js +2 -0
- package/dist/chunk-CBFC4QME.js.map +1 -0
- package/dist/chunk-EIG6CBTQ.js +2 -0
- package/dist/chunk-EIG6CBTQ.js.map +1 -0
- package/dist/chunk-FASEHVMD.js +2 -0
- package/dist/chunk-FASEHVMD.js.map +1 -0
- package/dist/chunk-KIFR5VIE.js +2 -0
- package/dist/chunk-KIFR5VIE.js.map +1 -0
- package/dist/chunk-KS6WGBHQ.js +2 -0
- package/dist/chunk-KS6WGBHQ.js.map +1 -0
- package/dist/chunk-NELCN6E2.js +2 -0
- package/dist/chunk-NELCN6E2.js.map +1 -0
- package/dist/chunk-NPTLORW5.js +2 -0
- package/dist/chunk-NPTLORW5.js.map +1 -0
- package/dist/chunk-RWMV7APX.js +2 -0
- package/dist/chunk-RWMV7APX.js.map +1 -0
- package/dist/chunk-SHHXKVVR.js +2 -0
- package/dist/chunk-SHHXKVVR.js.map +1 -0
- package/dist/chunk-TB6KI6CL.js +2 -0
- package/dist/chunk-TB6KI6CL.js.map +1 -0
- package/dist/components/avatar-group.js +2 -179
- package/dist/components/avatar-group.js.map +1 -0
- package/dist/components/avatar.js +2 -59
- package/dist/components/avatar.js.map +1 -0
- package/dist/components/badge.js +2 -111
- package/dist/components/badge.js.map +1 -0
- package/dist/components/button.js +2 -98
- package/dist/components/button.js.map +1 -0
- package/dist/components/calendar.js +2 -751
- package/dist/components/calendar.js.map +1 -0
- package/dist/components/checkbox.js +2 -153
- package/dist/components/checkbox.js.map +1 -0
- package/dist/components/chip.d.ts +3 -1
- package/dist/components/chip.js +2 -256
- package/dist/components/chip.js.map +1 -0
- package/dist/components/collapsible.js +2 -41
- package/dist/components/collapsible.js.map +1 -0
- package/dist/components/date-picker.d.ts +8 -3
- package/dist/components/date-picker.js +2 -232
- package/dist/components/date-picker.js.map +1 -0
- package/dist/components/divider.js +2 -29
- package/dist/components/divider.js.map +1 -0
- package/dist/components/dropdown-menu.js +2 -295
- package/dist/components/dropdown-menu.js.map +1 -0
- package/dist/components/icon.js +2 -177
- package/dist/components/icon.js.map +1 -0
- package/dist/components/input.d.ts +9 -4
- package/dist/components/input.js +2 -315
- package/dist/components/input.js.map +1 -0
- package/dist/components/list.js +2 -179
- package/dist/components/list.js.map +1 -0
- package/dist/components/logo.js +2 -324
- package/dist/components/logo.js.map +1 -0
- package/dist/components/otp-input.js +2 -47
- package/dist/components/otp-input.js.map +1 -0
- package/dist/components/radio.js +2 -156
- package/dist/components/radio.js.map +1 -0
- package/dist/components/rich-editor.d.ts +2 -1
- package/dist/components/rich-editor.js +2 -723
- package/dist/components/rich-editor.js.map +1 -0
- package/dist/components/search-input.js +2 -274
- package/dist/components/search-input.js.map +1 -0
- package/dist/components/select.d.ts +6 -3
- package/dist/components/select.js +2 -550
- package/dist/components/select.js.map +1 -0
- package/dist/components/sheet.js +2 -251
- package/dist/components/sheet.js.map +1 -0
- package/dist/components/skeleton.js +2 -16
- package/dist/components/skeleton.js.map +1 -0
- package/dist/components/status.js +2 -111
- package/dist/components/status.js.map +1 -0
- package/dist/components/switch.js +2 -36
- package/dist/components/switch.js.map +1 -0
- package/dist/components/table.js +2 -196
- package/dist/components/table.js.map +1 -0
- package/dist/components/tabs.d.ts +9 -6
- package/dist/components/tabs.js +2 -54
- package/dist/components/tabs.js.map +1 -0
- package/dist/components/tag.d.ts +3 -1
- package/dist/components/tag.js +2 -189
- package/dist/components/tag.js.map +1 -0
- package/dist/components/tooltip.js +2 -58
- package/dist/components/tooltip.js.map +1 -0
- package/dist/components/typography.js +2 -78
- package/dist/components/typography.js.map +1 -0
- package/dist/hooks/index.d.ts +7 -0
- package/dist/hooks/index.js +2 -0
- package/dist/hooks/index.js.map +1 -0
- package/dist/index.css +2 -2322
- package/dist/index.css.map +1 -0
- package/dist/logo-PQRZORCS.js +3 -0
- package/dist/logo-PQRZORCS.js.map +1 -0
- package/package.json +41 -8
- package/src/components/calendar.tsx +7 -6
- package/src/components/chip.tsx +11 -3
- package/src/components/date-picker.tsx +125 -22
- package/src/components/icon.tsx +1 -1
- package/src/components/input.tsx +124 -60
- package/src/components/logo.tsx +25 -20
- package/src/components/rich-editor.tsx +4 -3
- package/src/components/select.tsx +104 -26
- package/src/components/tabs.tsx +56 -37
- package/src/components/tag.tsx +11 -3
- package/src/index.css +2 -2
- package/src/resources/logo/index.tsx +33 -0
- package/tsup.config.ts +23 -5
- package/dist/components/test.d.ts +0 -5
- package/dist/components/test.js +0 -8
- package/dist/index.js +0 -0
- package/src/components/test.tsx +0 -3
- package/src/index.ts +0 -1
- package/src/resources/logo/index.ts +0 -3
|
@@ -1,29 +1,86 @@
|
|
|
1
|
+
import { createContext, useContext } from 'react'
|
|
1
2
|
import type { ComponentProps } from 'react'
|
|
2
3
|
import * as RadixPopover from '@radix-ui/react-popover'
|
|
3
|
-
import {
|
|
4
|
+
import { tv, twJoin, twMerge } from '@xjur-ui/util'
|
|
4
5
|
import { Typography, type TypographyProps } from './typography'
|
|
5
6
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
const DatePickerContext = createContext({
|
|
8
|
+
disabled: false,
|
|
9
|
+
variant: 'filled' as 'filled' | 'outlined',
|
|
10
|
+
hasError: false
|
|
11
|
+
})
|
|
12
|
+
|
|
13
|
+
function useDatePicker() {
|
|
14
|
+
const context = useContext(DatePickerContext)
|
|
15
|
+
if (!context) {
|
|
16
|
+
throw new Error('useDatePicker must be used within a DatePickerRoot')
|
|
17
|
+
}
|
|
18
|
+
return context
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function DatePickerRoot({
|
|
22
|
+
disabled = false,
|
|
23
|
+
variant = 'filled',
|
|
24
|
+
hasError = false,
|
|
25
|
+
...props
|
|
26
|
+
}: ComponentProps<typeof RadixPopover.Root> & {
|
|
27
|
+
disabled?: boolean
|
|
28
|
+
variant?: 'filled' | 'outlined'
|
|
29
|
+
hasError?: boolean
|
|
30
|
+
}) {
|
|
31
|
+
return (
|
|
32
|
+
<DatePickerContext.Provider value={{ disabled, variant, hasError }}>
|
|
33
|
+
<RadixPopover.Root {...props} />
|
|
34
|
+
</DatePickerContext.Provider>
|
|
35
|
+
)
|
|
10
36
|
}
|
|
11
37
|
|
|
12
38
|
export function DatePickerTrigger({
|
|
13
39
|
className,
|
|
14
40
|
...props
|
|
15
41
|
}: ComponentProps<typeof RadixPopover.Trigger>) {
|
|
42
|
+
const { disabled, variant, hasError } = useDatePicker()
|
|
43
|
+
|
|
44
|
+
const trigger = tv({
|
|
45
|
+
base: twMerge(
|
|
46
|
+
'border border-transparent group h-large-4x rounded-small-1x gap-small py-small_1x-alt px-small relative flex w-full items-center cursor-pointer',
|
|
47
|
+
'data-[state=open]:border-primary-idle',
|
|
48
|
+
'has-[input:not(:placeholder-shown)]:text-primary-idle',
|
|
49
|
+
'has-[input:not(:placeholder-shown)]:border-primary-idle',
|
|
50
|
+
'focus-within:border-primary-idle focus-within:hover:border-primary-idle',
|
|
51
|
+
'hover:border-border-layer-1'
|
|
52
|
+
),
|
|
53
|
+
variants: {
|
|
54
|
+
variant: {
|
|
55
|
+
filled: 'bg-layer-2-hover',
|
|
56
|
+
outlined:
|
|
57
|
+
'bg-layer-2-idle border-border-layer-2 hover:border-border-layer-3',
|
|
58
|
+
disabled:
|
|
59
|
+
'hover:border-transparent border-none bg-layer-2-idle cursor-text select-text'
|
|
60
|
+
},
|
|
61
|
+
state: {
|
|
62
|
+
idle: '',
|
|
63
|
+
error: twMerge(
|
|
64
|
+
'focus-within:border-danger-idle hover:border-danger-idle border-danger-idle focus-within:hover:border-danger-idle',
|
|
65
|
+
'data-[state=open]:border-danger-idle has-[input:not(:placeholder-shown)]:border-danger-idle'
|
|
66
|
+
)
|
|
67
|
+
}
|
|
68
|
+
},
|
|
69
|
+
defaultVariants: {
|
|
70
|
+
variant: 'filled',
|
|
71
|
+
state: 'idle'
|
|
72
|
+
}
|
|
73
|
+
})
|
|
74
|
+
|
|
16
75
|
return (
|
|
17
76
|
<RadixPopover.Trigger
|
|
18
|
-
className={
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
'has-[input:not(:placeholder-shown)]:text-primary-idle',
|
|
24
|
-
'has-[input:not(:placeholder-shown)]:border-primary-idle'
|
|
25
|
-
)}
|
|
77
|
+
className={trigger({
|
|
78
|
+
variant: disabled ? 'disabled' : variant,
|
|
79
|
+
state: hasError ? 'error' : 'idle',
|
|
80
|
+
className
|
|
81
|
+
})}
|
|
26
82
|
{...props}
|
|
83
|
+
disabled={disabled}
|
|
27
84
|
/>
|
|
28
85
|
)
|
|
29
86
|
}
|
|
@@ -39,7 +96,7 @@ export function DatePickerContent({
|
|
|
39
96
|
<RadixPopover.Portal>
|
|
40
97
|
<RadixPopover.Content
|
|
41
98
|
align={align}
|
|
42
|
-
className={
|
|
99
|
+
className={twJoin(
|
|
43
100
|
className,
|
|
44
101
|
'group z-10 max-h-[var(--radix-popover-content-available-height)] max-w-[var(--radix-popover-content-available-width)] min-w-[var(--radix-popover-trigger-width)]'
|
|
45
102
|
)}
|
|
@@ -68,7 +125,7 @@ export function DatePickerValue({
|
|
|
68
125
|
<input
|
|
69
126
|
{...props}
|
|
70
127
|
aria-readonly={true}
|
|
71
|
-
className={
|
|
128
|
+
className={twJoin('pointer-events-none', className)}
|
|
72
129
|
hidden={true}
|
|
73
130
|
placeholder={props.placeholder ?? ' '}
|
|
74
131
|
readOnly={true}
|
|
@@ -84,20 +141,22 @@ export function DatePickerLabel({
|
|
|
84
141
|
children,
|
|
85
142
|
...props
|
|
86
143
|
}: TypographyProps & { htmlFor?: string }) {
|
|
144
|
+
const { variant, disabled, hasError } = useDatePicker()
|
|
145
|
+
|
|
87
146
|
return (
|
|
88
147
|
<Typography
|
|
89
148
|
asChild={true}
|
|
90
|
-
className={
|
|
91
|
-
'inline-block max-w-full truncate text-left font-normal',
|
|
149
|
+
className={twJoin(
|
|
150
|
+
'group inline-block max-w-full truncate text-left font-normal',
|
|
92
151
|
'left-small right-small pointer-events-none absolute top-1/2 -translate-y-1/2',
|
|
93
152
|
'ease transition-all duration-250',
|
|
94
153
|
// Content Open
|
|
95
|
-
'group-data-[state=open]:text-primary-idle',
|
|
154
|
+
'group-data-[state=open]:text-primary-idle group-data-[state=open]:data-[error=true]:text-danger-label-active',
|
|
96
155
|
'group-data-[state=open]:-top-[3px]',
|
|
97
156
|
'group-data-[state=open]:text-size-label-sm-1x',
|
|
98
157
|
'group-data-[state=open]:font-medium',
|
|
99
158
|
// Filled
|
|
100
|
-
'group-has-[input:not(:placeholder-shown)]:text-primary-idle',
|
|
159
|
+
'group-has-[input:not(:placeholder-shown)]:text-primary-idle group-has-[input:not(:placeholder-shown)]:data-[error=true]:text-danger-label-active',
|
|
101
160
|
'group-has-[input:not(:placeholder-shown)]:-top-[3px]',
|
|
102
161
|
'group-has-[input:not(:placeholder-shown)]:text-size-label-sm-1x',
|
|
103
162
|
'group-has-[input:not(:placeholder-shown)]:font-medium',
|
|
@@ -113,13 +172,24 @@ export function DatePickerLabel({
|
|
|
113
172
|
'group-data-[state=open]:animate-in',
|
|
114
173
|
'group-data-[state=closed]:animate-out',
|
|
115
174
|
'group-has-[input:not(:placeholder-shown)]:animate-out',
|
|
175
|
+
'data-[disabled=true]:hidden',
|
|
176
|
+
|
|
116
177
|
className
|
|
117
178
|
)}
|
|
179
|
+
data-disabled={disabled}
|
|
180
|
+
data-error={hasError}
|
|
181
|
+
data-variant={variant}
|
|
118
182
|
weight="medium"
|
|
119
183
|
{...props}
|
|
120
184
|
>
|
|
121
185
|
<label htmlFor={htmlFor}>
|
|
122
|
-
<span
|
|
186
|
+
<span
|
|
187
|
+
className={twJoin(
|
|
188
|
+
'rounded-small-1x max-w-full',
|
|
189
|
+
'group-data-[variant=outlined]:bg-layer-2-idle',
|
|
190
|
+
'group-data-[variant=filled]:bg-layer-2-hover'
|
|
191
|
+
)}
|
|
192
|
+
>
|
|
123
193
|
{children}
|
|
124
194
|
</span>
|
|
125
195
|
</label>
|
|
@@ -134,7 +204,7 @@ export function DatePickerLeftSlot({
|
|
|
134
204
|
return (
|
|
135
205
|
<div
|
|
136
206
|
{...props}
|
|
137
|
-
className={
|
|
207
|
+
className={twJoin(
|
|
138
208
|
className,
|
|
139
209
|
'left-small absolute top-1/2 flex -translate-y-1/2 items-center justify-center'
|
|
140
210
|
)}
|
|
@@ -150,7 +220,7 @@ export function DatePickerRightSlot({
|
|
|
150
220
|
return (
|
|
151
221
|
<div
|
|
152
222
|
{...props}
|
|
153
|
-
className={
|
|
223
|
+
className={twJoin(
|
|
154
224
|
className,
|
|
155
225
|
'right-small absolute top-1/2 flex -translate-y-1/2 items-center justify-center'
|
|
156
226
|
)}
|
|
@@ -158,3 +228,36 @@ export function DatePickerRightSlot({
|
|
|
158
228
|
/>
|
|
159
229
|
)
|
|
160
230
|
}
|
|
231
|
+
|
|
232
|
+
export function DatePickerCaption({
|
|
233
|
+
className,
|
|
234
|
+
variant = 'body',
|
|
235
|
+
size = 'sm',
|
|
236
|
+
weight = 'normal',
|
|
237
|
+
...props
|
|
238
|
+
}: ComponentProps<typeof Typography>) {
|
|
239
|
+
const { hasError } = useDatePicker()
|
|
240
|
+
|
|
241
|
+
const caption = tv({
|
|
242
|
+
base: 'text-size-body-sm mt-small-1x font-normal',
|
|
243
|
+
variants: {
|
|
244
|
+
state: {
|
|
245
|
+
error: 'text-danger-label-active',
|
|
246
|
+
idle: 'text-neutral-dark'
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
})
|
|
250
|
+
|
|
251
|
+
return (
|
|
252
|
+
<Typography
|
|
253
|
+
className={caption({
|
|
254
|
+
state: hasError ? 'error' : 'idle',
|
|
255
|
+
className
|
|
256
|
+
})}
|
|
257
|
+
size={size}
|
|
258
|
+
variant={variant}
|
|
259
|
+
weight={weight}
|
|
260
|
+
{...props}
|
|
261
|
+
/>
|
|
262
|
+
)
|
|
263
|
+
}
|
package/src/components/icon.tsx
CHANGED
package/src/components/input.tsx
CHANGED
|
@@ -1,36 +1,53 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { tv, twMerge } from '@xjur-ui/util'
|
|
2
2
|
import type { ComponentProps } from 'react'
|
|
3
|
-
import { createContext } from 'react'
|
|
3
|
+
import { createContext, useContext, useMemo } from 'react'
|
|
4
4
|
import { InputMask, type MaskOptions } from '@react-input/mask'
|
|
5
5
|
import {
|
|
6
6
|
InputNumberFormat,
|
|
7
7
|
type InputNumberFormatProps
|
|
8
8
|
} from '@react-input/number-format'
|
|
9
9
|
import { inputMask, type InputMaskType } from '../resources/input-mask'
|
|
10
|
+
import { Typography } from './typography'
|
|
10
11
|
|
|
11
12
|
export { inputMask, type InputMaskType, type MaskOptions }
|
|
12
13
|
|
|
13
14
|
export type InputProps = {
|
|
14
15
|
variant?: 'outlined' | 'filled'
|
|
16
|
+
disabled?: boolean
|
|
17
|
+
hasError?: boolean
|
|
15
18
|
}
|
|
16
19
|
|
|
17
20
|
const FieldContext = createContext<InputProps>({
|
|
18
|
-
variant: 'filled'
|
|
21
|
+
variant: 'filled',
|
|
22
|
+
disabled: false,
|
|
23
|
+
hasError: false
|
|
19
24
|
})
|
|
20
25
|
|
|
26
|
+
function useInput() {
|
|
27
|
+
const context = useContext(FieldContext)
|
|
28
|
+
if (!context) {
|
|
29
|
+
throw new Error('useInput must be used within a InputRoot')
|
|
30
|
+
}
|
|
31
|
+
return context
|
|
32
|
+
}
|
|
33
|
+
|
|
21
34
|
export function InputRoot({
|
|
22
35
|
className,
|
|
23
36
|
children,
|
|
24
37
|
variant = 'filled',
|
|
38
|
+
disabled = false,
|
|
39
|
+
hasError = false,
|
|
25
40
|
...props
|
|
26
41
|
}: ComponentProps<'div'> & InputProps) {
|
|
42
|
+
const providerValue = useMemo(
|
|
43
|
+
() => ({ variant, disabled, hasError }),
|
|
44
|
+
[variant, disabled, hasError]
|
|
45
|
+
)
|
|
46
|
+
|
|
27
47
|
return (
|
|
28
|
-
<FieldContext.Provider value={
|
|
48
|
+
<FieldContext.Provider value={providerValue}>
|
|
29
49
|
<div
|
|
30
|
-
className={
|
|
31
|
-
'group gap-small relative flex w-full flex-col',
|
|
32
|
-
className
|
|
33
|
-
)}
|
|
50
|
+
className={twMerge('group relative flex w-full flex-col', className)}
|
|
34
51
|
{...props}
|
|
35
52
|
>
|
|
36
53
|
{children}
|
|
@@ -40,31 +57,45 @@ export function InputRoot({
|
|
|
40
57
|
}
|
|
41
58
|
|
|
42
59
|
export function InputContent({ className, ...props }: ComponentProps<'div'>) {
|
|
43
|
-
const
|
|
44
|
-
|
|
45
|
-
'relative h-large-4x rounded-small-1x gap-small py-small_1x-alt px-small flex items-center w-full',
|
|
46
|
-
'focus-within:border-primary-idle focus-within:border',
|
|
60
|
+
const content = tv({
|
|
61
|
+
base: twMerge(
|
|
62
|
+
'border border-transparent relative h-large-4x rounded-small-1x gap-small py-small_1x-alt px-small flex items-center w-full',
|
|
47
63
|
'group-has-[div[data-slot=input-right-action-slot]]:rounded-r-none',
|
|
48
|
-
'group-has-[div[data-slot=input-left-action-slot]]:rounded-l-none'
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
64
|
+
'group-has-[div[data-slot=input-left-action-slot]]:rounded-l-none',
|
|
65
|
+
'focus-within:border-primary-idle focus-within:hover:border-primary-idle',
|
|
66
|
+
'hover:border-border-layer-1'
|
|
67
|
+
),
|
|
68
|
+
variants: {
|
|
69
|
+
variant: {
|
|
70
|
+
filled: 'bg-layer-2-hover',
|
|
71
|
+
outlined:
|
|
72
|
+
'bg-layer-2-idle border-border-layer-2 hover:border-border-layer-3',
|
|
73
|
+
disabled: 'hover:border-transparent border-none bg-layer-2-idle'
|
|
74
|
+
},
|
|
75
|
+
state: {
|
|
76
|
+
idle: '',
|
|
77
|
+
error:
|
|
78
|
+
'focus-within:border-danger-idle hover:border-danger-idle border-danger-idle focus-within:hover:border-danger-idle'
|
|
59
79
|
}
|
|
80
|
+
},
|
|
81
|
+
defaultVariants: {
|
|
82
|
+
variant: 'filled',
|
|
83
|
+
state: 'idle'
|
|
60
84
|
}
|
|
61
|
-
)
|
|
85
|
+
})
|
|
62
86
|
|
|
63
87
|
return (
|
|
64
88
|
<FieldContext.Consumer>
|
|
65
|
-
{({ variant }) => {
|
|
89
|
+
{({ variant, disabled, hasError }) => {
|
|
66
90
|
return (
|
|
67
|
-
<div
|
|
91
|
+
<div
|
|
92
|
+
className={content({
|
|
93
|
+
variant: disabled ? 'disabled' : variant,
|
|
94
|
+
state: hasError ? 'error' : 'idle',
|
|
95
|
+
className
|
|
96
|
+
})}
|
|
97
|
+
{...props}
|
|
98
|
+
/>
|
|
68
99
|
)
|
|
69
100
|
}}
|
|
70
101
|
</FieldContext.Consumer>
|
|
@@ -76,22 +107,24 @@ export function InputLabel({
|
|
|
76
107
|
className,
|
|
77
108
|
children,
|
|
78
109
|
...props
|
|
79
|
-
}: ComponentProps<
|
|
110
|
+
}: ComponentProps<typeof Typography> & { htmlFor: string }) {
|
|
80
111
|
return (
|
|
81
112
|
<FieldContext.Consumer>
|
|
82
|
-
{({ variant }) => {
|
|
113
|
+
{({ variant, disabled, hasError }) => {
|
|
83
114
|
return (
|
|
84
|
-
<
|
|
85
|
-
|
|
86
|
-
|
|
115
|
+
<Typography
|
|
116
|
+
asChild={true}
|
|
117
|
+
className={twMerge(
|
|
118
|
+
'group inline-block max-w-full truncate text-left',
|
|
87
119
|
'ease animate-in left-small right-small pointer-events-none absolute top-1/2 -translate-y-1/2 transition-all duration-250',
|
|
88
120
|
// Filled
|
|
89
|
-
'group-focus-within
|
|
121
|
+
'group-focus-within:!text-primary-idle group-focus-within:data-[has-error=true]:!text-danger-label-active group-focus-within:-top-[3px]',
|
|
90
122
|
'group-focus-within:text-size-label-sm-1x group-focus-within:font-medium',
|
|
91
123
|
'group-has-[input:not(:placeholder-shown)]:-top-[3px]',
|
|
92
124
|
'group-has-[input:not(:placeholder-shown)]:text-size-label-sm-1x',
|
|
93
125
|
'group-has-[input:not(:placeholder-shown)]:font-medium',
|
|
94
|
-
'
|
|
126
|
+
'group-has-[input:not(:placeholder-shown)]:!text-primary-idle',
|
|
127
|
+
'group-has-[input:not(:placeholder-shown)]:!text-danger-label-active',
|
|
95
128
|
// If has left slot
|
|
96
129
|
'group-has-[div[data-slot=input-left-slot]]:left-large-4x',
|
|
97
130
|
'group-has-[div[data-slot=input-left-slot]]:group-focus-within:left-small',
|
|
@@ -103,22 +136,26 @@ export function InputLabel({
|
|
|
103
136
|
// Animate
|
|
104
137
|
'group-focus-within:animate-in',
|
|
105
138
|
'group-has-[input:not(:placeholder-shown)]:animate-out',
|
|
139
|
+
'data-[disabled=true]:hidden',
|
|
106
140
|
className
|
|
107
141
|
)}
|
|
142
|
+
data-disabled={disabled}
|
|
143
|
+
data-has-error={hasError}
|
|
108
144
|
data-variant={variant}
|
|
109
|
-
htmlFor={htmlFor}
|
|
110
145
|
{...props}
|
|
111
146
|
>
|
|
112
|
-
<
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
147
|
+
<label htmlFor={htmlFor}>
|
|
148
|
+
<span
|
|
149
|
+
className={twMerge(
|
|
150
|
+
'rounded-small-1x max-w-full',
|
|
151
|
+
'group-data-[variant=outlined]:group-focus-within:bg-layer-2-idle group-data-[variant=filled]:group-focus-within:bg-layer-2-hover',
|
|
152
|
+
'group-data-[variant=outlined]:bg-layer-2-idle group-data-[variant=filled]:bg-layer-2-hover'
|
|
153
|
+
)}
|
|
154
|
+
>
|
|
155
|
+
{children}
|
|
156
|
+
</span>
|
|
157
|
+
</label>
|
|
158
|
+
</Typography>
|
|
122
159
|
)
|
|
123
160
|
}}
|
|
124
161
|
</FieldContext.Consumer>
|
|
@@ -134,17 +171,19 @@ export function InputText({
|
|
|
134
171
|
maskOptions?: MaskOptions
|
|
135
172
|
maskType?: InputMaskType
|
|
136
173
|
}) {
|
|
174
|
+
const { disabled } = useInput()
|
|
137
175
|
const Component = maskOptions || maskType ? InputMask : 'input'
|
|
138
176
|
|
|
139
177
|
return (
|
|
140
178
|
<Component
|
|
141
179
|
{...props}
|
|
180
|
+
disabled={disabled}
|
|
142
181
|
{...(maskType
|
|
143
182
|
? { ...inputMask(maskType) }
|
|
144
183
|
: maskOptions && { ...maskOptions })}
|
|
145
|
-
className={
|
|
184
|
+
className={twMerge(
|
|
146
185
|
className,
|
|
147
|
-
'peer text-size-body-md text-neutral-dark flex-1
|
|
186
|
+
'peer !text-size-body-md text-neutral-dark flex-1 outline-none',
|
|
148
187
|
'group-has-[div[data-slot=input-left-slot]]:pl-large-1x ml-small-1x'
|
|
149
188
|
)}
|
|
150
189
|
placeholder={props.placeholder || ' '}
|
|
@@ -158,14 +197,16 @@ export function InputNumber({
|
|
|
158
197
|
locales = 'pt-BR',
|
|
159
198
|
...props
|
|
160
199
|
}: InputNumberFormatProps) {
|
|
200
|
+
const { disabled } = useInput()
|
|
161
201
|
return (
|
|
162
202
|
<InputNumberFormat
|
|
163
203
|
{...props}
|
|
164
|
-
className={
|
|
204
|
+
className={twMerge(
|
|
165
205
|
className,
|
|
166
|
-
'peer text-size-body-md text-neutral-dark flex-1 font-medium outline-none',
|
|
206
|
+
'peer !text-size-body-md text-neutral-dark flex-1 font-medium outline-none',
|
|
167
207
|
'group-has-[div[data-slot=input-left-slot]]:pl-large-1x ml-small-1x'
|
|
168
208
|
)}
|
|
209
|
+
disabled={disabled}
|
|
169
210
|
locales={locales}
|
|
170
211
|
placeholder={props.placeholder || ' '}
|
|
171
212
|
/>
|
|
@@ -176,7 +217,7 @@ export function InputLeftSlot({ className, ...props }: ComponentProps<'div'>) {
|
|
|
176
217
|
return (
|
|
177
218
|
<div
|
|
178
219
|
{...props}
|
|
179
|
-
className={
|
|
220
|
+
className={twMerge(
|
|
180
221
|
className,
|
|
181
222
|
'left-small absolute top-1/2 flex -translate-y-1/2 items-center justify-center'
|
|
182
223
|
)}
|
|
@@ -189,7 +230,7 @@ export function InputRightSlot({ className, ...props }: ComponentProps<'div'>) {
|
|
|
189
230
|
return (
|
|
190
231
|
<div
|
|
191
232
|
{...props}
|
|
192
|
-
className={
|
|
233
|
+
className={twMerge(
|
|
193
234
|
className,
|
|
194
235
|
'right-small absolute top-1/2 flex -translate-y-1/2 items-center justify-center'
|
|
195
236
|
)}
|
|
@@ -198,14 +239,35 @@ export function InputRightSlot({ className, ...props }: ComponentProps<'div'>) {
|
|
|
198
239
|
)
|
|
199
240
|
}
|
|
200
241
|
|
|
201
|
-
export function
|
|
242
|
+
export function InputCaption({
|
|
243
|
+
className,
|
|
244
|
+
variant = 'body',
|
|
245
|
+
size = 'sm',
|
|
246
|
+
weight = 'normal',
|
|
247
|
+
...props
|
|
248
|
+
}: ComponentProps<typeof Typography>) {
|
|
249
|
+
const { hasError } = useInput()
|
|
250
|
+
|
|
251
|
+
const caption = tv({
|
|
252
|
+
base: 'text-size-body-sm mt-small-1x font-normal',
|
|
253
|
+
variants: {
|
|
254
|
+
state: {
|
|
255
|
+
error: 'text-danger-label-active',
|
|
256
|
+
idle: 'text-neutral-dark'
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
})
|
|
260
|
+
|
|
202
261
|
return (
|
|
203
|
-
<
|
|
204
|
-
{
|
|
205
|
-
|
|
206
|
-
'text-size-body-sm text-neutral-dark font-normal',
|
|
262
|
+
<Typography
|
|
263
|
+
className={caption({
|
|
264
|
+
state: hasError ? 'error' : 'idle',
|
|
207
265
|
className
|
|
208
|
-
)}
|
|
266
|
+
})}
|
|
267
|
+
size={size}
|
|
268
|
+
variant={variant}
|
|
269
|
+
weight={weight}
|
|
270
|
+
{...props}
|
|
209
271
|
/>
|
|
210
272
|
)
|
|
211
273
|
}
|
|
@@ -214,7 +276,7 @@ export function InputContainer({ className, ...props }: ComponentProps<'div'>) {
|
|
|
214
276
|
return (
|
|
215
277
|
<div
|
|
216
278
|
{...props}
|
|
217
|
-
className={
|
|
279
|
+
className={twMerge(className, 'flex items-center')}
|
|
218
280
|
data-slot="input-content"
|
|
219
281
|
/>
|
|
220
282
|
)
|
|
@@ -227,13 +289,15 @@ export function InputAction({
|
|
|
227
289
|
}: ComponentProps<'div'> & {
|
|
228
290
|
side: 'left' | 'right'
|
|
229
291
|
}) {
|
|
292
|
+
const { disabled } = useInput()
|
|
230
293
|
return (
|
|
231
294
|
<div
|
|
232
295
|
{...props}
|
|
233
|
-
className={
|
|
296
|
+
className={twMerge(
|
|
234
297
|
className,
|
|
235
|
-
'group h-large-4x flex items-center justify-center'
|
|
298
|
+
'group h-large-4x flex items-center justify-center data-[disabled=true]:hidden'
|
|
236
299
|
)}
|
|
300
|
+
data-disabled={disabled}
|
|
237
301
|
data-side={side}
|
|
238
302
|
data-slot={`input-${side}-action-slot`}
|
|
239
303
|
/>
|
|
@@ -247,7 +311,7 @@ export function InputActionButton({
|
|
|
247
311
|
return (
|
|
248
312
|
<div
|
|
249
313
|
{...props}
|
|
250
|
-
className={
|
|
314
|
+
className={twMerge(
|
|
251
315
|
className,
|
|
252
316
|
'h-large-4x w-large-4x bg-layer-2-hover flex cursor-pointer items-center justify-center'
|
|
253
317
|
)}
|
package/src/components/logo.tsx
CHANGED
|
@@ -1,11 +1,25 @@
|
|
|
1
|
-
import { memo } from 'react'
|
|
2
|
-
import { Horizontal, Vertical, Icon } from '../resources/logo'
|
|
1
|
+
import { memo, lazy, Suspense } from 'react'
|
|
3
2
|
|
|
4
3
|
export interface LogoProps {
|
|
5
4
|
mode?: 'horizontal' | 'vertical' | 'icon'
|
|
6
5
|
variant?: 'colorful' | 'orange' | 'purple' | 'white' | 'gray'
|
|
7
6
|
}
|
|
8
7
|
|
|
8
|
+
// Lazy load logo components to reduce initial bundle size
|
|
9
|
+
const LazyLogos = lazy(() => import('../resources/logo'))
|
|
10
|
+
|
|
11
|
+
function LogoFallback({ mode }: { mode?: string }) {
|
|
12
|
+
const dimensions =
|
|
13
|
+
mode === 'icon' ? { width: 24, height: 24 } : { width: 95, height: 26 }
|
|
14
|
+
return (
|
|
15
|
+
<div
|
|
16
|
+
aria-label="Loading logo"
|
|
17
|
+
className="animate-pulse rounded bg-gray-200"
|
|
18
|
+
style={dimensions}
|
|
19
|
+
/>
|
|
20
|
+
)
|
|
21
|
+
}
|
|
22
|
+
|
|
9
23
|
export const Logo = memo(
|
|
10
24
|
({ mode = 'horizontal', variant = 'colorful' }: LogoProps) => {
|
|
11
25
|
const colorToHex = {
|
|
@@ -15,24 +29,15 @@ export const Logo = memo(
|
|
|
15
29
|
gray: '#6B7280'
|
|
16
30
|
}
|
|
17
31
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
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
|
-
}
|
|
32
|
+
return (
|
|
33
|
+
<Suspense fallback={<LogoFallback mode={mode} />}>
|
|
34
|
+
<LazyLogos
|
|
35
|
+
color={variant !== 'colorful' ? colorToHex[variant] : undefined}
|
|
36
|
+
mode={mode}
|
|
37
|
+
variant={variant}
|
|
38
|
+
/>
|
|
39
|
+
</Suspense>
|
|
40
|
+
)
|
|
36
41
|
}
|
|
37
42
|
)
|
|
38
43
|
|
|
@@ -6,12 +6,13 @@ import {
|
|
|
6
6
|
useCurrentEditor as useRichTextEditor,
|
|
7
7
|
useEditorState as useRichTextEditorState,
|
|
8
8
|
useEditor,
|
|
9
|
-
type EditorOptions
|
|
10
|
-
Extension
|
|
9
|
+
type EditorOptions
|
|
11
10
|
} from '@tiptap/react'
|
|
11
|
+
import type { Extension } from '@tiptap/core'
|
|
12
12
|
import { StarterKit } from '@tiptap/starter-kit'
|
|
13
13
|
import { Heading, type Level } from '@tiptap/extension-heading'
|
|
14
|
-
|
|
14
|
+
// Import specific extension instead of full extensions bundle
|
|
15
|
+
import { Placeholder } from '@tiptap/extension-placeholder'
|
|
15
16
|
import { useOS } from '../hooks'
|
|
16
17
|
import { Icon, type IconType } from './icon'
|
|
17
18
|
import { Button, type ButtonProps } from './button'
|