@xjur-ui/react 2.1.1 → 2.2.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/CHANGELOG.md +12 -0
- package/dist/components/steps/index.js +1 -1
- package/package.json +7 -4
- package/.turbo/turbo-build.log +0 -419
- package/eslint.config.js +0 -10
- package/postcss.config.js +0 -5
- package/prettier.config.js +0 -7
- package/src/components/avatar-group.tsx +0 -76
- package/src/components/avatar.tsx +0 -54
- package/src/components/badge.tsx +0 -40
- package/src/components/breadcrumb.tsx +0 -119
- package/src/components/chip.tsx +0 -117
- package/src/components/collapsible.tsx +0 -35
- package/src/components/controls/button.tsx +0 -107
- package/src/components/controls/calendar.tsx +0 -124
- package/src/components/controls/checkbox.tsx +0 -57
- package/src/components/controls/context/field.context.ts +0 -27
- package/src/components/controls/date-picker.tsx +0 -199
- package/src/components/controls/floating-label.tsx +0 -60
- package/src/components/controls/input.tsx +0 -237
- package/src/components/controls/otp-input.tsx +0 -45
- package/src/components/controls/radio.tsx +0 -74
- package/src/components/controls/rich-editor.tsx +0 -372
- package/src/components/controls/search-input.tsx +0 -154
- package/src/components/controls/search-selector.tsx +0 -98
- package/src/components/controls/select.tsx +0 -274
- package/src/components/controls/switch.tsx +0 -31
- package/src/components/custom/pessoa/index.ts +0 -9
- package/src/components/custom/pessoa/pessoa-add-button.tsx +0 -35
- package/src/components/custom/pessoa/pessoa-body.tsx +0 -22
- package/src/components/custom/pessoa/pessoa-close-button.tsx +0 -13
- package/src/components/custom/pessoa/pessoa-content.tsx +0 -25
- package/src/components/custom/pessoa/pessoa-footer.tsx +0 -15
- package/src/components/custom/pessoa/pessoa-header.tsx +0 -35
- package/src/components/custom/pessoa/pessoa-trigger.tsx +0 -25
- package/src/components/custom/pessoa/pessoa.context.tsx +0 -73
- package/src/components/custom/pessoa/pessoa.tsx +0 -35
- package/src/components/dialog.tsx +0 -242
- package/src/components/divider.tsx +0 -24
- package/src/components/drag-and-drop/drag-handle.tsx +0 -46
- package/src/components/drag-and-drop/drag-list-item.tsx +0 -91
- package/src/components/drag-and-drop/drag-list.tsx +0 -47
- package/src/components/drag-and-drop/drag-root.tsx +0 -30
- package/src/components/drag-and-drop/index.ts +0 -39
- package/src/components/drag-and-drop/types/drag-item.ts +0 -7
- package/src/components/dropdown-menu.tsx +0 -101
- package/src/components/full-calendar/calendar-add-event.tsx +0 -15
- package/src/components/full-calendar/calendar-body.tsx +0 -12
- package/src/components/full-calendar/calendar-cell.tsx +0 -120
- package/src/components/full-calendar/calendar-day-view.tsx +0 -76
- package/src/components/full-calendar/calendar-event.tsx +0 -178
- package/src/components/full-calendar/calendar-header.tsx +0 -14
- package/src/components/full-calendar/calendar-month-view.tsx +0 -69
- package/src/components/full-calendar/calendar-more-events-dropdown.tsx +0 -39
- package/src/components/full-calendar/calendar-navigator.tsx +0 -86
- package/src/components/full-calendar/calendar-root.tsx +0 -165
- package/src/components/full-calendar/calendar-today-button.tsx +0 -21
- package/src/components/full-calendar/calendar-toggle-view.tsx +0 -61
- package/src/components/full-calendar/calendar-view-renderer.tsx +0 -19
- package/src/components/full-calendar/calendar-week-day.tsx +0 -49
- package/src/components/full-calendar/calendar-week-view.tsx +0 -88
- package/src/components/full-calendar/helpers/calendar.ts +0 -158
- package/src/components/full-calendar/index.ts +0 -16
- package/src/components/full-calendar/types/calendar-cell.ts +0 -4
- package/src/components/full-calendar/types/calendar-event.ts +0 -7
- package/src/components/full-calendar/types/calendar-view.ts +0 -1
- package/src/components/full-calendar/types/calendar-week-hour.ts +0 -4
- package/src/components/horizontal-scroll.tsx +0 -159
- package/src/components/icon.tsx +0 -29
- package/src/components/list.tsx +0 -111
- package/src/components/logo.tsx +0 -44
- package/src/components/selection-bar.tsx +0 -273
- package/src/components/sheet.tsx +0 -150
- package/src/components/skeleton.tsx +0 -12
- package/src/components/status.tsx +0 -43
- package/src/components/steps/index.ts +0 -6
- package/src/components/steps/step.tsx +0 -23
- package/src/components/steps/steps-action.tsx +0 -65
- package/src/components/steps/steps-content.tsx +0 -12
- package/src/components/steps/steps-context.tsx +0 -121
- package/src/components/steps/steps-navigation.tsx +0 -80
- package/src/components/steps/steps-root.tsx +0 -9
- package/src/components/table/index.ts +0 -8
- package/src/components/table/table-body.tsx +0 -17
- package/src/components/table/table-cell.tsx +0 -14
- package/src/components/table/table-footer.tsx +0 -17
- package/src/components/table/table-head.tsx +0 -31
- package/src/components/table/table-header.tsx +0 -17
- package/src/components/table/table-row.tsx +0 -21
- package/src/components/table/table-sort.tsx +0 -34
- package/src/components/table/table.tsx +0 -16
- package/src/components/tabs.tsx +0 -72
- package/src/components/tag.tsx +0 -99
- package/src/components/tooltip.tsx +0 -63
- package/src/components/typography.tsx +0 -85
- package/src/components/upload.tsx +0 -647
- package/src/hooks/index.ts +0 -1
- package/src/hooks/use-os.ts +0 -32
- package/src/index.css +0 -5
- package/src/resources/icons.ts +0 -154
- package/src/resources/input-mask.ts +0 -91
- package/src/resources/logo/horizontal.tsx +0 -70
- package/src/resources/logo/icon.tsx +0 -54
- package/src/resources/logo/index.tsx +0 -33
- package/src/resources/logo/vertical.tsx +0 -70
- package/src/types.d.ts +0 -4
- package/tsconfig.json +0 -4
- package/tsup.config.ts +0 -30
|
@@ -1,372 +0,0 @@
|
|
|
1
|
-
import { cx } from '@xjur-ui/util'
|
|
2
|
-
import { useCallback, useMemo, useState, type ComponentProps } from 'react'
|
|
3
|
-
import {
|
|
4
|
-
EditorContent,
|
|
5
|
-
EditorContext,
|
|
6
|
-
useCurrentEditor as useRichTextEditor,
|
|
7
|
-
useEditorState as useRichTextEditorState,
|
|
8
|
-
useEditor,
|
|
9
|
-
type EditorOptions
|
|
10
|
-
} from '@tiptap/react'
|
|
11
|
-
import type { Extension } from '@tiptap/core'
|
|
12
|
-
import { StarterKit } from '@tiptap/starter-kit'
|
|
13
|
-
import { Heading, type Level } from '@tiptap/extension-heading'
|
|
14
|
-
// Import specific extension instead of full extensions bundle
|
|
15
|
-
import { Placeholder } from '@tiptap/extension-placeholder'
|
|
16
|
-
import { useOS } from '../../hooks'
|
|
17
|
-
import { Icon, type IconType } from '../icon'
|
|
18
|
-
import { Button, type ButtonProps } from './button'
|
|
19
|
-
import {
|
|
20
|
-
DropdownMenuContent,
|
|
21
|
-
DropdownMenuItem,
|
|
22
|
-
DropdownMenuItemText,
|
|
23
|
-
DropdownMenuList,
|
|
24
|
-
DropdownMenuRoot,
|
|
25
|
-
DropdownMenuTrigger
|
|
26
|
-
} from '../dropdown-menu'
|
|
27
|
-
import { Tooltip, TooltipTrigger, TooltipContent } from '../tooltip'
|
|
28
|
-
import { Typography } from '../typography'
|
|
29
|
-
|
|
30
|
-
const headingClasses: Partial<Record<Level, string>> = {
|
|
31
|
-
1: 'text-size-body-md',
|
|
32
|
-
2: 'text-size-title-lg',
|
|
33
|
-
3: 'text-size-headline-lg'
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
export function RichEditorRoot({
|
|
37
|
-
className,
|
|
38
|
-
editorOptions,
|
|
39
|
-
...props
|
|
40
|
-
}: ComponentProps<'div'> & {
|
|
41
|
-
editorOptions?: Partial<
|
|
42
|
-
Omit<EditorOptions, 'extensions'> & {
|
|
43
|
-
extensions?: Extension[]
|
|
44
|
-
}
|
|
45
|
-
>
|
|
46
|
-
}) {
|
|
47
|
-
const editor = useEditor({
|
|
48
|
-
...editorOptions,
|
|
49
|
-
extensions: [
|
|
50
|
-
StarterKit.configure({
|
|
51
|
-
bulletList: {
|
|
52
|
-
HTMLAttributes: {
|
|
53
|
-
class: 'list-disc list-outside pl-large-1x'
|
|
54
|
-
}
|
|
55
|
-
},
|
|
56
|
-
orderedList: {
|
|
57
|
-
HTMLAttributes: {
|
|
58
|
-
class: 'list-decimal list-outside pl-large-1x'
|
|
59
|
-
}
|
|
60
|
-
},
|
|
61
|
-
heading: false
|
|
62
|
-
}),
|
|
63
|
-
Placeholder.configure({
|
|
64
|
-
placeholder: ({ node, editor }) =>
|
|
65
|
-
node.type.name === 'paragraph' && editor.isEmpty
|
|
66
|
-
? 'Digite aqui…'
|
|
67
|
-
: '',
|
|
68
|
-
showOnlyWhenEditable: true,
|
|
69
|
-
includeChildren: false,
|
|
70
|
-
emptyNodeClass:
|
|
71
|
-
'before:content-[attr(data-placeholder)] before:absolute before:top-0 before:left-0 before:text-neutral-placeholder first:before:float-left first:before:content-[attr(data-placeholder)] first:before:pointer-events-none'
|
|
72
|
-
}),
|
|
73
|
-
Heading.configure({
|
|
74
|
-
levels: [1, 2, 3]
|
|
75
|
-
}).extend({
|
|
76
|
-
renderHTML({ node, HTMLAttributes }) {
|
|
77
|
-
const level: Level = node.attrs.level ?? 1
|
|
78
|
-
|
|
79
|
-
return [
|
|
80
|
-
'h',
|
|
81
|
-
{
|
|
82
|
-
...HTMLAttributes,
|
|
83
|
-
class: headingClasses[level]
|
|
84
|
-
},
|
|
85
|
-
0
|
|
86
|
-
]
|
|
87
|
-
}
|
|
88
|
-
}),
|
|
89
|
-
...(editorOptions?.extensions ?? [])
|
|
90
|
-
]
|
|
91
|
-
})
|
|
92
|
-
|
|
93
|
-
const value = useMemo(() => ({ editor }), [editor])
|
|
94
|
-
|
|
95
|
-
return (
|
|
96
|
-
<EditorContext.Provider value={value}>
|
|
97
|
-
<div
|
|
98
|
-
className={cx('gap-small flex w-full flex-col', className)}
|
|
99
|
-
data-slot="text-area-root"
|
|
100
|
-
{...props}
|
|
101
|
-
/>
|
|
102
|
-
</EditorContext.Provider>
|
|
103
|
-
)
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
export function RichEditorContent({
|
|
107
|
-
className,
|
|
108
|
-
...props
|
|
109
|
-
}: ComponentProps<'div'>) {
|
|
110
|
-
return (
|
|
111
|
-
<div
|
|
112
|
-
className={cx(
|
|
113
|
-
'bg-layer-2-hover py-small_1x-alt px-small rounded-small-1x min-h-[116px] w-full border border-transparent',
|
|
114
|
-
'hover:border-border-layer-2 transition-colors duration-200',
|
|
115
|
-
'[&_ul_ul]:list-[circle]',
|
|
116
|
-
'[&_ul_ul_ul]:list-[square]',
|
|
117
|
-
'[&_ol_ol]:list-[lower-alpha]',
|
|
118
|
-
'[&_ol_ol_ol]:list-[lower-roman]',
|
|
119
|
-
'gap-small flex flex-col overflow-x-hidden overflow-y-auto',
|
|
120
|
-
className
|
|
121
|
-
)}
|
|
122
|
-
data-slot="text-area-content"
|
|
123
|
-
{...props}
|
|
124
|
-
/>
|
|
125
|
-
)
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
export function RichEditorCaption({
|
|
129
|
-
className,
|
|
130
|
-
...props
|
|
131
|
-
}: ComponentProps<'p'>) {
|
|
132
|
-
return (
|
|
133
|
-
<p
|
|
134
|
-
{...props}
|
|
135
|
-
className={cx(
|
|
136
|
-
'text-size-body-sm text-neutral-dark font-normal',
|
|
137
|
-
className
|
|
138
|
-
)}
|
|
139
|
-
data-slot="text-area-caption"
|
|
140
|
-
/>
|
|
141
|
-
)
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
export function RichEditorAreaText({
|
|
145
|
-
className,
|
|
146
|
-
...props
|
|
147
|
-
}: Omit<ComponentProps<typeof EditorContent>, 'editor'>) {
|
|
148
|
-
const { editor } = useRichTextEditor()
|
|
149
|
-
|
|
150
|
-
return (
|
|
151
|
-
<EditorContent
|
|
152
|
-
className={cx(
|
|
153
|
-
'text-size-body-md text-neutral-dark max-h-[116px] *:h-full *:w-full *:outline-0',
|
|
154
|
-
className
|
|
155
|
-
)}
|
|
156
|
-
editor={editor}
|
|
157
|
-
{...props}
|
|
158
|
-
/>
|
|
159
|
-
)
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
export function RichEditorToolbar({
|
|
163
|
-
className,
|
|
164
|
-
...props
|
|
165
|
-
}: ComponentProps<'div'>) {
|
|
166
|
-
return (
|
|
167
|
-
<div
|
|
168
|
-
className={cx(
|
|
169
|
-
'h-large-4x gap-small-1x h-large-6px scrollbar-hide flex flex-nowrap items-center overflow-x-auto overflow-y-hidden',
|
|
170
|
-
className
|
|
171
|
-
)}
|
|
172
|
-
data-slot="text-area-toolbar"
|
|
173
|
-
{...props}
|
|
174
|
-
/>
|
|
175
|
-
)
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
export function ToolbarButton({
|
|
179
|
-
appearance = 'ghost',
|
|
180
|
-
variant = 'secondary',
|
|
181
|
-
onMouseDown,
|
|
182
|
-
onPointerDown,
|
|
183
|
-
...props
|
|
184
|
-
}: ButtonProps) {
|
|
185
|
-
return (
|
|
186
|
-
<Button
|
|
187
|
-
appearance={appearance}
|
|
188
|
-
size="icon_md"
|
|
189
|
-
tabIndex={-1}
|
|
190
|
-
type="button"
|
|
191
|
-
variant={variant}
|
|
192
|
-
onMouseDown={e => {
|
|
193
|
-
e.preventDefault()
|
|
194
|
-
onMouseDown?.(e)
|
|
195
|
-
}}
|
|
196
|
-
onPointerDown={e => {
|
|
197
|
-
e.preventDefault()
|
|
198
|
-
onPointerDown?.(e)
|
|
199
|
-
}}
|
|
200
|
-
{...props}
|
|
201
|
-
/>
|
|
202
|
-
)
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
type ToggleButtonName =
|
|
206
|
-
| 'bold'
|
|
207
|
-
| 'italic'
|
|
208
|
-
| 'underline'
|
|
209
|
-
| 'strike'
|
|
210
|
-
| 'bulletList'
|
|
211
|
-
| 'orderedList'
|
|
212
|
-
| 'undo'
|
|
213
|
-
| 'redo'
|
|
214
|
-
|
|
215
|
-
export function ToggleButton({
|
|
216
|
-
name,
|
|
217
|
-
...props
|
|
218
|
-
}: ButtonProps & { name: ToggleButtonName }) {
|
|
219
|
-
const { editor } = useRichTextEditor()
|
|
220
|
-
const { shortcut } = useOS()
|
|
221
|
-
|
|
222
|
-
const isActive = useRichTextEditorState({
|
|
223
|
-
editor,
|
|
224
|
-
selector: ctx => ctx.editor?.isActive(name) ?? false
|
|
225
|
-
})
|
|
226
|
-
|
|
227
|
-
const icon = useMemo(() => {
|
|
228
|
-
const iconsMap = new Map<ToggleButtonName, IconType>([
|
|
229
|
-
['bold', 'format_bold'],
|
|
230
|
-
['italic', 'format_italic'],
|
|
231
|
-
['underline', 'format_underlined'],
|
|
232
|
-
['strike', 'format_strikethrough'],
|
|
233
|
-
['bulletList', 'format_list_bulleted'],
|
|
234
|
-
['orderedList', 'format_list_numbered'],
|
|
235
|
-
['undo', 'undo'],
|
|
236
|
-
['redo', 'redo']
|
|
237
|
-
])
|
|
238
|
-
|
|
239
|
-
return iconsMap.get(name)
|
|
240
|
-
}, [name])
|
|
241
|
-
|
|
242
|
-
const description = useMemo(() => {
|
|
243
|
-
const descriptionsMap = new Map<ToggleButtonName, string>([
|
|
244
|
-
['bold', `Negrito (${shortcut} + B)`],
|
|
245
|
-
['italic', `Itálico (${shortcut} + I)`],
|
|
246
|
-
['underline', `Sublinhado (${shortcut} + U)`],
|
|
247
|
-
['strike', `Tachado (${shortcut} + S)`],
|
|
248
|
-
['bulletList', `Lista (${shortcut} + Shift + 7)`],
|
|
249
|
-
['orderedList', `Lista numerada (${shortcut} + Shift + 8)`],
|
|
250
|
-
['undo', `Desfazer (${shortcut} + Z)`],
|
|
251
|
-
['redo', `Refazer (${shortcut} + Y)`]
|
|
252
|
-
])
|
|
253
|
-
|
|
254
|
-
return descriptionsMap.get(name)
|
|
255
|
-
}, [name, shortcut])
|
|
256
|
-
|
|
257
|
-
const handleToggle = useCallback(() => {
|
|
258
|
-
if (!editor) throw new Error('Editor not found')
|
|
259
|
-
|
|
260
|
-
const commandsMap = new Map<ToggleButtonName, () => void>([
|
|
261
|
-
['bold', () => editor.chain().focus().toggleBold().run()],
|
|
262
|
-
['italic', () => editor.chain().focus().toggleItalic().run()],
|
|
263
|
-
['underline', () => editor.chain().focus().toggleUnderline().run()],
|
|
264
|
-
['strike', () => editor.chain().focus().toggleStrike().run()],
|
|
265
|
-
['bulletList', () => editor.chain().focus().toggleBulletList().run()],
|
|
266
|
-
['orderedList', () => editor.chain().focus().toggleOrderedList().run()],
|
|
267
|
-
['undo', () => editor.chain().focus().undo().run()],
|
|
268
|
-
['redo', () => editor.chain().focus().redo().run()]
|
|
269
|
-
])
|
|
270
|
-
|
|
271
|
-
commandsMap.get(name)?.()
|
|
272
|
-
}, [editor, name])
|
|
273
|
-
|
|
274
|
-
return (
|
|
275
|
-
<Tooltip>
|
|
276
|
-
<TooltipTrigger asChild={true}>
|
|
277
|
-
<ToolbarButton
|
|
278
|
-
onClick={handleToggle}
|
|
279
|
-
{...(isActive && { appearance: 'solid' })}
|
|
280
|
-
{...props}
|
|
281
|
-
>
|
|
282
|
-
{icon && <Icon className="text-icon-neutral-3" name={icon} />}
|
|
283
|
-
</ToolbarButton>
|
|
284
|
-
</TooltipTrigger>
|
|
285
|
-
|
|
286
|
-
<TooltipContent>
|
|
287
|
-
{description && <Typography size="sm">{description}</Typography>}
|
|
288
|
-
</TooltipContent>
|
|
289
|
-
</Tooltip>
|
|
290
|
-
)
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
export function HeadingButton({
|
|
294
|
-
appearance = 'ghost',
|
|
295
|
-
variant = 'secondary',
|
|
296
|
-
...props
|
|
297
|
-
}: ButtonProps) {
|
|
298
|
-
const [isOpen, setIsOpen] = useState(false)
|
|
299
|
-
const { editor } = useRichTextEditor()
|
|
300
|
-
|
|
301
|
-
const isActive = useRichTextEditorState({
|
|
302
|
-
editor,
|
|
303
|
-
selector: ctx => ctx.editor?.isActive('heading') ?? false
|
|
304
|
-
})
|
|
305
|
-
|
|
306
|
-
const isLevelActive = useCallback(
|
|
307
|
-
(level: Level) => {
|
|
308
|
-
if (!editor) throw new Error('Editor not found')
|
|
309
|
-
return editor.isActive('heading', { level })
|
|
310
|
-
},
|
|
311
|
-
[editor]
|
|
312
|
-
)
|
|
313
|
-
|
|
314
|
-
const toggleHeading = useCallback(
|
|
315
|
-
(level: Level) => {
|
|
316
|
-
if (!editor) throw new Error('Editor not found')
|
|
317
|
-
setIsOpen(false)
|
|
318
|
-
setTimeout(() => {
|
|
319
|
-
editor.chain().focus().toggleHeading({ level }).run()
|
|
320
|
-
}, 0)
|
|
321
|
-
},
|
|
322
|
-
[editor]
|
|
323
|
-
)
|
|
324
|
-
|
|
325
|
-
const levels: { level: Level; label: string; className?: string }[] = [
|
|
326
|
-
{ level: 1, label: 'Normal', className: headingClasses[1] },
|
|
327
|
-
{ level: 2, label: 'Grande', className: headingClasses[2] },
|
|
328
|
-
{ level: 3, label: 'Enorme', className: headingClasses[3] }
|
|
329
|
-
]
|
|
330
|
-
|
|
331
|
-
return (
|
|
332
|
-
<DropdownMenuRoot open={isOpen} onOpenChange={open => setIsOpen(open)}>
|
|
333
|
-
<DropdownMenuTrigger asChild={true}>
|
|
334
|
-
<Button
|
|
335
|
-
appearance={isActive ? 'solid' : appearance}
|
|
336
|
-
size="icon_md"
|
|
337
|
-
tabIndex={-1}
|
|
338
|
-
type="button"
|
|
339
|
-
variant={variant}
|
|
340
|
-
{...props}
|
|
341
|
-
>
|
|
342
|
-
<Tooltip>
|
|
343
|
-
<TooltipTrigger asChild={true}>
|
|
344
|
-
<Icon className="text-icon-neutral-3" name="format_size" />
|
|
345
|
-
</TooltipTrigger>
|
|
346
|
-
|
|
347
|
-
<TooltipContent>
|
|
348
|
-
<Typography size="sm">Tamanho</Typography>
|
|
349
|
-
</TooltipContent>
|
|
350
|
-
</Tooltip>
|
|
351
|
-
</Button>
|
|
352
|
-
</DropdownMenuTrigger>
|
|
353
|
-
<DropdownMenuContent>
|
|
354
|
-
<DropdownMenuList>
|
|
355
|
-
{levels.map(level => (
|
|
356
|
-
<DropdownMenuItem
|
|
357
|
-
isActive={isLevelActive(level.level)}
|
|
358
|
-
key={level.level}
|
|
359
|
-
onPointerDown={() => toggleHeading(level.level)}
|
|
360
|
-
>
|
|
361
|
-
<DropdownMenuItemText className={level.className}>
|
|
362
|
-
{level.label}
|
|
363
|
-
</DropdownMenuItemText>
|
|
364
|
-
</DropdownMenuItem>
|
|
365
|
-
))}
|
|
366
|
-
</DropdownMenuList>
|
|
367
|
-
</DropdownMenuContent>
|
|
368
|
-
</DropdownMenuRoot>
|
|
369
|
-
)
|
|
370
|
-
}
|
|
371
|
-
|
|
372
|
-
export { useRichTextEditorState, useRichTextEditor }
|
|
@@ -1,154 +0,0 @@
|
|
|
1
|
-
import { cva, cx } from '@xjur-ui/util'
|
|
2
|
-
import { createContext, type ComponentProps } from 'react'
|
|
3
|
-
import {
|
|
4
|
-
InputMask as InputMaskComponent,
|
|
5
|
-
type MaskOptions
|
|
6
|
-
} from '@react-input/mask'
|
|
7
|
-
import {
|
|
8
|
-
InputNumberFormat,
|
|
9
|
-
type InputNumberFormatProps
|
|
10
|
-
} from '@react-input/number-format'
|
|
11
|
-
import { Typography } from '../typography'
|
|
12
|
-
import { inputMask, type InputMaskType } from '../../resources/input-mask'
|
|
13
|
-
import { Button, type ButtonProps } from './button'
|
|
14
|
-
|
|
15
|
-
export type SearchInputProps = {
|
|
16
|
-
variant?: 'outlined' | 'line' | 'action'
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
const SearchInputRootContext = createContext<SearchInputProps>({
|
|
20
|
-
variant: 'outlined'
|
|
21
|
-
})
|
|
22
|
-
|
|
23
|
-
export function SearchInputRoot({
|
|
24
|
-
className,
|
|
25
|
-
variant = 'outlined',
|
|
26
|
-
...props
|
|
27
|
-
}: ComponentProps<'div'> & SearchInputProps) {
|
|
28
|
-
return (
|
|
29
|
-
<SearchInputRootContext.Provider value={{ variant }}>
|
|
30
|
-
<div className={cx('relative flex', className)} {...props} />
|
|
31
|
-
</SearchInputRootContext.Provider>
|
|
32
|
-
)
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
export function SearchInputContent({
|
|
36
|
-
className,
|
|
37
|
-
...props
|
|
38
|
-
}: ComponentProps<'div'>) {
|
|
39
|
-
const contentVarians = cva(
|
|
40
|
-
[
|
|
41
|
-
'gap-small py-small_1x-alt px-small flex items-center w-full',
|
|
42
|
-
'h-large-4x rounded-circle',
|
|
43
|
-
'border-border-layer-2 placeholder:placeholder-neutral-placeholder text-size-body-md text-neutral-dark border font-normal',
|
|
44
|
-
'group-hover:border-border-layer-3 transition-colors duration-200',
|
|
45
|
-
'disabled:opacity-60',
|
|
46
|
-
'focus-within:border-primary-idle'
|
|
47
|
-
],
|
|
48
|
-
{
|
|
49
|
-
variants: {
|
|
50
|
-
variant: {
|
|
51
|
-
outlined: 'rounded-circle focus-within:border-primary-idle ',
|
|
52
|
-
line: 'rounded-none border-t-0 border-b-1 border-x-0',
|
|
53
|
-
action: 'rounded-tr-none rounded-br-none border-r-0'
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
)
|
|
58
|
-
|
|
59
|
-
return (
|
|
60
|
-
<SearchInputRootContext.Consumer>
|
|
61
|
-
{({ variant }) => (
|
|
62
|
-
<div
|
|
63
|
-
className={cx(className, contentVarians({ variant }))}
|
|
64
|
-
data-variant={variant}
|
|
65
|
-
{...props}
|
|
66
|
-
/>
|
|
67
|
-
)}
|
|
68
|
-
</SearchInputRootContext.Consumer>
|
|
69
|
-
)
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
export function SearchInputLabel({
|
|
73
|
-
htmlFor,
|
|
74
|
-
...props
|
|
75
|
-
}: ComponentProps<'label'>) {
|
|
76
|
-
return (
|
|
77
|
-
<Typography
|
|
78
|
-
asChild={true}
|
|
79
|
-
className={cx('absolute -top-[22px] left-0')}
|
|
80
|
-
size="sm"
|
|
81
|
-
variant="label"
|
|
82
|
-
weight="medium"
|
|
83
|
-
>
|
|
84
|
-
<label htmlFor={htmlFor} {...props} />
|
|
85
|
-
</Typography>
|
|
86
|
-
)
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
export function SearchInputText({
|
|
90
|
-
className,
|
|
91
|
-
...props
|
|
92
|
-
}: ComponentProps<'input'>) {
|
|
93
|
-
return <input className={cx(className, 'flex-1 outline-none')} {...props} />
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
export function SearchInputMask({
|
|
97
|
-
className,
|
|
98
|
-
mask,
|
|
99
|
-
customMask,
|
|
100
|
-
...props
|
|
101
|
-
}: ComponentProps<'input'> & {
|
|
102
|
-
mask?: InputMaskType
|
|
103
|
-
customMask?: MaskOptions
|
|
104
|
-
}) {
|
|
105
|
-
return (
|
|
106
|
-
<InputMaskComponent
|
|
107
|
-
{...(mask ? { ...inputMask(mask) } : customMask && { ...customMask })}
|
|
108
|
-
className={cx(className, 'flex-1 outline-none')}
|
|
109
|
-
{...props}
|
|
110
|
-
/>
|
|
111
|
-
)
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
export function SearchInputNumber({
|
|
115
|
-
className,
|
|
116
|
-
locales = 'pt-BR',
|
|
117
|
-
groupDisplay = false,
|
|
118
|
-
...props
|
|
119
|
-
}: InputNumberFormatProps) {
|
|
120
|
-
return (
|
|
121
|
-
<InputNumberFormat
|
|
122
|
-
className={cx(className, 'flex-1 outline-none')}
|
|
123
|
-
groupDisplay={groupDisplay}
|
|
124
|
-
locales={locales}
|
|
125
|
-
{...props}
|
|
126
|
-
/>
|
|
127
|
-
)
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
export function SearchInputSlot(props: ComponentProps<'div'>) {
|
|
131
|
-
return <div {...props} data-slot="search-input-slot" />
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
export function SearchInputAction({
|
|
135
|
-
className,
|
|
136
|
-
appearance = 'ghost',
|
|
137
|
-
variant = 'outlined',
|
|
138
|
-
...props
|
|
139
|
-
}: ButtonProps) {
|
|
140
|
-
return (
|
|
141
|
-
<Button
|
|
142
|
-
{...props}
|
|
143
|
-
appearance={appearance}
|
|
144
|
-
className={cx(
|
|
145
|
-
className,
|
|
146
|
-
'cursor-pointer',
|
|
147
|
-
'h-large-4x rounded-tr-circle rounded-br-circle px-small py-small_1x-alt flex items-center justify-center rounded-none',
|
|
148
|
-
'text-size-body-md text-neutral-dark gap-small-1x !border-l-0'
|
|
149
|
-
)}
|
|
150
|
-
data-slot="search-input-action"
|
|
151
|
-
variant={variant}
|
|
152
|
-
/>
|
|
153
|
-
)
|
|
154
|
-
}
|
|
@@ -1,98 +0,0 @@
|
|
|
1
|
-
import { useMemo, useState, type ComponentProps } from 'react'
|
|
2
|
-
import type { MaskOptions } from '@react-input/mask'
|
|
3
|
-
import type { InputMaskType } from '../../resources/input-mask'
|
|
4
|
-
import {
|
|
5
|
-
DropdownMenuRoot,
|
|
6
|
-
DropdownMenuList,
|
|
7
|
-
DropdownMenuItemText,
|
|
8
|
-
DropdownMenuContent,
|
|
9
|
-
DropdownMenuItem,
|
|
10
|
-
DropdownMenuTrigger
|
|
11
|
-
} from '../dropdown-menu'
|
|
12
|
-
import { Icon } from '../icon'
|
|
13
|
-
import {
|
|
14
|
-
SearchInputContent,
|
|
15
|
-
SearchInputRoot,
|
|
16
|
-
SearchInputSlot,
|
|
17
|
-
SearchInputAction,
|
|
18
|
-
SearchInputMask,
|
|
19
|
-
SearchInputText
|
|
20
|
-
} from './search-input'
|
|
21
|
-
|
|
22
|
-
interface SelectorOption {
|
|
23
|
-
label: string
|
|
24
|
-
value: string
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
interface SearchSelectorProps extends ComponentProps<'input'> {
|
|
28
|
-
options: SelectorOption[]
|
|
29
|
-
selectedSearchOption?: string
|
|
30
|
-
mask?: InputMaskType
|
|
31
|
-
customMask?: MaskOptions
|
|
32
|
-
|
|
33
|
-
onChangeSearchOption?: (option: string) => void
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
export function SearchSelector({
|
|
37
|
-
options,
|
|
38
|
-
mask,
|
|
39
|
-
customMask,
|
|
40
|
-
placeholder = 'Pesquisar',
|
|
41
|
-
onChangeSearchOption,
|
|
42
|
-
selectedSearchOption: initialSelectedSearchOption,
|
|
43
|
-
...props
|
|
44
|
-
}: SearchSelectorProps) {
|
|
45
|
-
const [selectedSearchOption, setSelectedSearchOption] = useState(
|
|
46
|
-
initialSelectedSearchOption
|
|
47
|
-
)
|
|
48
|
-
|
|
49
|
-
const selectedSearchLabel = useMemo(
|
|
50
|
-
() => options.find(option => option.value === selectedSearchOption)?.label,
|
|
51
|
-
[options, selectedSearchOption]
|
|
52
|
-
)
|
|
53
|
-
|
|
54
|
-
return (
|
|
55
|
-
<SearchInputRoot className="w-full" variant="action">
|
|
56
|
-
<SearchInputContent>
|
|
57
|
-
<SearchInputSlot>
|
|
58
|
-
<Icon className="text-icon-neutral-3" name="search" />
|
|
59
|
-
</SearchInputSlot>
|
|
60
|
-
{mask || customMask ? (
|
|
61
|
-
<SearchInputMask
|
|
62
|
-
customMask={customMask}
|
|
63
|
-
mask={mask}
|
|
64
|
-
placeholder={placeholder}
|
|
65
|
-
{...props}
|
|
66
|
-
/>
|
|
67
|
-
) : (
|
|
68
|
-
<SearchInputText placeholder={placeholder} {...props} />
|
|
69
|
-
)}
|
|
70
|
-
</SearchInputContent>
|
|
71
|
-
|
|
72
|
-
<DropdownMenuRoot>
|
|
73
|
-
<DropdownMenuTrigger asChild={true}>
|
|
74
|
-
<SearchInputAction>
|
|
75
|
-
{selectedSearchLabel}
|
|
76
|
-
<Icon className="text-icon-neutral-3" name="keyboard_arrow_down" />
|
|
77
|
-
</SearchInputAction>
|
|
78
|
-
</DropdownMenuTrigger>
|
|
79
|
-
<DropdownMenuContent>
|
|
80
|
-
<DropdownMenuList>
|
|
81
|
-
{options.map(option => (
|
|
82
|
-
<DropdownMenuItem
|
|
83
|
-
isActive={selectedSearchOption === option.value}
|
|
84
|
-
key={option.value}
|
|
85
|
-
onClick={() => {
|
|
86
|
-
setSelectedSearchOption(option.value)
|
|
87
|
-
onChangeSearchOption?.(option.value)
|
|
88
|
-
}}
|
|
89
|
-
>
|
|
90
|
-
<DropdownMenuItemText>{option.label}</DropdownMenuItemText>
|
|
91
|
-
</DropdownMenuItem>
|
|
92
|
-
))}
|
|
93
|
-
</DropdownMenuList>
|
|
94
|
-
</DropdownMenuContent>
|
|
95
|
-
</DropdownMenuRoot>
|
|
96
|
-
</SearchInputRoot>
|
|
97
|
-
)
|
|
98
|
-
}
|