@xjur-ui/react 1.0.0 → 1.0.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.
Files changed (115) hide show
  1. package/.turbo/turbo-build.log +61 -57
  2. package/CHANGELOG.md +11 -0
  3. package/dist/components/avatar.d.ts +11 -0
  4. package/dist/components/avatar.js +58 -0
  5. package/dist/components/{ui/button.d.ts → button.d.ts} +2 -2
  6. package/dist/components/{ui/button.js → button.js} +9 -6
  7. package/dist/components/calendar.d.ts +11 -0
  8. package/dist/components/calendar.js +751 -0
  9. package/dist/components/checkbox.d.ts +8 -0
  10. package/dist/components/{ui/input/root.js → checkbox.js} +69 -79
  11. package/dist/components/chip.d.ts +24 -0
  12. package/dist/components/chip.js +255 -0
  13. package/dist/components/collapsible.d.ts +8 -0
  14. package/dist/components/collapsible.js +41 -0
  15. package/dist/components/date-picker.d.ts +20 -0
  16. package/dist/components/date-picker.js +230 -0
  17. package/dist/components/divider.d.ts +7 -0
  18. package/dist/components/divider.js +28 -0
  19. package/dist/components/dropdown-menu.d.ts +22 -0
  20. package/dist/components/dropdown-menu.js +294 -0
  21. package/dist/components/{resources/icons.d.ts → icon.d.ts} +11 -2
  22. package/dist/components/{ui/icon.js → icon.js} +18 -5
  23. package/dist/components/input.d.ts +32 -0
  24. package/dist/components/input.js +299 -0
  25. package/dist/components/list.d.ts +25 -0
  26. package/dist/components/{ui/input/content.js → list.js} +83 -87
  27. package/dist/components/{ui/logo.d.ts → logo.d.ts} +2 -2
  28. package/dist/components/{ui/logo.js → logo.js} +5 -5
  29. package/dist/components/{ui/otp-input.js → otp-input.js} +1 -1
  30. package/dist/components/radio.d.ts +10 -0
  31. package/dist/components/{ui/input/label.js → radio.js} +68 -77
  32. package/dist/components/search-input.d.ts +17 -0
  33. package/dist/components/search-input.js +274 -0
  34. package/dist/components/select.d.ts +33 -0
  35. package/dist/components/select.js +548 -0
  36. package/dist/components/sheet.d.ts +19 -0
  37. package/dist/components/sheet.js +251 -0
  38. package/dist/components/switch.d.ts +7 -0
  39. package/dist/components/switch.js +36 -0
  40. package/dist/components/tabs.d.ts +11 -0
  41. package/dist/components/tabs.js +54 -0
  42. package/dist/components/tag.d.ts +18 -0
  43. package/dist/components/tag.js +189 -0
  44. package/dist/components/{ui/typography.d.ts → typography.d.ts} +3 -3
  45. package/dist/components/{ui/typography.js → typography.js} +1 -1
  46. package/dist/index.css +1156 -62
  47. package/dist/index.d.ts +2 -17
  48. package/dist/index.js +0 -788
  49. package/eslint.config.js +8 -1
  50. package/package.json +40 -10
  51. package/src/components/avatar.tsx +53 -0
  52. package/src/components/{ui/button.tsx → button.tsx} +7 -5
  53. package/src/components/calendar.tsx +123 -0
  54. package/src/components/checkbox.tsx +57 -0
  55. package/src/components/chip.tsx +109 -0
  56. package/src/components/collapsible.tsx +35 -0
  57. package/src/components/date-picker.tsx +154 -0
  58. package/src/components/divider.tsx +23 -0
  59. package/src/components/dropdown-menu.tsx +101 -0
  60. package/src/components/{ui/icon.tsx → icon.tsx} +1 -1
  61. package/src/components/input.tsx +241 -0
  62. package/src/components/list.tsx +111 -0
  63. package/src/components/radio.tsx +74 -0
  64. package/src/components/search-input.tsx +112 -0
  65. package/src/components/select.tsx +234 -0
  66. package/src/components/sheet.tsx +141 -0
  67. package/src/components/switch.tsx +31 -0
  68. package/src/components/tabs.tsx +53 -0
  69. package/src/components/tag.tsx +91 -0
  70. package/src/index.css +4 -1
  71. package/src/index.ts +0 -1
  72. package/src/{components/resources → resources}/icons.ts +14 -1
  73. package/src/resources/input-mask.ts +91 -0
  74. package/dist/components/resources/icons.js +0 -133
  75. package/dist/components/resources/logo/horizontal.d.ts +0 -12
  76. package/dist/components/resources/logo/horizontal.js +0 -107
  77. package/dist/components/resources/logo/icon.d.ts +0 -12
  78. package/dist/components/resources/logo/icon.js +0 -79
  79. package/dist/components/resources/logo/index.d.ts +0 -4
  80. package/dist/components/resources/logo/index.js +0 -291
  81. package/dist/components/resources/logo/vertical.d.ts +0 -12
  82. package/dist/components/resources/logo/vertical.js +0 -107
  83. package/dist/components/ui/accordion.d.ts +0 -5
  84. package/dist/components/ui/accordion.js +0 -8
  85. package/dist/components/ui/icon.d.ts +0 -12
  86. package/dist/components/ui/index.d.ts +0 -17
  87. package/dist/components/ui/index.js +0 -788
  88. package/dist/components/ui/input/content.d.ts +0 -9
  89. package/dist/components/ui/input/index.d.ts +0 -12
  90. package/dist/components/ui/input/index.js +0 -335
  91. package/dist/components/ui/input/label.d.ts +0 -12
  92. package/dist/components/ui/input/message.d.ts +0 -10
  93. package/dist/components/ui/input/message.js +0 -128
  94. package/dist/components/ui/input/root.d.ts +0 -18
  95. package/dist/components/ui/input/slot.d.ts +0 -10
  96. package/dist/components/ui/input/slot.js +0 -20
  97. package/dist/components/ui/input/text.d.ts +0 -10
  98. package/dist/components/ui/input/text.js +0 -195
  99. package/src/components/ui/accordion.tsx +0 -3
  100. package/src/components/ui/index.ts +0 -13
  101. package/src/components/ui/input/content.tsx +0 -59
  102. package/src/components/ui/input/index.ts +0 -6
  103. package/src/components/ui/input/label.tsx +0 -41
  104. package/src/components/ui/input/message.tsx +0 -37
  105. package/src/components/ui/input/root.tsx +0 -57
  106. package/src/components/ui/input/slot.tsx +0 -21
  107. package/src/components/ui/input/text.tsx +0 -69
  108. /package/dist/components/{ui/otp-input.d.ts → otp-input.d.ts} +0 -0
  109. /package/src/components/{ui/logo.tsx → logo.tsx} +0 -0
  110. /package/src/components/{ui/otp-input.tsx → otp-input.tsx} +0 -0
  111. /package/src/components/{ui/typography.tsx → typography.tsx} +0 -0
  112. /package/src/{components/resources → resources}/logo/horizontal.tsx +0 -0
  113. /package/src/{components/resources → resources}/logo/icon.tsx +0 -0
  114. /package/src/{components/resources → resources}/logo/index.ts +0 -0
  115. /package/src/{components/resources → resources}/logo/vertical.tsx +0 -0
@@ -0,0 +1,101 @@
1
+ import * as React from 'react'
2
+ import * as DropdownMenuPrimitive from '@radix-ui/react-dropdown-menu'
3
+ import { cx } from '@xjur-ui/util'
4
+ import {
5
+ ListContent,
6
+ ListHeader,
7
+ ListHeaderTitle,
8
+ ListItem,
9
+ ListRoot
10
+ } from './list'
11
+ import { Typography } from './typography'
12
+ import { Divider } from './divider'
13
+
14
+ export function DropdownMenuRoot({
15
+ ...props
16
+ }: React.ComponentProps<typeof DropdownMenuPrimitive.Root>) {
17
+ return <DropdownMenuPrimitive.Root data-slot="dropdown-menu" {...props} />
18
+ }
19
+
20
+ export function DropdownMenuPortal({
21
+ ...props
22
+ }: React.ComponentProps<typeof DropdownMenuPrimitive.Portal>) {
23
+ return (
24
+ <DropdownMenuPrimitive.Portal data-slot="dropdown-menu-portal" {...props} />
25
+ )
26
+ }
27
+
28
+ export function DropdownMenuTrigger({
29
+ ...props
30
+ }: React.ComponentProps<typeof DropdownMenuPrimitive.Trigger>) {
31
+ return (
32
+ <DropdownMenuPrimitive.Trigger
33
+ data-slot="dropdown-menu-trigger"
34
+ {...props}
35
+ />
36
+ )
37
+ }
38
+
39
+ export function DropdownMenuContent({
40
+ className,
41
+ sideOffset = 4,
42
+ align = 'start',
43
+ side = 'bottom',
44
+ children,
45
+ ...props
46
+ }: React.ComponentProps<typeof DropdownMenuPrimitive.Content>) {
47
+ return (
48
+ <DropdownMenuPrimitive.Portal>
49
+ <DropdownMenuPrimitive.Content
50
+ align={align}
51
+ className={cx(
52
+ 'group z-10 max-h-[var(--radix-popover-content-available-height)] max-w-[var(--radix-popover-trigger-width)] min-w-[240px]',
53
+ className
54
+ )}
55
+ data-slot="dropdown-menu-content"
56
+ side={side}
57
+ sideOffset={sideOffset}
58
+ {...props}
59
+ >
60
+ <ListRoot>{children}</ListRoot>
61
+ </DropdownMenuPrimitive.Content>
62
+ </DropdownMenuPrimitive.Portal>
63
+ )
64
+ }
65
+
66
+ export function DropdownMenuList({
67
+ ...props
68
+ }: React.ComponentProps<typeof ListContent>) {
69
+ return <ListContent {...props} />
70
+ }
71
+
72
+ export function DropdownMenuHeader({
73
+ ...props
74
+ }: React.ComponentProps<typeof ListHeader>) {
75
+ return <ListHeader {...props} />
76
+ }
77
+
78
+ export function DropdownMenuHeaderTitle({
79
+ ...props
80
+ }: React.ComponentProps<typeof ListHeaderTitle>) {
81
+ return <ListHeaderTitle {...props} />
82
+ }
83
+
84
+ export function DropdownMenuItem({
85
+ className,
86
+ ...props
87
+ }: React.ComponentProps<typeof ListItem>) {
88
+ return <ListItem className={cx(className, 'cursor-pointer')} {...props} />
89
+ }
90
+
91
+ export function DropdownMenuItemText({
92
+ ...props
93
+ }: React.ComponentProps<typeof Typography>) {
94
+ return <Typography {...props} />
95
+ }
96
+
97
+ export function DropdownMenuItemDivider({
98
+ ...props
99
+ }: React.ComponentProps<typeof Divider>) {
100
+ return <Divider {...props} />
101
+ }
@@ -13,7 +13,7 @@ export function Icon({ className, filled = false, name, ...props }: IconProps) {
13
13
  {...props}
14
14
  className={cx(
15
15
  'material-symbols-outlined',
16
- 'text-size-body-lg text-icon-neutral-3',
16
+ 'text-size-body-lg',
17
17
  className
18
18
  )}
19
19
  style={{
@@ -0,0 +1,241 @@
1
+ import { cva, cx } from '@xjur-ui/util'
2
+ import type { ComponentProps } from 'react'
3
+ import { createContext } from 'react'
4
+ import { InputMask, type MaskOptions } from '@react-input/mask'
5
+ import {
6
+ InputNumberFormat,
7
+ type InputNumberFormatProps
8
+ } from '@react-input/number-format'
9
+ import { inputMask, type InputMaskType } from '../resources/input-mask'
10
+
11
+ export { inputMask, type InputMaskType, type MaskOptions }
12
+
13
+ export type InputProps = {
14
+ variant?: 'outlined' | 'filled'
15
+ }
16
+
17
+ const FieldContext = createContext<InputProps>({
18
+ variant: 'filled'
19
+ })
20
+
21
+ export function InputRoot({
22
+ className,
23
+ children,
24
+ variant = 'filled',
25
+ ...props
26
+ }: ComponentProps<'div'> & InputProps) {
27
+ return (
28
+ <FieldContext.Provider value={{ variant }}>
29
+ <div
30
+ className={cx(
31
+ 'group gap-small relative flex w-full flex-col',
32
+ className
33
+ )}
34
+ {...props}
35
+ >
36
+ {children}
37
+ </div>
38
+ </FieldContext.Provider>
39
+ )
40
+ }
41
+
42
+ export function InputContent({ className, ...props }: ComponentProps<'div'>) {
43
+ const variants = cva(
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:shadow-focus-primary focus-within:border',
47
+ '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
+ variants: {
52
+ variant: {
53
+ default: '',
54
+ outlined:
55
+ 'bg-layer-2-idle border-border-layer-2 border hover:border-border-layer-3 has-[input:not(:placeholder-shown)]:border-primary-idle',
56
+ filled:
57
+ 'bg-layer-2-hover group-hover:border-border-layer-1 group-hover:border-1'
58
+ }
59
+ }
60
+ }
61
+ )
62
+
63
+ return (
64
+ <FieldContext.Consumer>
65
+ {({ variant }) => {
66
+ return (
67
+ <div className={cx(className, variants({ variant }))} {...props} />
68
+ )
69
+ }}
70
+ </FieldContext.Consumer>
71
+ )
72
+ }
73
+
74
+ export function InputLabel({
75
+ htmlFor,
76
+ className,
77
+ ...props
78
+ }: ComponentProps<'label'> & { htmlFor: string }) {
79
+ return (
80
+ <FieldContext.Consumer>
81
+ {({ variant }) => {
82
+ return (
83
+ <label
84
+ className={cx(
85
+ 'rounded-small-1x text-size-body-md text-neutral-dark data-[variant=outlined]:bg-layer-2-idle bg-layer-2-hover w-fit font-normal',
86
+ 'ease animate-in pointer-events-none absolute top-1/2 left-auto -translate-y-1/2 transition-all duration-250',
87
+ // Filled
88
+ 'group-focus-within:text-primary-idle group-focus-within:bg-layer-2-hover data-[variant=outlined]:group-focus-within:bg-layer-2-idle group-focus-within:-top-[3px]',
89
+ 'group-focus-within:text-size-label-sm-1x group-focus-within:font-medium',
90
+ 'group-has-[input:not(:placeholder-shown)]:-top-[3px]',
91
+ 'group-has-[input:not(:placeholder-shown)]:text-size-label-sm-1x',
92
+ 'group-has-[input:not(:placeholder-shown)]:font-medium',
93
+ 'data-[variant=outlined]:group-has-[input:not(:placeholder-shown)]:text-primary-idle',
94
+ // If has left slot
95
+ 'group-has-[div[data-slot=input-left-slot]]:left-large-4x',
96
+ 'group-has-[div[data-slot=input-left-slot]]:group-focus-within:left-auto',
97
+ 'group-has-[div[data-slot=input-left-slot]]:group-has-[input:not(:placeholder-shown)]:left-auto',
98
+ // Animate
99
+ 'group-focus-within:animate-in',
100
+ 'group-has-[input:not(:placeholder-shown)]:animate-out',
101
+ className
102
+ )}
103
+ data-variant={variant}
104
+ htmlFor={htmlFor}
105
+ {...props}
106
+ />
107
+ )
108
+ }}
109
+ </FieldContext.Consumer>
110
+ )
111
+ }
112
+
113
+ export function InputText({
114
+ className,
115
+ maskOptions,
116
+ maskType,
117
+ ...props
118
+ }: ComponentProps<'input'> & {
119
+ maskOptions?: MaskOptions
120
+ maskType?: InputMaskType
121
+ }) {
122
+ const Component = maskOptions || maskType ? InputMask : 'input'
123
+
124
+ return (
125
+ <Component
126
+ {...props}
127
+ {...(maskType
128
+ ? { ...inputMask(maskType) }
129
+ : maskOptions && { ...maskOptions })}
130
+ className={cx(
131
+ className,
132
+ 'peer text-size-body-md text-neutral-dark flex-1 font-medium outline-none',
133
+ 'group-has-[div[data-slot=input-left-slot]]:pl-large-1x ml-small-1x'
134
+ )}
135
+ placeholder={props.placeholder || ' '}
136
+ {...(maskOptions && { ...maskOptions })}
137
+ />
138
+ )
139
+ }
140
+
141
+ export function InputNumber({
142
+ className,
143
+ locales = 'pt-BR',
144
+ ...props
145
+ }: InputNumberFormatProps) {
146
+ return (
147
+ <InputNumberFormat
148
+ {...props}
149
+ className={cx(
150
+ className,
151
+ 'peer text-size-body-md text-neutral-dark flex-1 font-medium outline-none',
152
+ 'group-has-[div[data-slot=input-left-slot]]:pl-large-1x ml-small-1x'
153
+ )}
154
+ locales={locales}
155
+ placeholder={props.placeholder || ' '}
156
+ />
157
+ )
158
+ }
159
+
160
+ export function InputLeftSlot({ className, ...props }: ComponentProps<'div'>) {
161
+ return (
162
+ <div
163
+ {...props}
164
+ className={cx(
165
+ className,
166
+ 'left-small absolute top-1/2 flex -translate-y-1/2 items-center justify-center'
167
+ )}
168
+ data-slot="input-left-slot"
169
+ />
170
+ )
171
+ }
172
+
173
+ export function InputRightSlot({ className, ...props }: ComponentProps<'div'>) {
174
+ return (
175
+ <div
176
+ {...props}
177
+ className={cx(
178
+ className,
179
+ 'right-small absolute top-1/2 flex -translate-y-1/2 items-center justify-center'
180
+ )}
181
+ data-slot="input-right-slot"
182
+ />
183
+ )
184
+ }
185
+
186
+ export function InputMessage({ className, ...props }: ComponentProps<'p'>) {
187
+ return (
188
+ <p
189
+ {...props}
190
+ className={cx(
191
+ 'text-size-body-sm text-neutral-dark font-normal',
192
+ className
193
+ )}
194
+ />
195
+ )
196
+ }
197
+
198
+ export function InputContainer({ className, ...props }: ComponentProps<'div'>) {
199
+ return (
200
+ <div
201
+ {...props}
202
+ className={cx(className, 'flex items-center')}
203
+ data-slot="input-content"
204
+ />
205
+ )
206
+ }
207
+
208
+ export function InputAction({
209
+ className,
210
+ side,
211
+ ...props
212
+ }: ComponentProps<'div'> & {
213
+ side: 'left' | 'right'
214
+ }) {
215
+ return (
216
+ <div
217
+ {...props}
218
+ className={cx(
219
+ className,
220
+ 'group h-large-4x flex items-center justify-center'
221
+ )}
222
+ data-side={side}
223
+ data-slot={`input-${side}-action-slot`}
224
+ />
225
+ )
226
+ }
227
+
228
+ export function InputActionButton({
229
+ className,
230
+ ...props
231
+ }: ComponentProps<'div'>) {
232
+ return (
233
+ <div
234
+ {...props}
235
+ className={cx(
236
+ className,
237
+ 'h-large-4x w-large-4x bg-layer-2-hover flex cursor-pointer items-center justify-center'
238
+ )}
239
+ />
240
+ )
241
+ }
@@ -0,0 +1,111 @@
1
+ import { Slot } from '@radix-ui/react-slot'
2
+ import { cx, cva, type ClassVariantProps } from '@xjur-ui/util'
3
+ import type { ComponentProps } from 'react'
4
+ import { type TypographyProps, Typography } from './typography'
5
+
6
+ export function ListRoot({
7
+ className,
8
+ asChild,
9
+ ...props
10
+ }: ComponentProps<'div'> & {
11
+ asChild?: boolean
12
+ }) {
13
+ const Comp = asChild ? Slot : 'div'
14
+
15
+ return (
16
+ <Comp
17
+ {...props}
18
+ className={cx(
19
+ className,
20
+ 'rounded-small scrollbar-hide bg-layer-2-idle border-border-layer-2 shadow-elevation-3 z-10 max-h-[400px] list-none overflow-y-auto border'
21
+ )}
22
+ />
23
+ )
24
+ }
25
+
26
+ export function ListHeader({
27
+ className,
28
+ asChild,
29
+ ...props
30
+ }: ComponentProps<'div'> & {
31
+ asChild?: boolean
32
+ }) {
33
+ const Comp = asChild ? Slot : 'div'
34
+ return <Comp {...props} className={cx(className, 'px-small pt-small-1x')} />
35
+ }
36
+
37
+ export function ListHeaderTitle({
38
+ variant = 'label',
39
+ size = 'sm',
40
+ weight = 'medium',
41
+ className,
42
+ ...props
43
+ }: TypographyProps) {
44
+ return (
45
+ <Typography
46
+ className={cx(className, 'text-neutral-placeholder')}
47
+ size={size}
48
+ variant={variant}
49
+ weight={weight}
50
+ {...props}
51
+ />
52
+ )
53
+ }
54
+
55
+ export function ListContent({
56
+ className,
57
+ asChild,
58
+ ...props
59
+ }: ComponentProps<'ul'> & {
60
+ asChild?: boolean
61
+ }) {
62
+ const Comp = asChild ? Slot : 'ul'
63
+
64
+ return (
65
+ <Comp
66
+ {...props}
67
+ className={cx('gap-small-1x p-small flex flex-col', className)}
68
+ />
69
+ )
70
+ }
71
+
72
+ const variants = cva(
73
+ [
74
+ 'py-medium px-small flex items-center gap-small rounded-small-1x',
75
+ 'bg-layer-2-idle text-neutral-dark',
76
+ 'hover:bg-layer-2-hover transition-colors duration-100 ease-out',
77
+ 'active:bg-layer-2-pressed'
78
+ ],
79
+ {
80
+ variants: {
81
+ size: {
82
+ md: 'h-large-4x',
83
+ lg: 'h-large-7x'
84
+ },
85
+ isActive: {
86
+ true: 'bg-primary-alt-active text-primary-label-active hover:bg-primary-alt-hover active:bg-primary-alt-pressed'
87
+ }
88
+ },
89
+ defaultVariants: {
90
+ size: 'md',
91
+ isActive: false
92
+ }
93
+ }
94
+ )
95
+
96
+ export function ListItem({
97
+ className,
98
+ size,
99
+ isActive,
100
+ asChild,
101
+ ...props
102
+ }: ComponentProps<'li'> &
103
+ ClassVariantProps<typeof variants> & {
104
+ asChild?: boolean
105
+ }) {
106
+ const Comp = asChild ? Slot : 'li'
107
+
108
+ return (
109
+ <Comp {...props} className={cx(variants({ size, isActive }), className)} />
110
+ )
111
+ }
@@ -0,0 +1,74 @@
1
+ import * as React from 'react'
2
+ import * as RadioGroupPrimitive from '@radix-ui/react-radio-group'
3
+ import { cx } from '@xjur-ui/util'
4
+ import { Typography } from './typography'
5
+
6
+ export function RadioGroup({
7
+ className,
8
+ orientation = 'vertical',
9
+ ...props
10
+ }: React.ComponentProps<typeof RadioGroupPrimitive.Root>) {
11
+ return (
12
+ <RadioGroupPrimitive.Root
13
+ className={cx(
14
+ 'gap-small flex data-[orientation=horizontal]:flex-row data-[orientation=vertical]:flex-col',
15
+ className
16
+ )}
17
+ data-orientation={orientation}
18
+ data-slot="radio-group"
19
+ {...props}
20
+ />
21
+ )
22
+ }
23
+
24
+ export function RadioItem({
25
+ className,
26
+ id,
27
+ label,
28
+ disabled = false,
29
+ ...props
30
+ }: React.ComponentProps<typeof RadioGroupPrimitive.Item> & {
31
+ label?: string
32
+ }) {
33
+ return (
34
+ <div className="gap-small flex items-center">
35
+ <RadioGroupPrimitive.Item
36
+ className={cx(
37
+ // layout
38
+ 'size-large-alt rounded-circle inline-flex items-center justify-center transition-[border-color,box-shadow,background-color] duration-200 outline-none',
39
+ // base
40
+ 'border-border-layer-2 bg-layer-2-idle cursor-pointer border-2',
41
+ // hover/focus (desmarcado)
42
+ 'hover:border-primary-idle focus:border-primary-idle focus:shadow-focus-primary',
43
+ // estado checked
44
+ 'data-[state=checked]:bg-primary-active data-[state=checked]:border-primary-active',
45
+ // hover quando estiver checked (opcional)
46
+ 'data-[state=checked]:hover:border-primary-idle',
47
+ // disabled
48
+ 'disabled:hover:border-border-layer-2 disabled:cursor-not-allowed disabled:opacity-[38%]',
49
+ className
50
+ )}
51
+ data-slot="radio-group-item"
52
+ disabled={disabled}
53
+ id={id}
54
+ {...props}
55
+ >
56
+ <RadioGroupPrimitive.Indicator
57
+ className="relative flex items-center justify-center"
58
+ data-slot="radio-group-indicator"
59
+ />
60
+ </RadioGroupPrimitive.Item>
61
+
62
+ {!!label && (
63
+ <Typography
64
+ asChild={true}
65
+ className="text-size-body-sm data-[disabled=true]:opacity-38"
66
+ data-disabled={disabled}
67
+ weight="medium"
68
+ >
69
+ <label htmlFor={id}>{label}</label>
70
+ </Typography>
71
+ )}
72
+ </div>
73
+ )
74
+ }
@@ -0,0 +1,112 @@
1
+ import { cva, cx } from '@xjur-ui/util'
2
+ import { createContext, type ComponentProps } from 'react'
3
+ import { Typography } from './typography'
4
+ import { Button, type ButtonProps } from './button'
5
+
6
+ export type SearchInputProps = {
7
+ variant?: 'outlined' | 'line' | 'action'
8
+ }
9
+
10
+ const SearchInputRootContext = createContext<SearchInputProps>({
11
+ variant: 'outlined'
12
+ })
13
+
14
+ export function SearchInputRoot({
15
+ className,
16
+ variant = 'outlined',
17
+ ...props
18
+ }: ComponentProps<'div'> & SearchInputProps) {
19
+ return (
20
+ <SearchInputRootContext.Provider value={{ variant }}>
21
+ <div className={cx(className, 'relative flex w-full')} {...props} />
22
+ </SearchInputRootContext.Provider>
23
+ )
24
+ }
25
+
26
+ export function SearchInputContent({
27
+ className,
28
+ ...props
29
+ }: ComponentProps<'div'>) {
30
+ const contentVarians = cva(
31
+ [
32
+ 'gap-small py-small_1x-alt px-small flex items-center w-full',
33
+ 'h-large-4x rounded-circle',
34
+ 'border-border-layer-2 placeholder:placeholder-neutral-placeholder text-size-body-md text-neutral-dark border font-normal',
35
+ 'group-hover:border-border-layer-3 transition-colors duration-200',
36
+ 'disabled:opacity-60',
37
+ 'focus-within:border-primary-idle'
38
+ ],
39
+ {
40
+ variants: {
41
+ variant: {
42
+ outlined:
43
+ 'rounded-circle focus-within:border-primary-idle focus-within:shadow-focus-primary',
44
+ line: 'rounded-none border-t-0 border-b-1 border-x-0',
45
+ action: 'rounded-tr-none rounded-br-none border-r-0'
46
+ }
47
+ }
48
+ }
49
+ )
50
+
51
+ return (
52
+ <SearchInputRootContext.Consumer>
53
+ {({ variant }) => (
54
+ <div
55
+ className={cx(className, contentVarians({ variant }))}
56
+ data-variant={variant}
57
+ {...props}
58
+ />
59
+ )}
60
+ </SearchInputRootContext.Consumer>
61
+ )
62
+ }
63
+
64
+ export function SearchInputLabel({
65
+ htmlFor,
66
+ ...props
67
+ }: ComponentProps<'label'>) {
68
+ return (
69
+ <Typography
70
+ asChild={true}
71
+ className={cx('absolute -top-[22px] left-0')}
72
+ size="sm"
73
+ variant="label"
74
+ weight="medium"
75
+ >
76
+ <label htmlFor={htmlFor} {...props} />
77
+ </Typography>
78
+ )
79
+ }
80
+
81
+ export function SearchInputText({
82
+ className,
83
+ ...props
84
+ }: ComponentProps<'input'>) {
85
+ return <input className={cx(className, 'flex-1 outline-none')} {...props} />
86
+ }
87
+
88
+ export function SearchInputSlot(props: ComponentProps<'div'>) {
89
+ return <div {...props} data-slot="search-input-slot" />
90
+ }
91
+
92
+ export function SearchInputAction({
93
+ className,
94
+ appearance = 'ghost',
95
+ variant = 'outlined',
96
+ ...props
97
+ }: ButtonProps) {
98
+ return (
99
+ <Button
100
+ {...props}
101
+ appearance={appearance}
102
+ className={cx(
103
+ className,
104
+ 'cursor-pointer',
105
+ 'h-large-4x rounded-tr-circle rounded-br-circle px-small py-small_1x-alt flex items-center justify-center rounded-none',
106
+ 'text-size-body-md text-neutral-dark gap-small-1x'
107
+ )}
108
+ data-slot="search-input-action"
109
+ variant={variant}
110
+ />
111
+ )
112
+ }