@burtson-labs/ui 0.8.1 → 0.9.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/README.md +1 -1
- package/dist/components/context-menu.d.ts +30 -0
- package/dist/components/context-menu.js +131 -0
- package/dist/components/context-menu.js.map +1 -0
- package/dist/components/dropdown-menu.js +5 -6
- package/dist/components/dropdown-menu.js.map +1 -1
- package/dist/components/editor-tabs.d.ts +43 -0
- package/dist/components/editor-tabs.js +178 -0
- package/dist/components/editor-tabs.js.map +1 -0
- package/dist/components/menubar.d.ts +30 -0
- package/dist/components/menubar.js +140 -0
- package/dist/components/menubar.js.map +1 -0
- package/dist/components/onboarding-checklist.d.ts +26 -0
- package/dist/components/onboarding-checklist.js +106 -0
- package/dist/components/onboarding-checklist.js.map +1 -0
- package/dist/components/popover.d.ts +2 -0
- package/dist/components/popover.js +3 -1
- package/dist/components/popover.js.map +1 -1
- package/dist/components/resizable.d.ts +33 -0
- package/dist/components/resizable.js +54 -0
- package/dist/components/resizable.js.map +1 -0
- package/dist/components/tour.d.ts +96 -0
- package/dist/components/tour.js +367 -0
- package/dist/components/tour.js.map +1 -0
- package/dist/components/tree-view.d.ts +61 -0
- package/dist/components/tree-view.js +278 -0
- package/dist/components/tree-view.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +10 -3
- package/dist/styles.css +1 -1
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -58,7 +58,7 @@ npx shadcn@latest add https://ui.burtson.ai/r/button.json
|
|
|
58
58
|
|
|
59
59
|
## <picture><source media="(prefers-color-scheme: dark)" srcset="https://icons.burtson.ai/svg-white/panel-grid.svg"/><img src="https://icons.burtson.ai/svg-black/panel-grid.svg" align="center" alt=""/></picture> Components
|
|
60
60
|
|
|
61
|
-
Accordion · Alert · Alert Dialog · App Shell · Avatar · Badge · Breadcrumb · Button · Card · Checkbox · Collapsible · Combobox · Command · Copy Button · Dialog · Dropdown Menu · Empty State · Field · Icon Button · Input · Kbd · Label · Navigation Menu · Page Header · Pagination · Popover · Progress · Radio Group · Reasoning · Scroll Area · Secret Input · Select · Separator · Sheet · Skeleton · Slider · Spinner · Stat Card · Status · Steps · Switch · Table · Tabs · Textarea · Toast · Toaster · Toolbar · Tooltip
|
|
61
|
+
Accordion · Alert · Alert Dialog · App Shell · Avatar · Badge · Breadcrumb · Button · Card · Checkbox · Collapsible · Combobox · Command · Context Menu · Copy Button · Dialog · Dropdown Menu · Editor Tabs · Empty State · Field · Icon Button · Input · Kbd · Label · Menubar · Navigation Menu · Onboarding Checklist · Page Header · Pagination · Popover · Progress · Radio Group · Reasoning · Resizable · Scroll Area · Secret Input · Select · Separator · Sheet · Skeleton · Slider · Spinner · Stat Card · Status · Steps · Switch · Table · Tabs · Textarea · Toast · Toaster · Toolbar · Tooltip · Tour · Tree View
|
|
62
62
|
|
|
63
63
|
Live previews and code for each one are at [ui.burtson.ai](https://ui.burtson.ai/docs/components/button).
|
|
64
64
|
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { ContextMenu as ContextMenuPrimitive } from 'radix-ui';
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
/**
|
|
4
|
+
* A right-click menu. Wrap the target in ContextMenuTrigger (use asChild to keep
|
|
5
|
+
* your element); the menu opens at the pointer, and from the keyboard with the
|
|
6
|
+
* context-menu key or Shift+F10 on the focused target. Same rows as
|
|
7
|
+
* DropdownMenu, so a command can appear in both.
|
|
8
|
+
*/
|
|
9
|
+
declare function ContextMenu(props: React.ComponentProps<typeof ContextMenuPrimitive.Root>): React.JSX.Element;
|
|
10
|
+
declare function ContextMenuTrigger(props: React.ComponentProps<typeof ContextMenuPrimitive.Trigger>): React.JSX.Element;
|
|
11
|
+
declare function ContextMenuGroup(props: React.ComponentProps<typeof ContextMenuPrimitive.Group>): React.JSX.Element;
|
|
12
|
+
declare function ContextMenuContent({ className, ...props }: React.ComponentProps<typeof ContextMenuPrimitive.Content>): React.JSX.Element;
|
|
13
|
+
declare function ContextMenuItem({ className, inset, variant, ...props }: React.ComponentProps<typeof ContextMenuPrimitive.Item> & {
|
|
14
|
+
inset?: boolean;
|
|
15
|
+
variant?: 'default' | 'destructive';
|
|
16
|
+
}): React.JSX.Element;
|
|
17
|
+
declare function ContextMenuCheckboxItem({ className, children, checked, ...props }: React.ComponentProps<typeof ContextMenuPrimitive.CheckboxItem>): React.JSX.Element;
|
|
18
|
+
declare function ContextMenuRadioGroup(props: React.ComponentProps<typeof ContextMenuPrimitive.RadioGroup>): React.JSX.Element;
|
|
19
|
+
declare function ContextMenuRadioItem({ className, children, ...props }: React.ComponentProps<typeof ContextMenuPrimitive.RadioItem>): React.JSX.Element;
|
|
20
|
+
declare function ContextMenuLabel({ className, inset, ...props }: React.ComponentProps<typeof ContextMenuPrimitive.Label> & {
|
|
21
|
+
inset?: boolean;
|
|
22
|
+
}): React.JSX.Element;
|
|
23
|
+
declare function ContextMenuSeparator({ className, ...props }: React.ComponentProps<typeof ContextMenuPrimitive.Separator>): React.JSX.Element;
|
|
24
|
+
declare function ContextMenuShortcut({ className, ...props }: React.ComponentProps<'span'>): React.JSX.Element;
|
|
25
|
+
declare function ContextMenuSub(props: React.ComponentProps<typeof ContextMenuPrimitive.Sub>): React.JSX.Element;
|
|
26
|
+
declare function ContextMenuSubTrigger({ className, inset, children, ...props }: React.ComponentProps<typeof ContextMenuPrimitive.SubTrigger> & {
|
|
27
|
+
inset?: boolean;
|
|
28
|
+
}): React.JSX.Element;
|
|
29
|
+
declare function ContextMenuSubContent({ className, ...props }: React.ComponentProps<typeof ContextMenuPrimitive.SubContent>): React.JSX.Element;
|
|
30
|
+
export { ContextMenu, ContextMenuCheckboxItem, ContextMenuContent, ContextMenuGroup, ContextMenuItem, ContextMenuLabel, ContextMenuRadioGroup, ContextMenuRadioItem, ContextMenuSeparator, ContextMenuShortcut, ContextMenuSub, ContextMenuSubContent, ContextMenuSubTrigger, ContextMenuTrigger, };
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import { cn } from "../lib/utils.js";
|
|
2
|
+
import { menuItemClasses, surfaceClasses } from "./popover.js";
|
|
3
|
+
import { ContextMenu } from "radix-ui";
|
|
4
|
+
import "react";
|
|
5
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
6
|
+
import ChevronRight from "@burtson-labs/icons/react/chevron-right";
|
|
7
|
+
import Check from "@burtson-labs/icons/react/check";
|
|
8
|
+
//#region src/components/context-menu.tsx
|
|
9
|
+
/**
|
|
10
|
+
* A right-click menu. Wrap the target in ContextMenuTrigger (use asChild to keep
|
|
11
|
+
* your element); the menu opens at the pointer, and from the keyboard with the
|
|
12
|
+
* context-menu key or Shift+F10 on the focused target. Same rows as
|
|
13
|
+
* DropdownMenu, so a command can appear in both.
|
|
14
|
+
*/
|
|
15
|
+
function ContextMenu$1(props) {
|
|
16
|
+
return /* @__PURE__ */ jsx(ContextMenu.Root, {
|
|
17
|
+
"data-slot": "context-menu",
|
|
18
|
+
...props
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
function ContextMenuTrigger(props) {
|
|
22
|
+
return /* @__PURE__ */ jsx(ContextMenu.Trigger, {
|
|
23
|
+
"data-slot": "context-menu-trigger",
|
|
24
|
+
...props
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
function ContextMenuGroup(props) {
|
|
28
|
+
return /* @__PURE__ */ jsx(ContextMenu.Group, {
|
|
29
|
+
"data-slot": "context-menu-group",
|
|
30
|
+
...props
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
function ContextMenuContent({ className, ...props }) {
|
|
34
|
+
return /* @__PURE__ */ jsx(ContextMenu.Portal, { children: /* @__PURE__ */ jsx(ContextMenu.Content, {
|
|
35
|
+
"data-slot": "context-menu-content",
|
|
36
|
+
className: cn(surfaceClasses, "max-h-(--radix-context-menu-content-available-height) min-w-[8rem] origin-(--radix-context-menu-content-transform-origin) overflow-x-hidden overflow-y-auto p-1", className),
|
|
37
|
+
...props
|
|
38
|
+
}) });
|
|
39
|
+
}
|
|
40
|
+
function ContextMenuItem({ className, inset, variant = "default", ...props }) {
|
|
41
|
+
return /* @__PURE__ */ jsx(ContextMenu.Item, {
|
|
42
|
+
"data-slot": "context-menu-item",
|
|
43
|
+
"data-inset": inset || void 0,
|
|
44
|
+
"data-variant": variant,
|
|
45
|
+
className: cn(menuItemClasses, "data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 data-[variant=destructive]:*:[svg]:!text-destructive", className),
|
|
46
|
+
...props
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
function ContextMenuCheckboxItem({ className, children, checked, ...props }) {
|
|
50
|
+
return /* @__PURE__ */ jsxs(ContextMenu.CheckboxItem, {
|
|
51
|
+
"data-slot": "context-menu-checkbox-item",
|
|
52
|
+
className: cn(menuItemClasses, "pl-8", className),
|
|
53
|
+
checked,
|
|
54
|
+
...props,
|
|
55
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
56
|
+
className: "pointer-events-none absolute left-2 flex size-3.5 items-center justify-center",
|
|
57
|
+
children: /* @__PURE__ */ jsx(ContextMenu.ItemIndicator, { children: /* @__PURE__ */ jsx(Check, {
|
|
58
|
+
className: "size-4 text-foreground",
|
|
59
|
+
"aria-hidden": true
|
|
60
|
+
}) })
|
|
61
|
+
}), children]
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
function ContextMenuRadioGroup(props) {
|
|
65
|
+
return /* @__PURE__ */ jsx(ContextMenu.RadioGroup, {
|
|
66
|
+
"data-slot": "context-menu-radio-group",
|
|
67
|
+
...props
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
function ContextMenuRadioItem({ className, children, ...props }) {
|
|
71
|
+
return /* @__PURE__ */ jsxs(ContextMenu.RadioItem, {
|
|
72
|
+
"data-slot": "context-menu-radio-item",
|
|
73
|
+
className: cn(menuItemClasses, "pl-8", className),
|
|
74
|
+
...props,
|
|
75
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
76
|
+
className: "pointer-events-none absolute left-2 flex size-3.5 items-center justify-center",
|
|
77
|
+
children: /* @__PURE__ */ jsx(ContextMenu.ItemIndicator, { children: /* @__PURE__ */ jsx("span", { className: "block size-2 rounded-full bg-foreground" }) })
|
|
78
|
+
}), children]
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
function ContextMenuLabel({ className, inset, ...props }) {
|
|
82
|
+
return /* @__PURE__ */ jsx(ContextMenu.Label, {
|
|
83
|
+
"data-slot": "context-menu-label",
|
|
84
|
+
"data-inset": inset || void 0,
|
|
85
|
+
className: cn("px-2 pt-2 pb-1 text-[11px] font-semibold tracking-[0.08em] text-muted-foreground uppercase data-[inset]:pl-8", className),
|
|
86
|
+
...props
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
function ContextMenuSeparator({ className, ...props }) {
|
|
90
|
+
return /* @__PURE__ */ jsx(ContextMenu.Separator, {
|
|
91
|
+
"data-slot": "context-menu-separator",
|
|
92
|
+
className: cn("-mx-1 my-1 h-px bg-border", className),
|
|
93
|
+
...props
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
function ContextMenuShortcut({ className, ...props }) {
|
|
97
|
+
return /* @__PURE__ */ jsx("span", {
|
|
98
|
+
"data-slot": "context-menu-shortcut",
|
|
99
|
+
className: cn("ml-auto text-xs tracking-widest text-muted-foreground", className),
|
|
100
|
+
...props
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
function ContextMenuSub(props) {
|
|
104
|
+
return /* @__PURE__ */ jsx(ContextMenu.Sub, {
|
|
105
|
+
"data-slot": "context-menu-sub",
|
|
106
|
+
...props
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
function ContextMenuSubTrigger({ className, inset, children, ...props }) {
|
|
110
|
+
return /* @__PURE__ */ jsxs(ContextMenu.SubTrigger, {
|
|
111
|
+
"data-slot": "context-menu-sub-trigger",
|
|
112
|
+
"data-inset": inset || void 0,
|
|
113
|
+
className: cn(menuItemClasses, "data-[state=open]:bg-muted", className),
|
|
114
|
+
...props,
|
|
115
|
+
children: [children, /* @__PURE__ */ jsx(ChevronRight, {
|
|
116
|
+
className: "ml-auto size-4",
|
|
117
|
+
"aria-hidden": true
|
|
118
|
+
})]
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
function ContextMenuSubContent({ className, ...props }) {
|
|
122
|
+
return /* @__PURE__ */ jsx(ContextMenu.Portal, { children: /* @__PURE__ */ jsx(ContextMenu.SubContent, {
|
|
123
|
+
"data-slot": "context-menu-sub-content",
|
|
124
|
+
className: cn(surfaceClasses, "min-w-[8rem] origin-(--radix-context-menu-content-transform-origin) overflow-hidden p-1", className),
|
|
125
|
+
...props
|
|
126
|
+
}) });
|
|
127
|
+
}
|
|
128
|
+
//#endregion
|
|
129
|
+
export { ContextMenu$1 as ContextMenu, ContextMenuCheckboxItem, ContextMenuContent, ContextMenuGroup, ContextMenuItem, ContextMenuLabel, ContextMenuRadioGroup, ContextMenuRadioItem, ContextMenuSeparator, ContextMenuShortcut, ContextMenuSub, ContextMenuSubContent, ContextMenuSubTrigger, ContextMenuTrigger };
|
|
130
|
+
|
|
131
|
+
//# sourceMappingURL=context-menu.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context-menu.js","names":["ContextMenu","ContextMenuPrimitive","itemClasses"],"sources":["../../src/components/context-menu.tsx"],"sourcesContent":["import Check from '@burtson-labs/icons/react/check';\nimport ChevronRight from '@burtson-labs/icons/react/chevron-right';\nimport { ContextMenu as ContextMenuPrimitive } from 'radix-ui';\nimport * as React from 'react';\n\nimport { cn } from '../lib/utils';\n\nimport { menuItemClasses as itemClasses, surfaceClasses } from './popover';\n\n/**\n * A right-click menu. Wrap the target in ContextMenuTrigger (use asChild to keep\n * your element); the menu opens at the pointer, and from the keyboard with the\n * context-menu key or Shift+F10 on the focused target. Same rows as\n * DropdownMenu, so a command can appear in both.\n */\nfunction ContextMenu(props: React.ComponentProps<typeof ContextMenuPrimitive.Root>) {\n return <ContextMenuPrimitive.Root data-slot=\"context-menu\" {...props} />;\n}\n\nfunction ContextMenuTrigger(props: React.ComponentProps<typeof ContextMenuPrimitive.Trigger>) {\n return <ContextMenuPrimitive.Trigger data-slot=\"context-menu-trigger\" {...props} />;\n}\n\nfunction ContextMenuGroup(props: React.ComponentProps<typeof ContextMenuPrimitive.Group>) {\n return <ContextMenuPrimitive.Group data-slot=\"context-menu-group\" {...props} />;\n}\n\nfunction ContextMenuContent({\n className,\n ...props\n}: React.ComponentProps<typeof ContextMenuPrimitive.Content>) {\n return (\n <ContextMenuPrimitive.Portal>\n <ContextMenuPrimitive.Content\n data-slot=\"context-menu-content\"\n className={cn(\n surfaceClasses,\n 'max-h-(--radix-context-menu-content-available-height) min-w-[8rem] origin-(--radix-context-menu-content-transform-origin) overflow-x-hidden overflow-y-auto p-1',\n className,\n )}\n {...props}\n />\n </ContextMenuPrimitive.Portal>\n );\n}\n\nfunction ContextMenuItem({\n className,\n inset,\n variant = 'default',\n ...props\n}: React.ComponentProps<typeof ContextMenuPrimitive.Item> & {\n inset?: boolean;\n variant?: 'default' | 'destructive';\n}) {\n return (\n <ContextMenuPrimitive.Item\n data-slot=\"context-menu-item\"\n data-inset={inset || undefined}\n data-variant={variant}\n className={cn(\n itemClasses,\n 'data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 data-[variant=destructive]:*:[svg]:!text-destructive',\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction ContextMenuCheckboxItem({\n className,\n children,\n checked,\n ...props\n}: React.ComponentProps<typeof ContextMenuPrimitive.CheckboxItem>) {\n return (\n <ContextMenuPrimitive.CheckboxItem\n data-slot=\"context-menu-checkbox-item\"\n className={cn(itemClasses, 'pl-8', className)}\n checked={checked}\n {...props}\n >\n <span className=\"pointer-events-none absolute left-2 flex size-3.5 items-center justify-center\">\n <ContextMenuPrimitive.ItemIndicator>\n <Check className=\"size-4 text-foreground\" aria-hidden />\n </ContextMenuPrimitive.ItemIndicator>\n </span>\n {children}\n </ContextMenuPrimitive.CheckboxItem>\n );\n}\n\nfunction ContextMenuRadioGroup(\n props: React.ComponentProps<typeof ContextMenuPrimitive.RadioGroup>,\n) {\n return <ContextMenuPrimitive.RadioGroup data-slot=\"context-menu-radio-group\" {...props} />;\n}\n\nfunction ContextMenuRadioItem({\n className,\n children,\n ...props\n}: React.ComponentProps<typeof ContextMenuPrimitive.RadioItem>) {\n return (\n <ContextMenuPrimitive.RadioItem\n data-slot=\"context-menu-radio-item\"\n className={cn(itemClasses, 'pl-8', className)}\n {...props}\n >\n <span className=\"pointer-events-none absolute left-2 flex size-3.5 items-center justify-center\">\n <ContextMenuPrimitive.ItemIndicator>\n <span className=\"block size-2 rounded-full bg-foreground\" />\n </ContextMenuPrimitive.ItemIndicator>\n </span>\n {children}\n </ContextMenuPrimitive.RadioItem>\n );\n}\n\nfunction ContextMenuLabel({\n className,\n inset,\n ...props\n}: React.ComponentProps<typeof ContextMenuPrimitive.Label> & { inset?: boolean }) {\n return (\n <ContextMenuPrimitive.Label\n data-slot=\"context-menu-label\"\n data-inset={inset || undefined}\n className={cn(\n 'px-2 pt-2 pb-1 text-[11px] font-semibold tracking-[0.08em] text-muted-foreground uppercase data-[inset]:pl-8',\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction ContextMenuSeparator({\n className,\n ...props\n}: React.ComponentProps<typeof ContextMenuPrimitive.Separator>) {\n return (\n <ContextMenuPrimitive.Separator\n data-slot=\"context-menu-separator\"\n className={cn('-mx-1 my-1 h-px bg-border', className)}\n {...props}\n />\n );\n}\n\nfunction ContextMenuShortcut({ className, ...props }: React.ComponentProps<'span'>) {\n return (\n <span\n data-slot=\"context-menu-shortcut\"\n className={cn('ml-auto text-xs tracking-widest text-muted-foreground', className)}\n {...props}\n />\n );\n}\n\nfunction ContextMenuSub(props: React.ComponentProps<typeof ContextMenuPrimitive.Sub>) {\n return <ContextMenuPrimitive.Sub data-slot=\"context-menu-sub\" {...props} />;\n}\n\nfunction ContextMenuSubTrigger({\n className,\n inset,\n children,\n ...props\n}: React.ComponentProps<typeof ContextMenuPrimitive.SubTrigger> & { inset?: boolean }) {\n return (\n <ContextMenuPrimitive.SubTrigger\n data-slot=\"context-menu-sub-trigger\"\n data-inset={inset || undefined}\n className={cn(itemClasses, 'data-[state=open]:bg-muted', className)}\n {...props}\n >\n {children}\n <ChevronRight className=\"ml-auto size-4\" aria-hidden />\n </ContextMenuPrimitive.SubTrigger>\n );\n}\n\nfunction ContextMenuSubContent({\n className,\n ...props\n}: React.ComponentProps<typeof ContextMenuPrimitive.SubContent>) {\n return (\n <ContextMenuPrimitive.Portal>\n <ContextMenuPrimitive.SubContent\n data-slot=\"context-menu-sub-content\"\n className={cn(\n surfaceClasses,\n 'min-w-[8rem] origin-(--radix-context-menu-content-transform-origin) overflow-hidden p-1',\n className,\n )}\n {...props}\n />\n </ContextMenuPrimitive.Portal>\n );\n}\n\nexport {\n ContextMenu,\n ContextMenuCheckboxItem,\n ContextMenuContent,\n ContextMenuGroup,\n ContextMenuItem,\n ContextMenuLabel,\n ContextMenuRadioGroup,\n ContextMenuRadioItem,\n ContextMenuSeparator,\n ContextMenuShortcut,\n ContextMenuSub,\n ContextMenuSubContent,\n ContextMenuSubTrigger,\n ContextMenuTrigger,\n};\n"],"mappings":"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"}
|
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
import { cn } from "../lib/utils.js";
|
|
2
|
-
import { surfaceClasses } from "./popover.js";
|
|
2
|
+
import { menuItemClasses, surfaceClasses } from "./popover.js";
|
|
3
3
|
import { DropdownMenu } from "radix-ui";
|
|
4
4
|
import "react";
|
|
5
5
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
6
6
|
import ChevronRight from "@burtson-labs/icons/react/chevron-right";
|
|
7
7
|
import Check from "@burtson-labs/icons/react/check";
|
|
8
8
|
//#region src/components/dropdown-menu.tsx
|
|
9
|
-
var itemClasses = "relative flex min-h-8 cursor-default items-center gap-2 rounded-sm px-2 text-[13px] outline-hidden select-none focus:bg-muted focus:text-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50 data-[inset]:pl-8 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 [&_svg:not([class*='text-'])]:text-muted-foreground";
|
|
10
9
|
function DropdownMenu$1(props) {
|
|
11
10
|
return /* @__PURE__ */ jsx(DropdownMenu.Root, {
|
|
12
11
|
"data-slot": "dropdown-menu",
|
|
@@ -38,14 +37,14 @@ function DropdownMenuItem({ className, inset, variant = "default", ...props }) {
|
|
|
38
37
|
"data-slot": "dropdown-menu-item",
|
|
39
38
|
"data-inset": inset || void 0,
|
|
40
39
|
"data-variant": variant,
|
|
41
|
-
className: cn(
|
|
40
|
+
className: cn(menuItemClasses, "data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 data-[variant=destructive]:*:[svg]:!text-destructive", className),
|
|
42
41
|
...props
|
|
43
42
|
});
|
|
44
43
|
}
|
|
45
44
|
function DropdownMenuCheckboxItem({ className, children, checked, ...props }) {
|
|
46
45
|
return /* @__PURE__ */ jsxs(DropdownMenu.CheckboxItem, {
|
|
47
46
|
"data-slot": "dropdown-menu-checkbox-item",
|
|
48
|
-
className: cn(
|
|
47
|
+
className: cn(menuItemClasses, "pl-8", className),
|
|
49
48
|
checked,
|
|
50
49
|
...props,
|
|
51
50
|
children: [/* @__PURE__ */ jsx("span", {
|
|
@@ -66,7 +65,7 @@ function DropdownMenuRadioGroup(props) {
|
|
|
66
65
|
function DropdownMenuRadioItem({ className, children, ...props }) {
|
|
67
66
|
return /* @__PURE__ */ jsxs(DropdownMenu.RadioItem, {
|
|
68
67
|
"data-slot": "dropdown-menu-radio-item",
|
|
69
|
-
className: cn(
|
|
68
|
+
className: cn(menuItemClasses, "pl-8", className),
|
|
70
69
|
...props,
|
|
71
70
|
children: [/* @__PURE__ */ jsx("span", {
|
|
72
71
|
className: "pointer-events-none absolute left-2 flex size-3.5 items-center justify-center",
|
|
@@ -106,7 +105,7 @@ function DropdownMenuSubTrigger({ className, inset, children, ...props }) {
|
|
|
106
105
|
return /* @__PURE__ */ jsxs(DropdownMenu.SubTrigger, {
|
|
107
106
|
"data-slot": "dropdown-menu-sub-trigger",
|
|
108
107
|
"data-inset": inset || void 0,
|
|
109
|
-
className: cn(
|
|
108
|
+
className: cn(menuItemClasses, "data-[state=open]:bg-muted", className),
|
|
110
109
|
...props,
|
|
111
110
|
children: [children, /* @__PURE__ */ jsx(ChevronRight, {
|
|
112
111
|
className: "ml-auto size-4",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dropdown-menu.js","names":["DropdownMenu","DropdownMenuPrimitive"],"sources":["../../src/components/dropdown-menu.tsx"],"sourcesContent":["import Check from '@burtson-labs/icons/react/check';\nimport ChevronRight from '@burtson-labs/icons/react/chevron-right';\nimport { DropdownMenu as DropdownMenuPrimitive } from 'radix-ui';\nimport * as React from 'react';\n\nimport { cn } from '../lib/utils';\n\nimport { surfaceClasses } from './popover';\n\
|
|
1
|
+
{"version":3,"file":"dropdown-menu.js","names":["DropdownMenu","DropdownMenuPrimitive","itemClasses"],"sources":["../../src/components/dropdown-menu.tsx"],"sourcesContent":["import Check from '@burtson-labs/icons/react/check';\nimport ChevronRight from '@burtson-labs/icons/react/chevron-right';\nimport { DropdownMenu as DropdownMenuPrimitive } from 'radix-ui';\nimport * as React from 'react';\n\nimport { cn } from '../lib/utils';\n\nimport { menuItemClasses as itemClasses, surfaceClasses } from './popover';\n\nfunction DropdownMenu(props: React.ComponentProps<typeof DropdownMenuPrimitive.Root>) {\n return <DropdownMenuPrimitive.Root data-slot=\"dropdown-menu\" {...props} />;\n}\n\nfunction DropdownMenuTrigger(props: React.ComponentProps<typeof DropdownMenuPrimitive.Trigger>) {\n return <DropdownMenuPrimitive.Trigger data-slot=\"dropdown-menu-trigger\" {...props} />;\n}\n\nfunction DropdownMenuGroup(props: React.ComponentProps<typeof DropdownMenuPrimitive.Group>) {\n return <DropdownMenuPrimitive.Group data-slot=\"dropdown-menu-group\" {...props} />;\n}\n\nfunction DropdownMenuContent({\n className,\n sideOffset = 4,\n ...props\n}: React.ComponentProps<typeof DropdownMenuPrimitive.Content>) {\n return (\n <DropdownMenuPrimitive.Portal>\n <DropdownMenuPrimitive.Content\n data-slot=\"dropdown-menu-content\"\n sideOffset={sideOffset}\n className={cn(\n surfaceClasses,\n 'max-h-(--radix-dropdown-menu-content-available-height) min-w-[8rem] origin-(--radix-dropdown-menu-content-transform-origin) overflow-x-hidden overflow-y-auto p-1',\n className,\n )}\n {...props}\n />\n </DropdownMenuPrimitive.Portal>\n );\n}\n\nfunction DropdownMenuItem({\n className,\n inset,\n variant = 'default',\n ...props\n}: React.ComponentProps<typeof DropdownMenuPrimitive.Item> & {\n inset?: boolean;\n variant?: 'default' | 'destructive';\n}) {\n return (\n <DropdownMenuPrimitive.Item\n data-slot=\"dropdown-menu-item\"\n data-inset={inset || undefined}\n data-variant={variant}\n className={cn(\n itemClasses,\n 'data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 data-[variant=destructive]:*:[svg]:!text-destructive',\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction DropdownMenuCheckboxItem({\n className,\n children,\n checked,\n ...props\n}: React.ComponentProps<typeof DropdownMenuPrimitive.CheckboxItem>) {\n return (\n <DropdownMenuPrimitive.CheckboxItem\n data-slot=\"dropdown-menu-checkbox-item\"\n className={cn(itemClasses, 'pl-8', className)}\n checked={checked}\n {...props}\n >\n <span className=\"pointer-events-none absolute left-2 flex size-3.5 items-center justify-center\">\n <DropdownMenuPrimitive.ItemIndicator>\n <Check className=\"size-4 text-foreground\" aria-hidden />\n </DropdownMenuPrimitive.ItemIndicator>\n </span>\n {children}\n </DropdownMenuPrimitive.CheckboxItem>\n );\n}\n\nfunction DropdownMenuRadioGroup(\n props: React.ComponentProps<typeof DropdownMenuPrimitive.RadioGroup>,\n) {\n return <DropdownMenuPrimitive.RadioGroup data-slot=\"dropdown-menu-radio-group\" {...props} />;\n}\n\nfunction DropdownMenuRadioItem({\n className,\n children,\n ...props\n}: React.ComponentProps<typeof DropdownMenuPrimitive.RadioItem>) {\n return (\n <DropdownMenuPrimitive.RadioItem\n data-slot=\"dropdown-menu-radio-item\"\n className={cn(itemClasses, 'pl-8', className)}\n {...props}\n >\n <span className=\"pointer-events-none absolute left-2 flex size-3.5 items-center justify-center\">\n <DropdownMenuPrimitive.ItemIndicator>\n <span className=\"block size-2 rounded-full bg-foreground\" />\n </DropdownMenuPrimitive.ItemIndicator>\n </span>\n {children}\n </DropdownMenuPrimitive.RadioItem>\n );\n}\n\nfunction DropdownMenuLabel({\n className,\n inset,\n ...props\n}: React.ComponentProps<typeof DropdownMenuPrimitive.Label> & { inset?: boolean }) {\n return (\n <DropdownMenuPrimitive.Label\n data-slot=\"dropdown-menu-label\"\n data-inset={inset || undefined}\n className={cn(\n 'px-2 pt-2 pb-1 text-[11px] font-semibold tracking-[0.08em] text-muted-foreground uppercase data-[inset]:pl-8',\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction DropdownMenuSeparator({\n className,\n ...props\n}: React.ComponentProps<typeof DropdownMenuPrimitive.Separator>) {\n return (\n <DropdownMenuPrimitive.Separator\n data-slot=\"dropdown-menu-separator\"\n className={cn('-mx-1 my-1 h-px bg-border', className)}\n {...props}\n />\n );\n}\n\nfunction DropdownMenuShortcut({ className, ...props }: React.ComponentProps<'span'>) {\n return (\n <span\n data-slot=\"dropdown-menu-shortcut\"\n className={cn('ml-auto text-xs tracking-widest text-muted-foreground', className)}\n {...props}\n />\n );\n}\n\nfunction DropdownMenuSub(props: React.ComponentProps<typeof DropdownMenuPrimitive.Sub>) {\n return <DropdownMenuPrimitive.Sub data-slot=\"dropdown-menu-sub\" {...props} />;\n}\n\nfunction DropdownMenuSubTrigger({\n className,\n inset,\n children,\n ...props\n}: React.ComponentProps<typeof DropdownMenuPrimitive.SubTrigger> & { inset?: boolean }) {\n return (\n <DropdownMenuPrimitive.SubTrigger\n data-slot=\"dropdown-menu-sub-trigger\"\n data-inset={inset || undefined}\n className={cn(itemClasses, 'data-[state=open]:bg-muted', className)}\n {...props}\n >\n {children}\n <ChevronRight className=\"ml-auto size-4\" aria-hidden />\n </DropdownMenuPrimitive.SubTrigger>\n );\n}\n\nfunction DropdownMenuSubContent({\n className,\n ...props\n}: React.ComponentProps<typeof DropdownMenuPrimitive.SubContent>) {\n return (\n <DropdownMenuPrimitive.Portal>\n <DropdownMenuPrimitive.SubContent\n data-slot=\"dropdown-menu-sub-content\"\n className={cn(\n surfaceClasses,\n 'min-w-[8rem] origin-(--radix-dropdown-menu-content-transform-origin) overflow-hidden p-1',\n className,\n )}\n {...props}\n />\n </DropdownMenuPrimitive.Portal>\n );\n}\n\nexport {\n DropdownMenu,\n DropdownMenuCheckboxItem,\n DropdownMenuContent,\n DropdownMenuGroup,\n DropdownMenuItem,\n DropdownMenuLabel,\n DropdownMenuRadioGroup,\n DropdownMenuRadioItem,\n DropdownMenuSeparator,\n DropdownMenuShortcut,\n DropdownMenuSub,\n DropdownMenuSubContent,\n DropdownMenuSubTrigger,\n DropdownMenuTrigger,\n};\n"],"mappings":"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"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
export interface EditorTab {
|
|
3
|
+
/** Stable identity, usually the file path. */
|
|
4
|
+
id: string;
|
|
5
|
+
label: string;
|
|
6
|
+
/** Full path or context; the tooltip and the accessible description. */
|
|
7
|
+
description?: string;
|
|
8
|
+
icon?: React.ReactNode;
|
|
9
|
+
/** Unsaved changes: a dot replaces the close button until hover. */
|
|
10
|
+
dirty?: boolean;
|
|
11
|
+
/** Default true. */
|
|
12
|
+
closeable?: boolean;
|
|
13
|
+
/** A preview tab that the next opened file replaces; shown in italics. */
|
|
14
|
+
preview?: boolean;
|
|
15
|
+
/** The id of the panel this tab shows, for aria-controls. */
|
|
16
|
+
controls?: string;
|
|
17
|
+
}
|
|
18
|
+
export interface EditorTabsProps extends Omit<React.ComponentProps<'div'>, 'children' | 'aria-label'> {
|
|
19
|
+
tabs: EditorTab[];
|
|
20
|
+
activeId: string | null;
|
|
21
|
+
onActiveChange: (id: string) => void;
|
|
22
|
+
/**
|
|
23
|
+
* A request to close. The component never removes a tab itself: for a dirty
|
|
24
|
+
* tab, ask the person (save, discard, cancel) and then update `tabs`.
|
|
25
|
+
*/
|
|
26
|
+
onClose?: (id: string) => void;
|
|
27
|
+
/** Reorder by drag or Ctrl+Shift+PageUp/PageDown. `toIndex` is the new position. */
|
|
28
|
+
onMove?: (id: string, toIndex: number) => void;
|
|
29
|
+
/** Required: e.g. "Open editors". */
|
|
30
|
+
'aria-label': string;
|
|
31
|
+
/** Right-hand slot for split, more and similar buttons. */
|
|
32
|
+
actions?: React.ReactNode;
|
|
33
|
+
/** Right-click on a tab. */
|
|
34
|
+
onTabContextMenu?: (id: string, event: React.MouseEvent) => void;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* The strip of open files above an editor. One tab stop; Left/Right/Home/End
|
|
38
|
+
* move focus, Enter or Space opens, Delete asks to close, Ctrl+Shift+PageUp
|
|
39
|
+
* and PageDown move the tab. Middle-click closes. The strip scrolls when the
|
|
40
|
+
* tabs overflow and keeps the active tab in view.
|
|
41
|
+
*/
|
|
42
|
+
declare function EditorTabs({ tabs, activeId, onActiveChange, onClose, onMove, actions, onTabContextMenu, className, 'aria-label': ariaLabel, ...props }: EditorTabsProps): React.JSX.Element;
|
|
43
|
+
export { EditorTabs };
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
import { cn } from "../lib/utils.js";
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
4
|
+
import X from "@burtson-labs/icons/react/x";
|
|
5
|
+
//#region src/components/editor-tabs.tsx
|
|
6
|
+
/**
|
|
7
|
+
* The strip of open files above an editor. One tab stop; Left/Right/Home/End
|
|
8
|
+
* move focus, Enter or Space opens, Delete asks to close, Ctrl+Shift+PageUp
|
|
9
|
+
* and PageDown move the tab. Middle-click closes. The strip scrolls when the
|
|
10
|
+
* tabs overflow and keeps the active tab in view.
|
|
11
|
+
*/
|
|
12
|
+
function EditorTabs({ tabs, activeId, onActiveChange, onClose, onMove, actions, onTabContextMenu, className, "aria-label": ariaLabel, ...props }) {
|
|
13
|
+
const baseId = React.useId();
|
|
14
|
+
const tabRefs = React.useRef(/* @__PURE__ */ new Map());
|
|
15
|
+
const listRef = React.useRef(null);
|
|
16
|
+
const [focusedId, setFocusedId] = React.useState(null);
|
|
17
|
+
const [dragId, setDragId] = React.useState(null);
|
|
18
|
+
const lastIds = React.useRef([]);
|
|
19
|
+
const hadFocus = React.useRef(false);
|
|
20
|
+
const ids = tabs.map((t) => t.id);
|
|
21
|
+
const idsKey = ids.join("\0");
|
|
22
|
+
const tabStop = (focusedId && ids.includes(focusedId) ? focusedId : null) ?? (activeId && ids.includes(activeId) ? activeId : null) ?? ids[0] ?? null;
|
|
23
|
+
React.useEffect(() => {
|
|
24
|
+
if (activeId) tabRefs.current.get(activeId)?.scrollIntoView?.({
|
|
25
|
+
block: "nearest",
|
|
26
|
+
inline: "nearest"
|
|
27
|
+
});
|
|
28
|
+
}, [activeId]);
|
|
29
|
+
React.useLayoutEffect(() => {
|
|
30
|
+
if (focusedId && !ids.includes(focusedId)) {
|
|
31
|
+
const next = (activeId && ids.includes(activeId) ? activeId : null) ?? ids[Math.min(Math.max(0, lastIds.current.indexOf(focusedId)), ids.length - 1)] ?? null;
|
|
32
|
+
setFocusedId(next);
|
|
33
|
+
const active = document.activeElement;
|
|
34
|
+
if (next && hadFocus.current && (!active || active === document.body)) tabRefs.current.get(next)?.focus();
|
|
35
|
+
}
|
|
36
|
+
lastIds.current = ids;
|
|
37
|
+
}, [
|
|
38
|
+
focusedId,
|
|
39
|
+
idsKey,
|
|
40
|
+
activeId
|
|
41
|
+
]);
|
|
42
|
+
const focusTab = (id) => {
|
|
43
|
+
if (!id) return;
|
|
44
|
+
setFocusedId(id);
|
|
45
|
+
tabRefs.current.get(id)?.focus();
|
|
46
|
+
};
|
|
47
|
+
const onKeyDown = (event, tab) => {
|
|
48
|
+
const i = ids.indexOf(tab.id);
|
|
49
|
+
const [prev, next] = (listRef.current ? getComputedStyle(listRef.current).direction === "rtl" : false) ? ["ArrowRight", "ArrowLeft"] : ["ArrowLeft", "ArrowRight"];
|
|
50
|
+
let handled = true;
|
|
51
|
+
if (event.ctrlKey && event.shiftKey && (event.key === "PageUp" || event.key === "PageDown")) {
|
|
52
|
+
const to = event.key === "PageUp" ? i - 1 : i + 1;
|
|
53
|
+
if (onMove && to >= 0 && to < ids.length) onMove(tab.id, to);
|
|
54
|
+
} else if (event.key === prev) focusTab(ids[(i - 1 + ids.length) % ids.length]);
|
|
55
|
+
else if (event.key === next) focusTab(ids[(i + 1) % ids.length]);
|
|
56
|
+
else if (event.key === "Home") focusTab(ids[0]);
|
|
57
|
+
else if (event.key === "End") focusTab(ids[ids.length - 1]);
|
|
58
|
+
else if (event.key === "Delete" && tab.closeable !== false && onClose) onClose(tab.id);
|
|
59
|
+
else handled = false;
|
|
60
|
+
if (handled) event.preventDefault();
|
|
61
|
+
};
|
|
62
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
63
|
+
"data-slot": "editor-tabs",
|
|
64
|
+
className: cn("flex h-9 min-w-0 items-stretch border-b bg-surface-muted", className),
|
|
65
|
+
...props,
|
|
66
|
+
children: [/* @__PURE__ */ jsx("div", {
|
|
67
|
+
ref: listRef,
|
|
68
|
+
role: "tablist",
|
|
69
|
+
"aria-label": ariaLabel,
|
|
70
|
+
"aria-orientation": "horizontal",
|
|
71
|
+
className: "flex min-w-0 flex-1 items-stretch overflow-x-auto [scrollbar-width:thin]",
|
|
72
|
+
onFocus: () => hadFocus.current = true,
|
|
73
|
+
onBlur: (event) => {
|
|
74
|
+
if (!listRef.current?.contains(event.relatedTarget)) hadFocus.current = false;
|
|
75
|
+
},
|
|
76
|
+
children: tabs.map((tab, i) => {
|
|
77
|
+
const active = tab.id === activeId;
|
|
78
|
+
const closeable = tab.closeable !== false && Boolean(onClose);
|
|
79
|
+
const tabId = `${baseId}-tab-${i}`;
|
|
80
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
81
|
+
"data-slot": "editor-tab",
|
|
82
|
+
"data-state": active ? "active" : "inactive",
|
|
83
|
+
"data-dirty": tab.dirty || void 0,
|
|
84
|
+
"data-dragging": dragId === tab.id || void 0,
|
|
85
|
+
draggable: Boolean(onMove),
|
|
86
|
+
onDragStart: (event) => {
|
|
87
|
+
setDragId(tab.id);
|
|
88
|
+
event.dataTransfer.effectAllowed = "move";
|
|
89
|
+
event.dataTransfer.setData("text/plain", tab.id);
|
|
90
|
+
},
|
|
91
|
+
onDragEnd: () => setDragId(null),
|
|
92
|
+
onDragOver: (event) => {
|
|
93
|
+
if (dragId) event.preventDefault();
|
|
94
|
+
},
|
|
95
|
+
onDrop: (event) => {
|
|
96
|
+
event.preventDefault();
|
|
97
|
+
if (dragId && dragId !== tab.id) onMove?.(dragId, i);
|
|
98
|
+
setDragId(null);
|
|
99
|
+
},
|
|
100
|
+
onAuxClick: (event) => {
|
|
101
|
+
if (event.button === 1 && closeable) {
|
|
102
|
+
event.preventDefault();
|
|
103
|
+
onClose?.(tab.id);
|
|
104
|
+
}
|
|
105
|
+
},
|
|
106
|
+
onContextMenu: onTabContextMenu ? (event) => onTabContextMenu(tab.id, event) : void 0,
|
|
107
|
+
className: cn("group/tab relative flex max-w-60 shrink-0 items-center border-e text-[13px] text-muted-foreground", "hover:bg-muted/60 data-[state=active]:bg-background data-[state=active]:text-foreground", "data-[state=active]:before:absolute data-[state=active]:before:inset-x-0 data-[state=active]:before:top-0 data-[state=active]:before:h-0.5 data-[state=active]:before:bg-brand data-[state=active]:before:content-[\"\"]", "data-[dragging]:opacity-50"),
|
|
108
|
+
children: [
|
|
109
|
+
/* @__PURE__ */ jsxs("button", {
|
|
110
|
+
ref: (el) => {
|
|
111
|
+
if (el) tabRefs.current.set(tab.id, el);
|
|
112
|
+
else tabRefs.current.delete(tab.id);
|
|
113
|
+
},
|
|
114
|
+
type: "button",
|
|
115
|
+
role: "tab",
|
|
116
|
+
id: tabId,
|
|
117
|
+
"aria-selected": active,
|
|
118
|
+
"aria-controls": tab.controls,
|
|
119
|
+
"aria-describedby": tab.description ? `${tabId}-desc` : void 0,
|
|
120
|
+
title: tab.description,
|
|
121
|
+
tabIndex: tab.id === tabStop ? 0 : -1,
|
|
122
|
+
onFocus: () => setFocusedId(tab.id),
|
|
123
|
+
onClick: () => onActiveChange(tab.id),
|
|
124
|
+
onKeyDown: (event) => onKeyDown(event, tab),
|
|
125
|
+
className: cn("flex h-full min-w-0 items-center gap-1.5 ps-3 outline-none focus-visible:shadow-[inset_0_0_0_1px_var(--ring)]", closeable ? "pe-1" : "pe-3"),
|
|
126
|
+
children: [
|
|
127
|
+
tab.icon && /* @__PURE__ */ jsx("span", {
|
|
128
|
+
"aria-hidden": true,
|
|
129
|
+
className: "flex shrink-0 [&_svg]:size-4",
|
|
130
|
+
children: tab.icon
|
|
131
|
+
}),
|
|
132
|
+
/* @__PURE__ */ jsx("span", {
|
|
133
|
+
className: cn("truncate", tab.preview && "italic"),
|
|
134
|
+
children: tab.label
|
|
135
|
+
}),
|
|
136
|
+
tab.dirty && /* @__PURE__ */ jsx("span", {
|
|
137
|
+
className: "sr-only",
|
|
138
|
+
children: ", unsaved changes"
|
|
139
|
+
})
|
|
140
|
+
]
|
|
141
|
+
}),
|
|
142
|
+
tab.description && /* @__PURE__ */ jsx("span", {
|
|
143
|
+
id: `${tabId}-desc`,
|
|
144
|
+
hidden: true,
|
|
145
|
+
children: tab.description
|
|
146
|
+
}),
|
|
147
|
+
closeable ? /* @__PURE__ */ jsxs("button", {
|
|
148
|
+
type: "button",
|
|
149
|
+
tabIndex: -1,
|
|
150
|
+
"aria-label": `Close ${tab.label}`,
|
|
151
|
+
title: "Close (Delete)",
|
|
152
|
+
onClick: () => onClose?.(tab.id),
|
|
153
|
+
className: "me-1 flex size-5 shrink-0 items-center justify-center rounded-xs text-muted-foreground outline-none hover:bg-muted hover:text-foreground",
|
|
154
|
+
children: [tab.dirty && /* @__PURE__ */ jsx("span", {
|
|
155
|
+
"aria-hidden": true,
|
|
156
|
+
className: "size-2 rounded-full bg-foreground/70 group-hover/tab:hidden"
|
|
157
|
+
}), /* @__PURE__ */ jsx(X, {
|
|
158
|
+
"aria-hidden": true,
|
|
159
|
+
className: cn("size-3.5", tab.dirty ? "hidden group-hover/tab:block" : "opacity-0 group-hover/tab:opacity-100 group-data-[state=active]/tab:opacity-100 group-focus-within/tab:opacity-100")
|
|
160
|
+
})]
|
|
161
|
+
}) : tab.dirty ? /* @__PURE__ */ jsx("span", {
|
|
162
|
+
"aria-hidden": true,
|
|
163
|
+
className: "me-3 size-2 shrink-0 rounded-full bg-foreground/70"
|
|
164
|
+
}) : null
|
|
165
|
+
]
|
|
166
|
+
}, tab.id);
|
|
167
|
+
})
|
|
168
|
+
}), actions && /* @__PURE__ */ jsx("div", {
|
|
169
|
+
"data-slot": "editor-tabs-actions",
|
|
170
|
+
className: "flex shrink-0 items-center gap-0.5 px-1",
|
|
171
|
+
children: actions
|
|
172
|
+
})]
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
//#endregion
|
|
176
|
+
export { EditorTabs };
|
|
177
|
+
|
|
178
|
+
//# sourceMappingURL=editor-tabs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"editor-tabs.js","names":[],"sources":["../../src/components/editor-tabs.tsx"],"sourcesContent":["import X from '@burtson-labs/icons/react/x';\nimport * as React from 'react';\n\nimport { cn } from '../lib/utils';\n\nexport interface EditorTab {\n /** Stable identity, usually the file path. */\n id: string;\n label: string;\n /** Full path or context; the tooltip and the accessible description. */\n description?: string;\n icon?: React.ReactNode;\n /** Unsaved changes: a dot replaces the close button until hover. */\n dirty?: boolean;\n /** Default true. */\n closeable?: boolean;\n /** A preview tab that the next opened file replaces; shown in italics. */\n preview?: boolean;\n /** The id of the panel this tab shows, for aria-controls. */\n controls?: string;\n}\n\nexport interface EditorTabsProps extends Omit<\n React.ComponentProps<'div'>,\n 'children' | 'aria-label'\n> {\n tabs: EditorTab[];\n activeId: string | null;\n onActiveChange: (id: string) => void;\n /**\n * A request to close. The component never removes a tab itself: for a dirty\n * tab, ask the person (save, discard, cancel) and then update `tabs`.\n */\n onClose?: (id: string) => void;\n /** Reorder by drag or Ctrl+Shift+PageUp/PageDown. `toIndex` is the new position. */\n onMove?: (id: string, toIndex: number) => void;\n /** Required: e.g. \"Open editors\". */\n 'aria-label': string;\n /** Right-hand slot for split, more and similar buttons. */\n actions?: React.ReactNode;\n /** Right-click on a tab. */\n onTabContextMenu?: (id: string, event: React.MouseEvent) => void;\n}\n\n/**\n * The strip of open files above an editor. One tab stop; Left/Right/Home/End\n * move focus, Enter or Space opens, Delete asks to close, Ctrl+Shift+PageUp\n * and PageDown move the tab. Middle-click closes. The strip scrolls when the\n * tabs overflow and keeps the active tab in view.\n */\nfunction EditorTabs({\n tabs,\n activeId,\n onActiveChange,\n onClose,\n onMove,\n actions,\n onTabContextMenu,\n className,\n 'aria-label': ariaLabel,\n ...props\n}: EditorTabsProps) {\n const baseId = React.useId();\n const tabRefs = React.useRef(new Map<string, HTMLButtonElement>());\n const listRef = React.useRef<HTMLDivElement>(null);\n const [focusedId, setFocusedId] = React.useState<string | null>(null);\n const [dragId, setDragId] = React.useState<string | null>(null);\n const lastIds = React.useRef<string[]>([]);\n const hadFocus = React.useRef(false);\n\n const ids = tabs.map((t) => t.id);\n const idsKey = ids.join('\\u0000');\n const tabStop =\n (focusedId && ids.includes(focusedId) ? focusedId : null) ??\n (activeId && ids.includes(activeId) ? activeId : null) ??\n ids[0] ??\n null;\n\n React.useEffect(() => {\n if (activeId)\n tabRefs.current.get(activeId)?.scrollIntoView?.({ block: 'nearest', inline: 'nearest' });\n }, [activeId]);\n\n // After a close, keep keyboard focus in the strip: the active tab if the\n // app picked one, else the neighbour at the closed tab's position.\n React.useLayoutEffect(() => {\n if (focusedId && !ids.includes(focusedId)) {\n const next =\n (activeId && ids.includes(activeId) ? activeId : null) ??\n ids[Math.min(Math.max(0, lastIds.current.indexOf(focusedId)), ids.length - 1)] ??\n null;\n setFocusedId(next);\n const active = document.activeElement;\n if (next && hadFocus.current && (!active || active === document.body))\n tabRefs.current.get(next)?.focus();\n }\n lastIds.current = ids;\n // ids is derived from tabs each render; idsKey is its stable form.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [focusedId, idsKey, activeId]);\n\n const focusTab = (id: string | undefined) => {\n if (!id) return;\n setFocusedId(id);\n tabRefs.current.get(id)?.focus();\n };\n\n const onKeyDown = (event: React.KeyboardEvent<HTMLButtonElement>, tab: EditorTab) => {\n const i = ids.indexOf(tab.id);\n const rtl = listRef.current ? getComputedStyle(listRef.current).direction === 'rtl' : false;\n const [prev, next] = rtl ? ['ArrowRight', 'ArrowLeft'] : ['ArrowLeft', 'ArrowRight'];\n let handled = true;\n if (event.ctrlKey && event.shiftKey && (event.key === 'PageUp' || event.key === 'PageDown')) {\n const to = event.key === 'PageUp' ? i - 1 : i + 1;\n if (onMove && to >= 0 && to < ids.length) onMove(tab.id, to);\n } else if (event.key === prev) focusTab(ids[(i - 1 + ids.length) % ids.length]);\n else if (event.key === next) focusTab(ids[(i + 1) % ids.length]);\n else if (event.key === 'Home') focusTab(ids[0]);\n else if (event.key === 'End') focusTab(ids[ids.length - 1]);\n else if (event.key === 'Delete' && tab.closeable !== false && onClose) onClose(tab.id);\n else handled = false;\n if (handled) event.preventDefault();\n };\n\n return (\n <div\n data-slot=\"editor-tabs\"\n className={cn('flex h-9 min-w-0 items-stretch border-b bg-surface-muted', className)}\n {...props}\n >\n <div\n ref={listRef}\n role=\"tablist\"\n aria-label={ariaLabel}\n aria-orientation=\"horizontal\"\n className=\"flex min-w-0 flex-1 items-stretch overflow-x-auto [scrollbar-width:thin]\"\n onFocus={() => (hadFocus.current = true)}\n onBlur={(event) => {\n if (!listRef.current?.contains(event.relatedTarget)) hadFocus.current = false;\n }}\n >\n {tabs.map((tab, i) => {\n const active = tab.id === activeId;\n const closeable = tab.closeable !== false && Boolean(onClose);\n const tabId = `${baseId}-tab-${i}`;\n return (\n <div\n key={tab.id}\n data-slot=\"editor-tab\"\n data-state={active ? 'active' : 'inactive'}\n data-dirty={tab.dirty || undefined}\n data-dragging={dragId === tab.id || undefined}\n draggable={Boolean(onMove)}\n onDragStart={(event) => {\n setDragId(tab.id);\n event.dataTransfer.effectAllowed = 'move';\n event.dataTransfer.setData('text/plain', tab.id);\n }}\n onDragEnd={() => setDragId(null)}\n onDragOver={(event) => {\n if (dragId) event.preventDefault();\n }}\n onDrop={(event) => {\n event.preventDefault();\n if (dragId && dragId !== tab.id) onMove?.(dragId, i);\n setDragId(null);\n }}\n onAuxClick={(event) => {\n if (event.button === 1 && closeable) {\n event.preventDefault();\n onClose?.(tab.id);\n }\n }}\n onContextMenu={\n onTabContextMenu ? (event) => onTabContextMenu(tab.id, event) : undefined\n }\n className={cn(\n 'group/tab relative flex max-w-60 shrink-0 items-center border-e text-[13px] text-muted-foreground',\n 'hover:bg-muted/60 data-[state=active]:bg-background data-[state=active]:text-foreground',\n // The active tab's top edge carries the brand colour.\n 'data-[state=active]:before:absolute data-[state=active]:before:inset-x-0 data-[state=active]:before:top-0 data-[state=active]:before:h-0.5 data-[state=active]:before:bg-brand data-[state=active]:before:content-[\"\"]',\n 'data-[dragging]:opacity-50',\n )}\n >\n <button\n ref={(el) => {\n if (el) tabRefs.current.set(tab.id, el);\n else tabRefs.current.delete(tab.id);\n }}\n type=\"button\"\n role=\"tab\"\n id={tabId}\n aria-selected={active}\n aria-controls={tab.controls}\n aria-describedby={tab.description ? `${tabId}-desc` : undefined}\n title={tab.description}\n tabIndex={tab.id === tabStop ? 0 : -1}\n onFocus={() => setFocusedId(tab.id)}\n onClick={() => onActiveChange(tab.id)}\n onKeyDown={(event) => onKeyDown(event, tab)}\n className={cn(\n 'flex h-full min-w-0 items-center gap-1.5 ps-3 outline-none focus-visible:shadow-[inset_0_0_0_1px_var(--ring)]',\n closeable ? 'pe-1' : 'pe-3',\n )}\n >\n {tab.icon && (\n <span aria-hidden className=\"flex shrink-0 [&_svg]:size-4\">\n {tab.icon}\n </span>\n )}\n <span className={cn('truncate', tab.preview && 'italic')}>{tab.label}</span>\n {tab.dirty && <span className=\"sr-only\">, unsaved changes</span>}\n </button>\n {tab.description && (\n <span id={`${tabId}-desc`} hidden>\n {tab.description}\n </span>\n )}\n {closeable ? (\n <button\n type=\"button\"\n tabIndex={-1}\n aria-label={`Close ${tab.label}`}\n title=\"Close (Delete)\"\n onClick={() => onClose?.(tab.id)}\n className=\"me-1 flex size-5 shrink-0 items-center justify-center rounded-xs text-muted-foreground outline-none hover:bg-muted hover:text-foreground\"\n >\n {tab.dirty && (\n <span\n aria-hidden\n className=\"size-2 rounded-full bg-foreground/70 group-hover/tab:hidden\"\n />\n )}\n <X\n aria-hidden\n className={cn(\n 'size-3.5',\n tab.dirty\n ? 'hidden group-hover/tab:block'\n : 'opacity-0 group-hover/tab:opacity-100 group-data-[state=active]/tab:opacity-100 group-focus-within/tab:opacity-100',\n )}\n />\n </button>\n ) : tab.dirty ? (\n <span aria-hidden className=\"me-3 size-2 shrink-0 rounded-full bg-foreground/70\" />\n ) : null}\n </div>\n );\n })}\n </div>\n {actions && (\n <div data-slot=\"editor-tabs-actions\" className=\"flex shrink-0 items-center gap-0.5 px-1\">\n {actions}\n </div>\n )}\n </div>\n );\n}\n\nexport { EditorTabs };\n"],"mappings":"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"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { Menubar as MenubarPrimitive } from 'radix-ui';
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
/**
|
|
4
|
+
* An application menu bar (File, Edit, View). Left/Right move between menus,
|
|
5
|
+
* Down opens one, and an open menu follows the pointer across triggers. Rows
|
|
6
|
+
* match DropdownMenu and ContextMenu.
|
|
7
|
+
*/
|
|
8
|
+
declare function Menubar({ className, ...props }: React.ComponentProps<typeof MenubarPrimitive.Root>): React.JSX.Element;
|
|
9
|
+
declare function MenubarMenu(props: React.ComponentProps<typeof MenubarPrimitive.Menu>): React.JSX.Element;
|
|
10
|
+
declare function MenubarTrigger({ className, ...props }: React.ComponentProps<typeof MenubarPrimitive.Trigger>): React.JSX.Element;
|
|
11
|
+
declare function MenubarGroup(props: React.ComponentProps<typeof MenubarPrimitive.Group>): React.JSX.Element;
|
|
12
|
+
declare function MenubarContent({ className, align, sideOffset, ...props }: React.ComponentProps<typeof MenubarPrimitive.Content>): React.JSX.Element;
|
|
13
|
+
declare function MenubarItem({ className, inset, variant, ...props }: React.ComponentProps<typeof MenubarPrimitive.Item> & {
|
|
14
|
+
inset?: boolean;
|
|
15
|
+
variant?: 'default' | 'destructive';
|
|
16
|
+
}): React.JSX.Element;
|
|
17
|
+
declare function MenubarCheckboxItem({ className, children, checked, ...props }: React.ComponentProps<typeof MenubarPrimitive.CheckboxItem>): React.JSX.Element;
|
|
18
|
+
declare function MenubarRadioGroup(props: React.ComponentProps<typeof MenubarPrimitive.RadioGroup>): React.JSX.Element;
|
|
19
|
+
declare function MenubarRadioItem({ className, children, ...props }: React.ComponentProps<typeof MenubarPrimitive.RadioItem>): React.JSX.Element;
|
|
20
|
+
declare function MenubarLabel({ className, inset, ...props }: React.ComponentProps<typeof MenubarPrimitive.Label> & {
|
|
21
|
+
inset?: boolean;
|
|
22
|
+
}): React.JSX.Element;
|
|
23
|
+
declare function MenubarSeparator({ className, ...props }: React.ComponentProps<typeof MenubarPrimitive.Separator>): React.JSX.Element;
|
|
24
|
+
declare function MenubarShortcut({ className, ...props }: React.ComponentProps<'span'>): React.JSX.Element;
|
|
25
|
+
declare function MenubarSub(props: React.ComponentProps<typeof MenubarPrimitive.Sub>): React.JSX.Element;
|
|
26
|
+
declare function MenubarSubTrigger({ className, inset, children, ...props }: React.ComponentProps<typeof MenubarPrimitive.SubTrigger> & {
|
|
27
|
+
inset?: boolean;
|
|
28
|
+
}): React.JSX.Element;
|
|
29
|
+
declare function MenubarSubContent({ className, ...props }: React.ComponentProps<typeof MenubarPrimitive.SubContent>): React.JSX.Element;
|
|
30
|
+
export { Menubar, MenubarMenu, MenubarCheckboxItem, MenubarContent, MenubarGroup, MenubarItem, MenubarLabel, MenubarRadioGroup, MenubarRadioItem, MenubarSeparator, MenubarShortcut, MenubarSub, MenubarSubContent, MenubarSubTrigger, MenubarTrigger, };
|