datool 0.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 (45) hide show
  1. package/README.md +218 -0
  2. package/client-dist/assets/geist-cyrillic-wght-normal-CHSlOQsW.woff2 +0 -0
  3. package/client-dist/assets/geist-latin-ext-wght-normal-DMtmJ5ZE.woff2 +0 -0
  4. package/client-dist/assets/geist-latin-wght-normal-Dm3htQBi.woff2 +0 -0
  5. package/client-dist/assets/index-BeRNeRUq.css +1 -0
  6. package/client-dist/assets/index-uoZ4c_I8.js +164 -0
  7. package/client-dist/index.html +13 -0
  8. package/index.html +12 -0
  9. package/package.json +55 -0
  10. package/src/client/App.tsx +885 -0
  11. package/src/client/components/connection-status.tsx +43 -0
  12. package/src/client/components/data-table-cell.tsx +235 -0
  13. package/src/client/components/data-table-col-icon.tsx +73 -0
  14. package/src/client/components/data-table-header-col.tsx +225 -0
  15. package/src/client/components/data-table-search-input.tsx +729 -0
  16. package/src/client/components/data-table.tsx +2014 -0
  17. package/src/client/components/stream-controls.tsx +157 -0
  18. package/src/client/components/theme-provider.tsx +230 -0
  19. package/src/client/components/ui/button.tsx +68 -0
  20. package/src/client/components/ui/combobox.tsx +308 -0
  21. package/src/client/components/ui/context-menu.tsx +261 -0
  22. package/src/client/components/ui/dropdown-menu.tsx +267 -0
  23. package/src/client/components/ui/input-group.tsx +153 -0
  24. package/src/client/components/ui/input.tsx +19 -0
  25. package/src/client/components/ui/textarea.tsx +18 -0
  26. package/src/client/components/viewer-settings.tsx +185 -0
  27. package/src/client/index.css +192 -0
  28. package/src/client/lib/data-table-search.ts +750 -0
  29. package/src/client/lib/datool-icons.ts +37 -0
  30. package/src/client/lib/datool-url-state.ts +159 -0
  31. package/src/client/lib/filterable-table.ts +146 -0
  32. package/src/client/lib/table-search-persistence.ts +94 -0
  33. package/src/client/lib/utils.ts +6 -0
  34. package/src/client/main.tsx +14 -0
  35. package/src/index.ts +19 -0
  36. package/src/node/cli.ts +54 -0
  37. package/src/node/config.ts +231 -0
  38. package/src/node/lines.ts +82 -0
  39. package/src/node/runtime.ts +102 -0
  40. package/src/node/server.ts +403 -0
  41. package/src/node/sources/command.ts +82 -0
  42. package/src/node/sources/file.ts +116 -0
  43. package/src/node/sources/ssh.ts +59 -0
  44. package/src/shared/columns.ts +41 -0
  45. package/src/shared/types.ts +188 -0
@@ -0,0 +1,308 @@
1
+ "use client"
2
+
3
+ import * as React from "react"
4
+ import { Combobox as ComboboxPrimitive } from "@base-ui/react"
5
+
6
+ import { cn } from "@/lib/utils"
7
+ import { Button } from "@/components/ui/button"
8
+ import {
9
+ InputGroup,
10
+ InputGroupAddon,
11
+ InputGroupButton,
12
+ InputGroupInput,
13
+ } from "@/components/ui/input-group"
14
+ import { ChevronDownIcon, XIcon, CheckIcon } from "lucide-react"
15
+
16
+ const Combobox = ComboboxPrimitive.Root
17
+
18
+ function ComboboxValue({ ...props }: ComboboxPrimitive.Value.Props) {
19
+ return <ComboboxPrimitive.Value data-slot="combobox-value" {...props} />
20
+ }
21
+
22
+ function ComboboxTrigger({
23
+ className,
24
+ children,
25
+ ...props
26
+ }: ComboboxPrimitive.Trigger.Props) {
27
+ return (
28
+ <ComboboxPrimitive.Trigger
29
+ data-slot="combobox-trigger"
30
+ className={cn("[&_svg:not([class*='size-'])]:size-3.5", className)}
31
+ {...props}
32
+ >
33
+ {children}
34
+ <ChevronDownIcon className="pointer-events-none size-3.5 text-muted-foreground" />
35
+ </ComboboxPrimitive.Trigger>
36
+ )
37
+ }
38
+
39
+ function ComboboxClear({ className, ...props }: ComboboxPrimitive.Clear.Props) {
40
+ return (
41
+ <ComboboxPrimitive.Clear
42
+ data-slot="combobox-clear"
43
+ render={<InputGroupButton variant="ghost" size="icon-xs" />}
44
+ className={cn(className)}
45
+ {...props}
46
+ >
47
+ <XIcon className="pointer-events-none" />
48
+ </ComboboxPrimitive.Clear>
49
+ )
50
+ }
51
+
52
+ function ComboboxInput({
53
+ className,
54
+ children,
55
+ containerRef,
56
+ disabled = false,
57
+ startAdornment,
58
+ showTrigger = true,
59
+ showClear = false,
60
+ inputClassName,
61
+ ...props
62
+ }: ComboboxPrimitive.Input.Props & {
63
+ containerRef?: React.Ref<HTMLDivElement>
64
+ startAdornment?: React.ReactNode
65
+ showTrigger?: boolean
66
+ showClear?: boolean
67
+ inputClassName?: string
68
+ }) {
69
+ return (
70
+ <InputGroup ref={containerRef} className={cn("w-auto", className)}>
71
+ {startAdornment ? (
72
+ <InputGroupAddon align="inline-start">{startAdornment}</InputGroupAddon>
73
+ ) : null}
74
+ <ComboboxPrimitive.Input
75
+ render={
76
+ <InputGroupInput disabled={disabled} className={inputClassName} />
77
+ }
78
+ {...props}
79
+ />
80
+ <InputGroupAddon align="inline-end">
81
+ {showTrigger && (
82
+ <InputGroupButton
83
+ size="icon-xs"
84
+ variant="ghost"
85
+ asChild
86
+ data-slot="input-group-button"
87
+ className="group-has-data-[slot=combobox-clear]/input-group:hidden data-pressed:bg-transparent"
88
+ disabled={disabled}
89
+ >
90
+ <ComboboxTrigger />
91
+ </InputGroupButton>
92
+ )}
93
+ {showClear && <ComboboxClear disabled={disabled} />}
94
+ </InputGroupAddon>
95
+ {children}
96
+ </InputGroup>
97
+ )
98
+ }
99
+
100
+ function ComboboxContent({
101
+ className,
102
+ side = "bottom",
103
+ sideOffset = 6,
104
+ align = "start",
105
+ alignOffset = 0,
106
+ anchor,
107
+ ...props
108
+ }: ComboboxPrimitive.Popup.Props &
109
+ Pick<
110
+ ComboboxPrimitive.Positioner.Props,
111
+ "side" | "align" | "sideOffset" | "alignOffset" | "anchor"
112
+ >) {
113
+ return (
114
+ <ComboboxPrimitive.Portal>
115
+ <ComboboxPrimitive.Positioner
116
+ side={side}
117
+ sideOffset={sideOffset}
118
+ align={align}
119
+ alignOffset={alignOffset}
120
+ anchor={anchor}
121
+ className="isolate z-50"
122
+ >
123
+ <ComboboxPrimitive.Popup
124
+ data-slot="combobox-content"
125
+ data-chips={!!anchor}
126
+ className={cn(
127
+ "group/combobox-content relative max-h-(--available-height) w-(--anchor-width) max-w-(--available-width) min-w-[calc(var(--anchor-width)+--spacing(7))] origin-(--transform-origin) overflow-hidden rounded-lg bg-popover text-popover-foreground shadow-md ring-1 ring-foreground/10 duration-100 data-[chips=true]:min-w-(--anchor-width) data-[side=bottom]:slide-in-from-top-2 data-[side=inline-end]:slide-in-from-left-2 data-[side=inline-start]:slide-in-from-right-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 *:data-[slot=input-group]:m-1 *:data-[slot=input-group]:mb-0 *:data-[slot=input-group]:h-7 *:data-[slot=input-group]:border-none *:data-[slot=input-group]:bg-input/20 *:data-[slot=input-group]:shadow-none dark:bg-popover data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95",
128
+ className
129
+ )}
130
+ {...props}
131
+ />
132
+ </ComboboxPrimitive.Positioner>
133
+ </ComboboxPrimitive.Portal>
134
+ )
135
+ }
136
+
137
+ function ComboboxList({ className, ...props }: ComboboxPrimitive.List.Props) {
138
+ return (
139
+ <ComboboxPrimitive.List
140
+ data-slot="combobox-list"
141
+ className={cn(
142
+ "no-scrollbar max-h-[min(calc(--spacing(72)---spacing(9)),calc(var(--available-height)---spacing(9)))] scroll-py-1 overflow-y-auto overscroll-contain p-1 data-empty:p-0",
143
+ className
144
+ )}
145
+ {...props}
146
+ />
147
+ )
148
+ }
149
+
150
+ function ComboboxItem({
151
+ className,
152
+ children,
153
+ ...props
154
+ }: ComboboxPrimitive.Item.Props) {
155
+ return (
156
+ <ComboboxPrimitive.Item
157
+ data-slot="combobox-item"
158
+ className={cn(
159
+ "relative flex min-h-7 w-full cursor-default items-center gap-2 rounded-md px-2 py-1 text-xs/relaxed outline-hidden select-none data-highlighted:bg-accent data-highlighted:text-accent-foreground not-data-[variant=destructive]:data-highlighted:**:text-accent-foreground data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-3.5",
160
+ className
161
+ )}
162
+ {...props}
163
+ >
164
+ {children}
165
+ <ComboboxPrimitive.ItemIndicator
166
+ render={
167
+ <span className="pointer-events-none absolute right-2 flex items-center justify-center" />
168
+ }
169
+ >
170
+ <CheckIcon className="pointer-events-none" />
171
+ </ComboboxPrimitive.ItemIndicator>
172
+ </ComboboxPrimitive.Item>
173
+ )
174
+ }
175
+
176
+ function ComboboxGroup({ className, ...props }: ComboboxPrimitive.Group.Props) {
177
+ return (
178
+ <ComboboxPrimitive.Group
179
+ data-slot="combobox-group"
180
+ className={cn(className)}
181
+ {...props}
182
+ />
183
+ )
184
+ }
185
+
186
+ function ComboboxLabel({
187
+ className,
188
+ ...props
189
+ }: ComboboxPrimitive.GroupLabel.Props) {
190
+ return (
191
+ <ComboboxPrimitive.GroupLabel
192
+ data-slot="combobox-label"
193
+ className={cn("px-2 py-1.5 text-xs text-muted-foreground", className)}
194
+ {...props}
195
+ />
196
+ )
197
+ }
198
+
199
+ function ComboboxCollection({ ...props }: ComboboxPrimitive.Collection.Props) {
200
+ return (
201
+ <ComboboxPrimitive.Collection data-slot="combobox-collection" {...props} />
202
+ )
203
+ }
204
+
205
+ function ComboboxEmpty({ className, ...props }: ComboboxPrimitive.Empty.Props) {
206
+ return (
207
+ <ComboboxPrimitive.Empty
208
+ data-slot="combobox-empty"
209
+ className={cn(
210
+ "hidden w-full justify-center py-2 text-center text-xs/relaxed text-muted-foreground group-data-empty/combobox-content:flex",
211
+ className
212
+ )}
213
+ {...props}
214
+ />
215
+ )
216
+ }
217
+
218
+ function ComboboxSeparator({
219
+ className,
220
+ ...props
221
+ }: ComboboxPrimitive.Separator.Props) {
222
+ return (
223
+ <ComboboxPrimitive.Separator
224
+ data-slot="combobox-separator"
225
+ className={cn("-mx-1 my-1 h-px bg-border/50", className)}
226
+ {...props}
227
+ />
228
+ )
229
+ }
230
+
231
+ function ComboboxChips({
232
+ className,
233
+ ...props
234
+ }: React.ComponentPropsWithRef<typeof ComboboxPrimitive.Chips> &
235
+ ComboboxPrimitive.Chips.Props) {
236
+ return (
237
+ <ComboboxPrimitive.Chips
238
+ data-slot="combobox-chips"
239
+ className={cn(
240
+ "flex min-h-7 flex-wrap items-center gap-1 rounded-md border border-input bg-input/20 bg-clip-padding px-2 py-0.5 text-xs/relaxed transition-colors focus-within:border-ring focus-within:ring-2 focus-within:ring-ring/30 has-aria-invalid:border-destructive has-aria-invalid:ring-2 has-aria-invalid:ring-destructive/20 has-data-[slot=combobox-chip]:px-1 dark:bg-input/30 dark:has-aria-invalid:border-destructive/50 dark:has-aria-invalid:ring-destructive/40",
241
+ className
242
+ )}
243
+ {...props}
244
+ />
245
+ )
246
+ }
247
+
248
+ function ComboboxChip({
249
+ className,
250
+ children,
251
+ showRemove = true,
252
+ ...props
253
+ }: ComboboxPrimitive.Chip.Props & {
254
+ showRemove?: boolean
255
+ }) {
256
+ return (
257
+ <ComboboxPrimitive.Chip
258
+ data-slot="combobox-chip"
259
+ className={cn(
260
+ "flex h-[calc(--spacing(4.75))] w-fit items-center justify-center gap-1 rounded-[calc(var(--radius-sm)-2px)] bg-muted-foreground/10 px-1.5 text-xs/relaxed font-medium whitespace-nowrap text-foreground has-disabled:pointer-events-none has-disabled:cursor-not-allowed has-disabled:opacity-50 has-data-[slot=combobox-chip-remove]:pr-0",
261
+ className
262
+ )}
263
+ {...props}
264
+ >
265
+ {children}
266
+ {showRemove && (
267
+ <ComboboxPrimitive.ChipRemove
268
+ render={<Button variant="ghost" size="icon-xs" />}
269
+ className="-ml-1 opacity-50 hover:opacity-100"
270
+ data-slot="combobox-chip-remove"
271
+ >
272
+ <XIcon className="pointer-events-none" />
273
+ </ComboboxPrimitive.ChipRemove>
274
+ )}
275
+ </ComboboxPrimitive.Chip>
276
+ )
277
+ }
278
+
279
+ function ComboboxChipsInput({
280
+ className,
281
+ ...props
282
+ }: ComboboxPrimitive.Input.Props) {
283
+ return (
284
+ <ComboboxPrimitive.Input
285
+ data-slot="combobox-chip-input"
286
+ className={cn("min-w-16 flex-1 outline-none", className)}
287
+ {...props}
288
+ />
289
+ )
290
+ }
291
+
292
+ export {
293
+ Combobox,
294
+ ComboboxInput,
295
+ ComboboxContent,
296
+ ComboboxList,
297
+ ComboboxItem,
298
+ ComboboxGroup,
299
+ ComboboxLabel,
300
+ ComboboxCollection,
301
+ ComboboxEmpty,
302
+ ComboboxSeparator,
303
+ ComboboxChips,
304
+ ComboboxChip,
305
+ ComboboxChipsInput,
306
+ ComboboxTrigger,
307
+ ComboboxValue,
308
+ }
@@ -0,0 +1,261 @@
1
+ import * as React from "react"
2
+ import { ContextMenu as ContextMenuPrimitive } from "radix-ui"
3
+
4
+ import { cn } from "@/lib/utils"
5
+ import { ChevronRightIcon, CheckIcon } from "lucide-react"
6
+
7
+ function ContextMenu({
8
+ ...props
9
+ }: React.ComponentProps<typeof ContextMenuPrimitive.Root>) {
10
+ return <ContextMenuPrimitive.Root data-slot="context-menu" {...props} />
11
+ }
12
+
13
+ function ContextMenuTrigger({
14
+ className,
15
+ ...props
16
+ }: React.ComponentProps<typeof ContextMenuPrimitive.Trigger>) {
17
+ return (
18
+ <ContextMenuPrimitive.Trigger
19
+ data-slot="context-menu-trigger"
20
+ className={cn("select-none", className)}
21
+ {...props}
22
+ />
23
+ )
24
+ }
25
+
26
+ function ContextMenuGroup({
27
+ ...props
28
+ }: React.ComponentProps<typeof ContextMenuPrimitive.Group>) {
29
+ return (
30
+ <ContextMenuPrimitive.Group data-slot="context-menu-group" {...props} />
31
+ )
32
+ }
33
+
34
+ function ContextMenuPortal({
35
+ ...props
36
+ }: React.ComponentProps<typeof ContextMenuPrimitive.Portal>) {
37
+ return (
38
+ <ContextMenuPrimitive.Portal data-slot="context-menu-portal" {...props} />
39
+ )
40
+ }
41
+
42
+ function ContextMenuSub({
43
+ ...props
44
+ }: React.ComponentProps<typeof ContextMenuPrimitive.Sub>) {
45
+ return <ContextMenuPrimitive.Sub data-slot="context-menu-sub" {...props} />
46
+ }
47
+
48
+ function ContextMenuRadioGroup({
49
+ ...props
50
+ }: React.ComponentProps<typeof ContextMenuPrimitive.RadioGroup>) {
51
+ return (
52
+ <ContextMenuPrimitive.RadioGroup
53
+ data-slot="context-menu-radio-group"
54
+ {...props}
55
+ />
56
+ )
57
+ }
58
+
59
+ function ContextMenuContent({
60
+ className,
61
+ ...props
62
+ }: React.ComponentProps<typeof ContextMenuPrimitive.Content> & {
63
+ side?: "top" | "right" | "bottom" | "left"
64
+ }) {
65
+ return (
66
+ <ContextMenuPrimitive.Portal>
67
+ <ContextMenuPrimitive.Content
68
+ data-slot="context-menu-content"
69
+ className={cn("z-50 max-h-(--radix-context-menu-content-available-height) min-w-32 origin-(--radix-context-menu-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-lg bg-popover p-1 text-popover-foreground shadow-md ring-1 ring-foreground/10 duration-100 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95", className )}
70
+ {...props}
71
+ />
72
+ </ContextMenuPrimitive.Portal>
73
+ )
74
+ }
75
+
76
+ function ContextMenuItem({
77
+ className,
78
+ inset,
79
+ variant = "default",
80
+ ...props
81
+ }: React.ComponentProps<typeof ContextMenuPrimitive.Item> & {
82
+ inset?: boolean
83
+ variant?: "default" | "destructive"
84
+ }) {
85
+ return (
86
+ <ContextMenuPrimitive.Item
87
+ data-slot="context-menu-item"
88
+ data-inset={inset}
89
+ data-variant={variant}
90
+ className={cn(
91
+ "group/context-menu-item relative flex min-h-7 cursor-default items-center gap-2 rounded-md px-2 py-1 text-xs/relaxed outline-hidden select-none focus:bg-accent focus:text-accent-foreground not-data-[variant=destructive]:focus:**:text-accent-foreground data-inset:pl-7.5 data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 data-[variant=destructive]:focus:text-destructive dark:data-[variant=destructive]:focus:bg-destructive/20 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-3.5 data-[variant=destructive]:*:[svg]:text-destructive",
92
+ className
93
+ )}
94
+ {...props}
95
+ />
96
+ )
97
+ }
98
+
99
+ function ContextMenuSubTrigger({
100
+ className,
101
+ inset,
102
+ children,
103
+ ...props
104
+ }: React.ComponentProps<typeof ContextMenuPrimitive.SubTrigger> & {
105
+ inset?: boolean
106
+ }) {
107
+ return (
108
+ <ContextMenuPrimitive.SubTrigger
109
+ data-slot="context-menu-sub-trigger"
110
+ data-inset={inset}
111
+ className={cn(
112
+ "flex min-h-7 cursor-default items-center gap-2 rounded-md px-2 py-1 text-xs outline-hidden select-none focus:bg-accent focus:text-accent-foreground not-data-[variant=destructive]:focus:**:text-accent-foreground data-inset:pl-7.5 data-open:bg-accent data-open:text-accent-foreground [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-3.5",
113
+ className
114
+ )}
115
+ {...props}
116
+ >
117
+ {children}
118
+ <ChevronRightIcon className="ml-auto" />
119
+ </ContextMenuPrimitive.SubTrigger>
120
+ )
121
+ }
122
+
123
+ function ContextMenuSubContent({
124
+ className,
125
+ ...props
126
+ }: React.ComponentProps<typeof ContextMenuPrimitive.SubContent>) {
127
+ return (
128
+ <ContextMenuPrimitive.SubContent
129
+ data-slot="context-menu-sub-content"
130
+ className={cn("z-50 min-w-32 origin-(--radix-context-menu-content-transform-origin) overflow-hidden rounded-lg bg-popover p-1 text-popover-foreground shadow-md ring-1 ring-foreground/10 duration-100 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95", className )}
131
+ {...props}
132
+ />
133
+ )
134
+ }
135
+
136
+ function ContextMenuCheckboxItem({
137
+ className,
138
+ children,
139
+ checked,
140
+ inset,
141
+ ...props
142
+ }: React.ComponentProps<typeof ContextMenuPrimitive.CheckboxItem> & {
143
+ inset?: boolean
144
+ }) {
145
+ return (
146
+ <ContextMenuPrimitive.CheckboxItem
147
+ data-slot="context-menu-checkbox-item"
148
+ data-inset={inset}
149
+ className={cn(
150
+ "relative flex min-h-7 cursor-default items-center gap-2 rounded-md py-1.5 pr-8 pl-2 text-xs outline-hidden select-none focus:bg-accent focus:text-accent-foreground focus:**:text-accent-foreground data-inset:pl-7.5 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-3.5",
151
+ className
152
+ )}
153
+ checked={checked}
154
+ {...props}
155
+ >
156
+ <span className="pointer-events-none absolute right-2 flex items-center justify-center">
157
+ <ContextMenuPrimitive.ItemIndicator>
158
+ <CheckIcon
159
+ />
160
+ </ContextMenuPrimitive.ItemIndicator>
161
+ </span>
162
+ {children}
163
+ </ContextMenuPrimitive.CheckboxItem>
164
+ )
165
+ }
166
+
167
+ function ContextMenuRadioItem({
168
+ className,
169
+ children,
170
+ inset,
171
+ ...props
172
+ }: React.ComponentProps<typeof ContextMenuPrimitive.RadioItem> & {
173
+ inset?: boolean
174
+ }) {
175
+ return (
176
+ <ContextMenuPrimitive.RadioItem
177
+ data-slot="context-menu-radio-item"
178
+ data-inset={inset}
179
+ className={cn(
180
+ "relative flex min-h-7 cursor-default items-center gap-2 rounded-md py-1.5 pr-8 pl-2 text-xs outline-hidden select-none focus:bg-accent focus:text-accent-foreground focus:**:text-accent-foreground data-inset:pl-7.5 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-3.5",
181
+ className
182
+ )}
183
+ {...props}
184
+ >
185
+ <span className="pointer-events-none absolute right-2 flex items-center justify-center">
186
+ <ContextMenuPrimitive.ItemIndicator>
187
+ <CheckIcon
188
+ />
189
+ </ContextMenuPrimitive.ItemIndicator>
190
+ </span>
191
+ {children}
192
+ </ContextMenuPrimitive.RadioItem>
193
+ )
194
+ }
195
+
196
+ function ContextMenuLabel({
197
+ className,
198
+ inset,
199
+ ...props
200
+ }: React.ComponentProps<typeof ContextMenuPrimitive.Label> & {
201
+ inset?: boolean
202
+ }) {
203
+ return (
204
+ <ContextMenuPrimitive.Label
205
+ data-slot="context-menu-label"
206
+ data-inset={inset}
207
+ className={cn(
208
+ "px-2 py-1.5 text-xs text-muted-foreground data-inset:pl-7.5",
209
+ className
210
+ )}
211
+ {...props}
212
+ />
213
+ )
214
+ }
215
+
216
+ function ContextMenuSeparator({
217
+ className,
218
+ ...props
219
+ }: React.ComponentProps<typeof ContextMenuPrimitive.Separator>) {
220
+ return (
221
+ <ContextMenuPrimitive.Separator
222
+ data-slot="context-menu-separator"
223
+ className={cn("-mx-1 my-1 h-px bg-border/50", className)}
224
+ {...props}
225
+ />
226
+ )
227
+ }
228
+
229
+ function ContextMenuShortcut({
230
+ className,
231
+ ...props
232
+ }: React.ComponentProps<"span">) {
233
+ return (
234
+ <span
235
+ data-slot="context-menu-shortcut"
236
+ className={cn(
237
+ "ml-auto text-[0.625rem] tracking-widest text-muted-foreground group-focus/context-menu-item:text-accent-foreground",
238
+ className
239
+ )}
240
+ {...props}
241
+ />
242
+ )
243
+ }
244
+
245
+ export {
246
+ ContextMenu,
247
+ ContextMenuTrigger,
248
+ ContextMenuContent,
249
+ ContextMenuItem,
250
+ ContextMenuCheckboxItem,
251
+ ContextMenuRadioItem,
252
+ ContextMenuLabel,
253
+ ContextMenuSeparator,
254
+ ContextMenuShortcut,
255
+ ContextMenuGroup,
256
+ ContextMenuPortal,
257
+ ContextMenuSub,
258
+ ContextMenuSubContent,
259
+ ContextMenuSubTrigger,
260
+ ContextMenuRadioGroup,
261
+ }