torch-glare 2.1.5 → 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.
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../cli/bin/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,GAAG,EAAE,MAAM,wBAAwB,CAAC;AAC7C,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AACrD,OAAO,EAAE,OAAO,EAAE,MAAM,yBAAyB,CAAC;AAClD,OAAO,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AACtD,OAAO,EAAE,OAAO,EAAE,MAAM,0BAA0B,CAAC;AACnD,OAAO,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAC1D,OAAO,EAAE,yBAAyB,EAAE,MAAM,2BAA2B,CAAC;AACtE,OAAO,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAElD,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,aAAa,CAAC;KACnB,WAAW,CAAC,2CAA2C,CAAC;KACxD,OAAO,CAAC,OAAO,CAAC,CAAC;AAEpB,OAAO;KACJ,OAAO,CAAC,MAAM,CAAC;KACf,WAAW,CAAC,0CAA0C,CAAC;KACvD,MAAM,CAAC,GAAG,EAAE,CAAC,UAAU,EAAE,CAAC,CAAC;AAE9B,OAAO;KACJ,OAAO,CAAC,iBAAiB,CAAC;KAC1B,WAAW,CAAC,0DAA0D,CAAC;KACvE,MAAM,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC;AAEzC,OAAO;KACJ,OAAO,CAAC,aAAa,CAAC;KACtB,WAAW,CAAC,qDAAqD,CAAC;KAClE,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,IAAI,GAAG,IAAI,EAAE,CAAC,CAAC,CAAC;AAEhD,OAAO;KACJ,OAAO,CAAC,iBAAiB,CAAC;KAC1B,WAAW,CAAC,uDAAuD,CAAC;KACpE,MAAM,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,SAAS,CAAC,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,CAAC,CAAC;AAE5D,OAAO;KACJ,OAAO,CAAC,aAAa,CAAC;KACtB,WAAW,CAAC,sDAAsD,CAAC;KACnE,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;AAEnC,OAAO;KACJ,OAAO,CAAC,qBAAqB,CAAC;KAC9B,WAAW,CAAC,yDAAyD,CAAC;KACtE,MAAM,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,WAAW,CAAC,QAAQ,IAAI,GAAG,QAAQ,EAAE,CAAC,CAAC,CAAC;AAEhE,OAAO;KACJ,OAAO,CAAC,QAAQ,CAAC;KACjB,WAAW,CAAC,6BAA6B,CAAC;KAC1C,MAAM,CAAC,GAAG,EAAE,CAAC,yBAAyB,EAAE,CAAC,CAAC;AAE7C,OAAO;KACJ,OAAO,CAAC,KAAK,CAAC;KACd,WAAW,CAAC,kDAAkD,CAAC;KAC/D,MAAM,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,CAAC;AAE5B,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../cli/bin/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,GAAG,EAAE,MAAM,wBAAwB,CAAC;AAC7C,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AACrD,OAAO,EAAE,OAAO,EAAE,MAAM,yBAAyB,CAAC;AAClD,OAAO,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AACtD,OAAO,EAAE,OAAO,EAAE,MAAM,0BAA0B,CAAC;AACnD,OAAO,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAC1D,OAAO,EAAE,yBAAyB,EAAE,MAAM,2BAA2B,CAAC;AACtE,OAAO,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAElD,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,aAAa,CAAC;KACnB,WAAW,CAAC,2CAA2C,CAAC;KACxD,OAAO,CAAC,OAAO,CAAC,CAAC;AAEpB,OAAO;KACJ,OAAO,CAAC,MAAM,CAAC;KACf,WAAW,CAAC,0CAA0C,CAAC;KACvD,MAAM,CAAC,GAAG,EAAE,CAAC,UAAU,EAAE,CAAC,CAAC;AAE9B,OAAO;KACJ,OAAO,CAAC,iBAAiB,CAAC;KAC1B,WAAW,CAAC,0DAA0D,CAAC;KACvE,MAAM,CAAC,aAAa,EAAE,8CAA8C,CAAC;KACrE,MAAM,CAAC,CAAC,SAAS,EAAE,OAAO,EAAE,EAAE,CAAC,GAAG,CAAC,SAAS,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC;AAEnE,OAAO;KACJ,OAAO,CAAC,aAAa,CAAC;KACtB,WAAW,CAAC,qDAAqD,CAAC;KAClE,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,IAAI,GAAG,IAAI,EAAE,CAAC,CAAC,CAAC;AAEhD,OAAO;KACJ,OAAO,CAAC,iBAAiB,CAAC;KAC1B,WAAW,CAAC,uDAAuD,CAAC;KACpE,MAAM,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,SAAS,CAAC,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,CAAC,CAAC;AAE5D,OAAO;KACJ,OAAO,CAAC,aAAa,CAAC;KACtB,WAAW,CAAC,sDAAsD,CAAC;KACnE,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;AAEnC,OAAO;KACJ,OAAO,CAAC,qBAAqB,CAAC;KAC9B,WAAW,CAAC,yDAAyD,CAAC;KACtE,MAAM,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,WAAW,CAAC,QAAQ,IAAI,GAAG,QAAQ,EAAE,CAAC,CAAC,CAAC;AAEhE,OAAO;KACJ,OAAO,CAAC,QAAQ,CAAC;KACjB,WAAW,CAAC,6BAA6B,CAAC;KAC1C,MAAM,CAAC,GAAG,EAAE,CAAC,yBAAyB,EAAE,CAAC,CAAC;AAE7C,OAAO;KACJ,OAAO,CAAC,KAAK,CAAC;KACd,WAAW,CAAC,kDAAkD,CAAC;KAC/D,MAAM,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,CAAC;AAE5B,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC"}
@@ -0,0 +1,455 @@
1
+ ---
2
+ title: ContextMenu
3
+ description: Right-click (or long-press) menu that opens at the pointer, with submenus, checkboxes, radio groups, and keyboard navigation
4
+ group: Overlays & Dialogs
5
+ keywords: [context-menu, right-click, menu, radix-ui, submenu, checkbox, contextmenu]
6
+ ---
7
+
8
+ # ContextMenu
9
+
10
+ > A right-click / long-press menu that opens at the pointer. Wrap any zone in a `ContextMenuTrigger` and the menu appears where the user clicks — same surface as DropdownMenu (items, groups, the boxed look, auto-grouping), built on `@radix-ui/react-context-menu`.
11
+
12
+ ## Installation
13
+
14
+ ```bash
15
+ npm install @radix-ui/react-context-menu
16
+ ```
17
+
18
+ ## Import
19
+
20
+ ```typescript
21
+ import {
22
+ ContextMenu,
23
+ ContextMenuTrigger,
24
+ ContextMenuContent,
25
+ ContextMenuItem,
26
+ ContextMenuGroup,
27
+ ContextMenuRadioGroup,
28
+ ContextMenuCheckboxItem,
29
+ ContextMenuRadioItem,
30
+ ContextMenuLabel,
31
+ ContextMenuShortcut,
32
+ ContextMenuSub,
33
+ ContextMenuSubTrigger,
34
+ ContextMenuSubContent,
35
+ ContextMenuPortal,
36
+ } from '@torch-ui/components'
37
+ ```
38
+
39
+ ## Quick Examples
40
+
41
+ ### Basic Menu
42
+
43
+ Wrap the right-click zone in `ContextMenuTrigger`. The menu opens at the pointer.
44
+
45
+ ```typescript
46
+ import { ContextMenu, ContextMenuTrigger, ContextMenuContent, ContextMenuItem } from '@torch-ui/components'
47
+
48
+ function Example() {
49
+ return (
50
+ <ContextMenu>
51
+ <ContextMenuTrigger asChild>
52
+ <div className="flex h-40 w-72 items-center justify-center rounded-md border border-dashed">
53
+ Right-click here
54
+ </div>
55
+ </ContextMenuTrigger>
56
+ <ContextMenuContent>
57
+ <ContextMenuItem>Profile</ContextMenuItem>
58
+ <ContextMenuItem>Settings</ContextMenuItem>
59
+ <ContextMenuItem>Logout</ContextMenuItem>
60
+ </ContextMenuContent>
61
+ </ContextMenu>
62
+ )
63
+ }
64
+ ```
65
+
66
+ ### With Icons, Shortcuts, and a Negative Item
67
+
68
+ ```typescript
69
+ import { ContextMenu, ContextMenuTrigger, ContextMenuContent, ContextMenuItem, ContextMenuShortcut } from '@torch-ui/components'
70
+
71
+ function ActionsMenu() {
72
+ return (
73
+ <ContextMenu>
74
+ <ContextMenuTrigger asChild>
75
+ <div className="flex h-40 w-72 items-center justify-center rounded-md border border-dashed">
76
+ Right-click the canvas
77
+ </div>
78
+ </ContextMenuTrigger>
79
+ <ContextMenuContent>
80
+ <ContextMenuItem>
81
+ <i className="ri-edit-line" />
82
+ <span>Edit</span>
83
+ <ContextMenuShortcut>⌘E</ContextMenuShortcut>
84
+ </ContextMenuItem>
85
+ <ContextMenuItem>
86
+ <i className="ri-share-line" />
87
+ <span>Share</span>
88
+ <ContextMenuShortcut>⌘⇧S</ContextMenuShortcut>
89
+ </ContextMenuItem>
90
+ <ContextMenuItem variant="Negative">
91
+ <i className="ri-delete-bin-line" />
92
+ <span>Delete</span>
93
+ <ContextMenuShortcut>⌫</ContextMenuShortcut>
94
+ </ContextMenuItem>
95
+ </ContextMenuContent>
96
+ </ContextMenu>
97
+ )
98
+ }
99
+ ```
100
+
101
+ ### With Checkboxes
102
+
103
+ > Clicking a checkbox item keeps the menu open — `onSelect` calls `preventDefault()` internally so Radix does not auto-close. Toggle several options without the menu dismissing.
104
+
105
+ ```typescript
106
+ import { ContextMenu, ContextMenuTrigger, ContextMenuContent, ContextMenuCheckboxItem } from '@torch-ui/components'
107
+ import { useState } from 'react'
108
+
109
+ function CheckboxMenu() {
110
+ const [showStatusBar, setShowStatusBar] = useState(true)
111
+ const [showActivityBar, setShowActivityBar] = useState(false)
112
+ const [showPanel, setShowPanel] = useState(false)
113
+
114
+ return (
115
+ <ContextMenu>
116
+ <ContextMenuTrigger asChild>
117
+ <div className="flex h-40 w-72 items-center justify-center rounded-md border border-dashed">
118
+ Right-click to toggle view
119
+ </div>
120
+ </ContextMenuTrigger>
121
+ <ContextMenuContent>
122
+ <ContextMenuCheckboxItem
123
+ checked={showStatusBar}
124
+ onCheckedChange={setShowStatusBar}
125
+ >
126
+ Status Bar
127
+ </ContextMenuCheckboxItem>
128
+ <ContextMenuCheckboxItem
129
+ checked={showActivityBar}
130
+ onCheckedChange={setShowActivityBar}
131
+ >
132
+ Activity Bar
133
+ </ContextMenuCheckboxItem>
134
+ <ContextMenuCheckboxItem
135
+ checked={showPanel}
136
+ onCheckedChange={setShowPanel}
137
+ >
138
+ Panel
139
+ </ContextMenuCheckboxItem>
140
+ </ContextMenuContent>
141
+ </ContextMenu>
142
+ )
143
+ }
144
+ ```
145
+
146
+ ### With Radio Group
147
+
148
+ > Like checkboxes, selecting a radio item keeps the menu open (`onSelect` `preventDefault` is built in).
149
+
150
+ ```typescript
151
+ import { ContextMenu, ContextMenuTrigger, ContextMenuContent, ContextMenuRadioGroup, ContextMenuRadioItem } from '@torch-ui/components'
152
+ import { useState } from 'react'
153
+
154
+ function RadioMenu() {
155
+ const [position, setPosition] = useState('bottom')
156
+
157
+ return (
158
+ <ContextMenu>
159
+ <ContextMenuTrigger asChild>
160
+ <div className="flex h-40 w-72 items-center justify-center rounded-md border border-dashed">
161
+ Right-click to pick a position
162
+ </div>
163
+ </ContextMenuTrigger>
164
+ <ContextMenuContent>
165
+ <ContextMenuRadioGroup value={position} onValueChange={setPosition}>
166
+ <ContextMenuRadioItem value="top">Top</ContextMenuRadioItem>
167
+ <ContextMenuRadioItem value="bottom">Bottom</ContextMenuRadioItem>
168
+ <ContextMenuRadioItem value="right">Right</ContextMenuRadioItem>
169
+ </ContextMenuRadioGroup>
170
+ </ContextMenuContent>
171
+ </ContextMenu>
172
+ )
173
+ }
174
+ ```
175
+
176
+ ### With Submenu
177
+
178
+ ```typescript
179
+ import { ContextMenu, ContextMenuTrigger, ContextMenuContent, ContextMenuItem, ContextMenuSub, ContextMenuSubTrigger, ContextMenuSubContent } from '@torch-ui/components'
180
+
181
+ function SubmenuExample() {
182
+ return (
183
+ <ContextMenu>
184
+ <ContextMenuTrigger asChild>
185
+ <div className="flex h-40 w-72 items-center justify-center rounded-md border border-dashed">
186
+ Right-click for more
187
+ </div>
188
+ </ContextMenuTrigger>
189
+ <ContextMenuContent>
190
+ <ContextMenuItem>New Tab</ContextMenuItem>
191
+ <ContextMenuItem>New Window</ContextMenuItem>
192
+
193
+ <ContextMenuSub>
194
+ <ContextMenuSubTrigger>More Tools</ContextMenuSubTrigger>
195
+ <ContextMenuSubContent>
196
+ <ContextMenuItem>Developer Tools</ContextMenuItem>
197
+ <ContextMenuItem>Task Manager</ContextMenuItem>
198
+ <ContextMenuItem>Extensions</ContextMenuItem>
199
+ </ContextMenuSubContent>
200
+ </ContextMenuSub>
201
+
202
+ <ContextMenuItem>Print</ContextMenuItem>
203
+ </ContextMenuContent>
204
+ </ContextMenu>
205
+ )
206
+ }
207
+ ```
208
+
209
+ ### RTL
210
+
211
+ Set `dir="rtl"` on the Root and the menu, items, and submenu arrows mirror automatically.
212
+
213
+ ```typescript
214
+ import { ContextMenu, ContextMenuTrigger, ContextMenuContent, ContextMenuItem, ContextMenuShortcut } from '@torch-ui/components'
215
+
216
+ function RtlMenu() {
217
+ return (
218
+ <ContextMenu dir="rtl">
219
+ <ContextMenuTrigger asChild>
220
+ <div className="flex h-40 w-72 items-center justify-center rounded-md border border-dashed">
221
+ انقر بزر الفأرة الأيمن
222
+ </div>
223
+ </ContextMenuTrigger>
224
+ <ContextMenuContent>
225
+ <ContextMenuItem>
226
+ تحرير
227
+ <ContextMenuShortcut>⌘E</ContextMenuShortcut>
228
+ </ContextMenuItem>
229
+ <ContextMenuItem variant="Negative">حذف</ContextMenuItem>
230
+ </ContextMenuContent>
231
+ </ContextMenu>
232
+ )
233
+ }
234
+ ```
235
+
236
+ ## API Reference
237
+
238
+ ### ContextMenu (Root)
239
+
240
+ A controlled wrapper around the Radix root. It tracks the open state internally (so a second right-click can dismiss the menu) while still forwarding `open` / `onOpenChange` when you control it.
241
+
242
+ | Prop | Type | Default | Description |
243
+ |------|------|---------|-------------|
244
+ | `open` | `boolean` | - | Controlled open state |
245
+ | `onOpenChange` | `(open: boolean) => void` | - | Callback when state changes |
246
+ | `dir` | `'ltr' \| 'rtl'` | - | Reading direction; mirrors layout and arrows |
247
+ | `modal` | `boolean` | `true` | Whether to block outside interactions |
248
+ | `children` | `React.ReactNode` | - | Trigger and content |
249
+
250
+ ### ContextMenuTrigger
251
+
252
+ The right-click zone. Wrap it around the element the menu should open from.
253
+
254
+ | Prop | Type | Default | Description |
255
+ |------|------|---------|-------------|
256
+ | `asChild` | `boolean` | `false` | Merge props onto the child element instead of rendering a wrapper |
257
+ | `disabled` | `boolean` | `false` | Disables opening on right-click |
258
+
259
+ ### ContextMenuContent
260
+
261
+ | Prop | Type | Default | Description |
262
+ |------|------|---------|-------------|
263
+ | `variant` | `'PresentationStyle'` | `'PresentationStyle'` | Visual style variant |
264
+ | `theme` | `'dark' \| 'light' \| 'default'` | - | Theme variant (applied as `data-theme`) |
265
+ | `className` | `string` | - | Additional CSS classes |
266
+ | `collisionPadding` | `number` | `8` | Min distance kept from the viewport edge |
267
+ | `autoGroup` | `boolean` | `true` | Auto-wrap loose items in a Boxed group (see Behavior notes) |
268
+
269
+ ### ContextMenuItem
270
+
271
+ | Prop | Type | Default | Description |
272
+ |------|------|---------|-------------|
273
+ | `variant` | `'Default' \| 'info' \| 'Negative'` | `'Default'` | Item style variant |
274
+ | `size` | `'S' \| 'M'` | `'M'` | Item size |
275
+ | `active` | `boolean` | `false` | Active (selected) state |
276
+ | `disabled` | `boolean` | `false` | Disabled state (still shows but is not selectable) |
277
+ | `onSelect` | `(event: Event) => void` | - | Select handler; closes the menu by default |
278
+
279
+ ### ContextMenuCheckboxItem
280
+
281
+ | Prop | Type | Default | Description |
282
+ |------|------|---------|-------------|
283
+ | `checked` | `boolean \| 'indeterminate'` | `false` | Checked state |
284
+ | `onCheckedChange` | `(checked: boolean) => void` | - | Change handler |
285
+ | `variant` | `'Default' \| 'info' \| 'Negative'` | `'Default'` | Style variant |
286
+ | `size` | `'S' \| 'M'` | `'M'` | Item size |
287
+
288
+ > Selecting a checkbox item keeps the menu open — `onSelect` `preventDefault` is built in.
289
+
290
+ ### ContextMenuRadioGroup
291
+
292
+ | Prop | Type | Default | Description |
293
+ |------|------|---------|-------------|
294
+ | `value` | `string` | - | Selected radio value |
295
+ | `onValueChange` | `(value: string) => void` | - | Change handler |
296
+ | `variant` | `'Boxed' \| 'Plain'` | `'Boxed'` | `Boxed` renders a bordered container; `Plain` is semantic grouping only |
297
+
298
+ ### ContextMenuRadioItem
299
+
300
+ | Prop | Type | Default | Description |
301
+ |------|------|---------|-------------|
302
+ | `value` | `string` | Required | Radio option value |
303
+ | `variant` | `'Default' \| 'info' \| 'Negative'` | `'Default'` | Style variant |
304
+ | `size` | `'S' \| 'M'` | `'M'` | Item size |
305
+
306
+ > Selecting a radio item keeps the menu open — `onSelect` `preventDefault` is built in.
307
+
308
+ ### ContextMenuSubTrigger
309
+
310
+ | Prop | Type | Default | Description |
311
+ |------|------|---------|-------------|
312
+ | `variant` | `'Default' \| 'info' \| 'Negative'` | `'Default'` | Style variant |
313
+ | `size` | `'S' \| 'M'` | `'M'` | Item size |
314
+ | `className` | `string` | - | Additional CSS classes |
315
+
316
+ Renders a trailing chevron (`ri-arrow-right-s-line`) that mirrors in RTL.
317
+
318
+ ### ContextMenuLabel
319
+
320
+ | Prop | Type | Default | Description |
321
+ |------|------|---------|-------------|
322
+ | `className` | `string` | - | Additional CSS classes |
323
+
324
+ A non-interactive section heading. Acts as a boundary for auto-grouping.
325
+
326
+ ### ContextMenuShortcut
327
+
328
+ | Prop | Type | Default | Description |
329
+ |------|------|---------|-------------|
330
+ | `className` | `string` | - | Additional CSS classes |
331
+
332
+ A right-aligned (RTL-aware) span for keyboard hints inside an item.
333
+
334
+ ## TypeScript
335
+
336
+ ### Key Interfaces
337
+
338
+ ```typescript
339
+ import * as ContextMenuPrimitive from '@radix-ui/react-context-menu'
340
+
341
+ // Root — controlled wrapper
342
+ type ContextMenuProps = React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.Root>
343
+ // { open?, onOpenChange?, dir?, modal?, children, ... }
344
+
345
+ export const ContextMenu: React.FC<ContextMenuProps>
346
+
347
+ // Content
348
+ interface ContextMenuContentProps {
349
+ variant?: 'PresentationStyle'
350
+ theme?: 'dark' | 'light' | 'default'
351
+ className?: string
352
+ collisionPadding?: number // default 8
353
+ autoGroup?: boolean // default true
354
+ }
355
+
356
+ export const ContextMenuContent: React.ForwardRefExoticComponent<ContextMenuContentProps>
357
+
358
+ // Item
359
+ interface ContextMenuItemProps {
360
+ variant?: 'Default' | 'info' | 'Negative'
361
+ size?: 'S' | 'M'
362
+ active?: boolean
363
+ disabled?: boolean
364
+ onSelect?: (event: Event) => void
365
+ }
366
+
367
+ export const ContextMenuItem: React.ForwardRefExoticComponent<ContextMenuItemProps>
368
+
369
+ // CheckboxItem
370
+ interface ContextMenuCheckboxItemProps {
371
+ checked?: boolean | 'indeterminate'
372
+ onCheckedChange?: (checked: boolean) => void
373
+ variant?: 'Default' | 'info' | 'Negative'
374
+ size?: 'S' | 'M'
375
+ }
376
+
377
+ export const ContextMenuCheckboxItem: React.ForwardRefExoticComponent<ContextMenuCheckboxItemProps>
378
+
379
+ // RadioGroup
380
+ interface ContextMenuRadioGroupProps {
381
+ value?: string
382
+ onValueChange?: (value: string) => void
383
+ variant?: 'Boxed' | 'Plain'
384
+ }
385
+
386
+ export const ContextMenuRadioGroup: React.ForwardRefExoticComponent<ContextMenuRadioGroupProps>
387
+
388
+ // RadioItem
389
+ interface ContextMenuRadioItemProps {
390
+ value: string
391
+ variant?: 'Default' | 'info' | 'Negative'
392
+ size?: 'S' | 'M'
393
+ }
394
+
395
+ export const ContextMenuRadioItem: React.ForwardRefExoticComponent<ContextMenuRadioItemProps>
396
+ ```
397
+
398
+ ## Behavior Notes
399
+
400
+ - **Opens at the pointer**: the menu opens on right-click (`contextmenu`) at the exact cursor position, not anchored to a fixed trigger button.
401
+ - **Second right-click closes it**: the Root is made controlled and tracks `open` in context. The Trigger listens in the capture phase, and when the menu is already open it `preventDefault()` / `stopPropagation()` and closes — so a second right-click dismisses instead of re-anchoring (which Radix handles unreliably).
402
+ - **Auto-grouping**: by default (`autoGroup` on `ContextMenuContent`, default `true`) consecutive loose items (`ContextMenuItem`, `ContextMenuCheckboxItem`, `ContextMenuRadioItem`, and `ContextMenuSub`) are automatically wrapped in a `Boxed` `ContextMenuGroup`, so they render inside a boxed container like DropdownMenu even when you do not write a group. Labels and explicit groups act as boundaries and pass through unchanged. Set `autoGroup={false}` to render children verbatim.
403
+ - **Checkbox / radio keep the menu open**: `ContextMenuCheckboxItem` and `ContextMenuRadioItem` call `event.preventDefault()` inside `onSelect`, stopping Radix's default auto-close so users can toggle multiple options in one pass.
404
+ - **Open-only animation**: only the open (enter) state animates (`fade-in`). There is intentionally no exit animation — holding the old DOM node during close breaks close/reposition on a second right-click, so it is omitted to keep repositioning reliable.
405
+ - **Submenus and RTL**: nested `ContextMenuSub` / `ContextMenuSubTrigger` / `ContextMenuSubContent` are supported, and `dir="rtl"` on the Root mirrors the layout (including the submenu chevron).
406
+
407
+ ## Accessibility
408
+
409
+ - **Keyboard Support**:
410
+ - Shift+F10 or the Menu (context) key: open the menu from the focused trigger
411
+ - Arrow Down / Arrow Up: move between items
412
+ - Arrow Right: open submenu (Arrow Left to close) — mirrored in RTL
413
+ - Enter / Space: select item
414
+ - Escape: close menu
415
+ - **Touch**: long-press on the trigger opens the menu on touch devices.
416
+ - **ARIA Attributes**: roles and states are applied automatically by Radix UI.
417
+ - **Focus Management**: focus is trapped within the open menu and restored on close.
418
+ - **Screen Readers**: menu structure, checked/selected states, and submenus are announced.
419
+
420
+ ## Best Practices
421
+
422
+ 1. **Use a clear right-click zone**
423
+ ```typescript
424
+ <ContextMenuTrigger asChild>
425
+ <div className="rounded-md border border-dashed">Right-click here</div>
426
+ </ContextMenuTrigger>
427
+ ```
428
+
429
+ 2. **Use labels to separate sections** — they also break auto-grouping into distinct boxed runs
430
+ ```typescript
431
+ <ContextMenuLabel>Edit</ContextMenuLabel>
432
+ ```
433
+
434
+ 3. **Show keyboard shortcuts**
435
+ ```typescript
436
+ <ContextMenuItem>
437
+ Save
438
+ <ContextMenuShortcut>⌘S</ContextMenuShortcut>
439
+ </ContextMenuItem>
440
+ ```
441
+
442
+ 4. **Use the Negative variant for destructive actions**
443
+ ```typescript
444
+ <ContextMenuItem variant="Negative">Delete</ContextMenuItem>
445
+ ```
446
+
447
+ 5. **Let checkbox/radio toggles stay open**: rely on the built-in behavior so users can adjust several settings without reopening.
448
+ 6. **Avoid deeply nested submenus**: 2 levels max.
449
+ 7. **Keep item labels concise**: short, action-oriented text.
450
+
451
+ ## Related Components
452
+
453
+ - [DropdownMenu](./dropdown-menu.md) - Button-anchored menu
454
+ - [Popover](./popover.md) - Non-menu popover
455
+ - [Select](./select.md) - Form select field
@@ -11,7 +11,22 @@ keywords: [data-views, layout, table, kanban, inbox, tree, multi-view, filter, s
11
11
 
12
12
  ## Installation
13
13
 
14
- The component is part of `torch-glare`. It depends on `@radix-ui/react-slider`, `react-day-picker`, `lucide-react`, and `vaul` (all already vendored by the library). No extra install needed.
14
+ ```bash
15
+ npx torch-glare@latest add DataViews
16
+ ```
17
+
18
+ The CLI transitively installs everything DataViews imports — the sibling views,
19
+ the `DataViewCard` layout, the `useDataViewsState` hook, the `dataViews` utils,
20
+ and the `TreeFolder` component — plus the 3rd-party deps it uses
21
+ (`@radix-ui/react-slider`, `react-day-picker`, `lucide-react`, `vaul`).
22
+
23
+ > **Badge version:** DataViews uses the current Badge API
24
+ > (`color` / `badgeStyle` / `showIcon`). If your project vendored an older
25
+ > `Badge.tsx` (with `variant` / `isSelected`), refresh it with
26
+ > `npx torch-glare@latest add Badge --force` and migrate call sites
27
+ > (`variant=` → `color=`, `isSelected`+`onUnselect` → `isClosable`+`onClose`).
28
+ > The Badge also needs `mapping-color-system-v4` tokens
29
+ > (`--background-presentation-badge-{color}-{subtle|solid}`) in your CSS.
15
30
 
16
31
  ## Import
17
32