@ctrl-ui/react 0.8.0 → 0.8.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 (59) hide show
  1. package/README.md +1 -0
  2. package/dist/blocks/coding-agent.js +3 -1
  3. package/dist/blocks/file-explorer.js +3 -1
  4. package/dist/blocks/settings.js +3 -1
  5. package/dist/control-props.d.ts +2 -1
  6. package/dist/email/email.d.ts +28 -0
  7. package/dist/email/email.js +70 -0
  8. package/dist/email/templates.d.ts +51 -0
  9. package/dist/email/templates.js +228 -0
  10. package/dist/email/theme.d.ts +23 -0
  11. package/dist/email/theme.js +98 -0
  12. package/dist/extensions/create-track-highlight.d.ts +0 -2
  13. package/dist/extensions/create-track-highlight.js +49 -8
  14. package/dist/extensions/supports-anchor-transitions.d.ts +4 -0
  15. package/dist/extensions/supports-anchor-transitions.js +31 -0
  16. package/dist/extensions/track-highlight.d.ts +0 -6
  17. package/dist/extensions/track-highlight.js +25 -9
  18. package/dist/knob-contracts/button-knobs.d.ts +1 -1
  19. package/dist/knob-contracts/button-knobs.js +4 -1
  20. package/dist/knob-contracts/progressive-blur-knobs.d.ts +5 -0
  21. package/dist/knob-contracts/progressive-blur-knobs.js +9 -0
  22. package/dist/scripts/contrast-eval.d.ts +46 -0
  23. package/dist/scripts/contrast-eval.js +327 -0
  24. package/dist/skin.config.js +9 -1
  25. package/dist/skin.d.ts +11 -9
  26. package/dist/skin.js +0 -1
  27. package/dist/styles/index.css +2 -1
  28. package/dist/styles/recipes/button-group.css +46 -0
  29. package/dist/styles/recipes/button.css +53 -5
  30. package/dist/styles/recipes/progressive-blur.css +145 -0
  31. package/dist/styles/recipes/scroll-area.css +140 -5
  32. package/dist/styles/recipes/sidebar.css +49 -0
  33. package/dist/styles/recipes/table-of-contents.css +1 -1
  34. package/dist/styles/recipes/track-highlight.css +126 -2
  35. package/dist/styles/recipes/tree.css +4 -0
  36. package/dist/ui/button-group.d.ts +3 -1
  37. package/dist/ui/button-group.js +21 -18
  38. package/dist/ui/button.d.ts +3 -1
  39. package/dist/ui/button.js +13 -4
  40. package/dist/ui/checkbox-group.d.ts +5 -3
  41. package/dist/ui/checkbox-group.js +23 -6
  42. package/dist/ui/color-picker.js +1 -1
  43. package/dist/ui/dropdown-menu.d.ts +2 -3
  44. package/dist/ui/dropdown-menu.js +1 -7
  45. package/dist/ui/progressive-blur.d.ts +12 -0
  46. package/dist/ui/progressive-blur.js +47 -0
  47. package/dist/ui/scroll-area.d.ts +4 -1
  48. package/dist/ui/scroll-area.js +27 -4
  49. package/dist/ui/sidebar-menu.d.ts +39 -0
  50. package/dist/ui/sidebar-menu.js +135 -0
  51. package/dist/ui/sidebar-provider.d.ts +28 -0
  52. package/dist/ui/sidebar-provider.js +80 -0
  53. package/dist/ui/sidebar.d.ts +4 -61
  54. package/dist/ui/sidebar.js +23 -202
  55. package/dist/ui/table-of-contents.js +3 -11
  56. package/dist/ui/toggle.d.ts +3 -2
  57. package/dist/ui/toggle.js +22 -10
  58. package/dist/ui/tree.js +13 -19
  59. package/package.json +5 -1
@@ -0,0 +1,135 @@
1
+ "use client";
2
+ import { cn } from "../lib/cn.js";
3
+ import { skinIndicator } from "../skin.js";
4
+ import { Tooltip, TooltipContent, TooltipTrigger } from "./tooltip.js";
5
+ import { useSidebar } from "./sidebar-provider.js";
6
+ import { TrackHighlight } from "../extensions/track-highlight.js";
7
+ import { createContext, useContext } from "react";
8
+ import { useRender } from "@base-ui/react/use-render";
9
+ import { jsx, jsxs } from "react/jsx-runtime";
10
+ import { cva } from "class-variance-authority";
11
+ //#region src/ui/sidebar-menu.tsx
12
+ const sidebarMenuButtonVariants = ["default", "outline"];
13
+ const sidebarMenuButtonSizes = [
14
+ "default",
15
+ "sm",
16
+ "lg"
17
+ ];
18
+ function SidebarGroup({ className, ...props }) {
19
+ return /* @__PURE__ */ jsx("div", {
20
+ "data-control-ui": "sidebar",
21
+ "data-control-family": "sidebar",
22
+ "data-slot": "group",
23
+ className: cn("relative flex w-full min-w-0 flex-col", className),
24
+ ...props
25
+ });
26
+ }
27
+ function SidebarGroupLabel({ className, render, children, ...props }) {
28
+ return useRender({
29
+ defaultTagName: "div",
30
+ render,
31
+ props: {
32
+ ...props,
33
+ "data-control-ui": "sidebar",
34
+ "data-control-family": "sidebar",
35
+ "data-slot": "group-label",
36
+ className: cn("flex h-[var(--control-h-sm)] shrink-0 items-center [&>svg]:size-4 [&>svg]:shrink-0", "group-data-[collapsible=icon]:invisible group-data-[collapsible=icon]:-mt-[var(--control-h-sm)] group-data-[collapsible=icon]:opacity-0", className),
37
+ children
38
+ }
39
+ });
40
+ }
41
+ const SidebarMenuContext = createContext("none");
42
+ function SidebarMenu({ className, indicator, style, children, ...props }) {
43
+ const resolvedIndicator = indicator ?? skinIndicator("sidebar") ?? "none";
44
+ const hasHighlight = resolvedIndicator !== "none";
45
+ const list = /* @__PURE__ */ jsx("ul", {
46
+ "data-control-ui": "sidebar",
47
+ "data-control-family": "sidebar",
48
+ "data-slot": "menu",
49
+ "data-indicator": resolvedIndicator,
50
+ className: cn("flex min-w-0 flex-col", hasHighlight ? void 0 : className),
51
+ style: hasHighlight ? void 0 : style,
52
+ ...props,
53
+ children: /* @__PURE__ */ jsx(SidebarMenuContext.Provider, {
54
+ value: resolvedIndicator,
55
+ children
56
+ })
57
+ });
58
+ if (!hasHighlight) return list;
59
+ return /* @__PURE__ */ jsxs("div", {
60
+ "data-control-ui": "sidebar",
61
+ "data-control-family": "sidebar",
62
+ "data-slot": "menu-track",
63
+ "data-indicator": resolvedIndicator,
64
+ "data-track": resolvedIndicator,
65
+ className: cn("relative isolate", className),
66
+ style,
67
+ children: [list, /* @__PURE__ */ jsx(TrackHighlight, {})]
68
+ });
69
+ }
70
+ function SidebarMenuItem({ className, ...props }) {
71
+ return /* @__PURE__ */ jsx("li", {
72
+ "data-control-ui": "sidebar",
73
+ "data-control-family": "sidebar",
74
+ "data-slot": "menu-item",
75
+ className: cn("group/menu-item relative", className),
76
+ ...props
77
+ });
78
+ }
79
+ const sidebarMenuButtonClasses = cva("peer/menu-button flex w-full items-center overflow-hidden text-start group-data-[collapsible=icon]:px-0! disabled:pointer-events-none aria-disabled:pointer-events-none [&>span:last-child]:truncate [&>svg]:size-4 [&>svg]:shrink-0", {
80
+ variants: {
81
+ variant: {
82
+ default: null,
83
+ outline: null
84
+ },
85
+ size: {
86
+ default: "group-data-[collapsible=icon]:size-[var(--control-h-md)]!",
87
+ sm: "group-data-[collapsible=icon]:size-[var(--control-h-sm)]!",
88
+ lg: "group-data-[collapsible=icon]:size-[var(--control-h-lg)]!"
89
+ }
90
+ },
91
+ defaultVariants: {
92
+ variant: "default",
93
+ size: "default"
94
+ }
95
+ });
96
+ function SidebarMenuButton({ render, isActive = false, variant = "default", size = "default", tooltip, className, children, ...props }) {
97
+ const { isMobile, state } = useSidebar();
98
+ const indicator = useContext(SidebarMenuContext);
99
+ const button = useRender({
100
+ defaultTagName: "button",
101
+ render,
102
+ props: {
103
+ type: "button",
104
+ ...props,
105
+ "data-control-ui": "sidebar",
106
+ "data-control-family": "sidebar",
107
+ "data-slot": "menu-button",
108
+ "data-size": size,
109
+ "data-variant": variant,
110
+ "data-active": isActive || void 0,
111
+ "data-track-item": indicator !== "none" ? "" : void 0,
112
+ className: cn(sidebarMenuButtonClasses({
113
+ variant,
114
+ size
115
+ }), className),
116
+ children
117
+ }
118
+ });
119
+ if (!tooltip) return button;
120
+ return /* @__PURE__ */ jsxs(Tooltip, { children: [/* @__PURE__ */ jsx(TooltipTrigger, { render: button }), /* @__PURE__ */ jsx(TooltipContent, {
121
+ side: "right",
122
+ align: "center",
123
+ hidden: state !== "collapsed" || isMobile,
124
+ children: tooltip
125
+ })] });
126
+ }
127
+ function SidebarMenuSub({ className, ...props }) {
128
+ return /* @__PURE__ */ jsx(SidebarMenu, {
129
+ "data-submenu": "",
130
+ className: cn("group-data-[collapsible=icon]:hidden", className),
131
+ ...props
132
+ });
133
+ }
134
+ //#endregion
135
+ export { SidebarGroup, SidebarGroupLabel, SidebarMenu, SidebarMenuButton, SidebarMenuItem, SidebarMenuSub, sidebarMenuButtonSizes, sidebarMenuButtonVariants };
@@ -0,0 +1,28 @@
1
+ import { SidebarKnobStyle } from "../knob-contracts/sidebar-knobs.js";
2
+ import { CSSProperties, ComponentProps } from "react";
3
+ //#region src/ui/sidebar-provider.d.ts
4
+ type SidebarStyle = CSSProperties & SidebarKnobStyle & {
5
+ "--sidebar-width"?: string;
6
+ "--sidebar-width-icon"?: string;
7
+ };
8
+ type SidebarContextProps = {
9
+ state: "expanded" | "collapsed";
10
+ open: boolean;
11
+ setOpen: (open: boolean) => void;
12
+ openMobile: boolean;
13
+ setOpenMobile: (open: boolean) => void;
14
+ isMobile: boolean;
15
+ toggleSidebar: () => void;
16
+ };
17
+ declare function useSidebar(): SidebarContextProps;
18
+ type SidebarProviderProps = Omit<ComponentProps<"div">, "style"> & {
19
+ defaultOpen?: boolean;
20
+ open?: boolean;
21
+ onOpenChange?: (open: boolean) => void;
22
+ persistOpen?: boolean;
23
+ keyboardShortcut?: string | null;
24
+ style?: SidebarStyle;
25
+ };
26
+ declare function SidebarProvider({ defaultOpen, open: openProp, onOpenChange, persistOpen, keyboardShortcut, ref, className, style, children, ...props }: SidebarProviderProps): import("react").JSX.Element;
27
+ //#endregion
28
+ export { SidebarProvider, SidebarProviderProps, SidebarStyle, useSidebar };
@@ -0,0 +1,80 @@
1
+ "use client";
2
+ import { cn } from "../lib/cn.js";
3
+ import { skinSidebarWidth } from "../skin.js";
4
+ import { TooltipProvider } from "./tooltip.js";
5
+ import { SIDEBAR_COOKIE_NAME } from "../control-props.js";
6
+ import { useIsMobile } from "../hooks/use-mobile.js";
7
+ import { createContext, useContext, useEffect, useRef, useState } from "react";
8
+ import { jsx } from "react/jsx-runtime";
9
+ //#region src/ui/sidebar-provider.tsx
10
+ const SIDEBAR_COOKIE_MAX_AGE = 604800;
11
+ const SIDEBAR_WIDTH = "16rem";
12
+ const SIDEBAR_WIDTH_ICON = "3rem";
13
+ const SIDEBAR_KEYBOARD_SHORTCUT = "b";
14
+ const SIDEBAR_MOBILE_BREAKPOINT = 1024;
15
+ const SidebarContext = createContext(null);
16
+ function useSidebar() {
17
+ const context = useContext(SidebarContext);
18
+ if (!context) throw new Error("useSidebar must be used within a SidebarProvider.");
19
+ return context;
20
+ }
21
+ function SidebarProvider({ defaultOpen = true, open: openProp, onOpenChange, persistOpen = true, keyboardShortcut = SIDEBAR_KEYBOARD_SHORTCUT, ref, className, style, children, ...props }) {
22
+ const isMobile = useIsMobile(SIDEBAR_MOBILE_BREAKPOINT);
23
+ const [openMobile, setOpenMobile] = useState(false);
24
+ const [internalOpen, setInternalOpen] = useState(defaultOpen);
25
+ const open = openProp ?? internalOpen;
26
+ const setOpen = (value) => {
27
+ const openState = typeof value === "function" ? value(open) : value;
28
+ if (onOpenChange) onOpenChange(openState);
29
+ else setInternalOpen(openState);
30
+ if (persistOpen) document.cookie = `${SIDEBAR_COOKIE_NAME}=${openState}; path=/; max-age=${SIDEBAR_COOKIE_MAX_AGE}`;
31
+ };
32
+ const toggleSidebar = () => isMobile ? setOpenMobile((prev) => !prev) : setOpen(!open);
33
+ const toggleRef = useRef(toggleSidebar);
34
+ useEffect(() => {
35
+ toggleRef.current = toggleSidebar;
36
+ });
37
+ useEffect(() => {
38
+ if (keyboardShortcut === null) return;
39
+ const handleKeyDown = (event) => {
40
+ if (event.key === keyboardShortcut && (event.metaKey || event.ctrlKey)) {
41
+ event.preventDefault();
42
+ toggleRef.current();
43
+ }
44
+ };
45
+ window.addEventListener("keydown", handleKeyDown);
46
+ return () => window.removeEventListener("keydown", handleKeyDown);
47
+ }, [keyboardShortcut]);
48
+ const contextValue = {
49
+ state: open ? "expanded" : "collapsed",
50
+ open,
51
+ setOpen,
52
+ isMobile,
53
+ openMobile,
54
+ setOpenMobile,
55
+ toggleSidebar
56
+ };
57
+ const wrapperStyle = {
58
+ "--sidebar-width": skinSidebarWidth() ?? SIDEBAR_WIDTH,
59
+ "--sidebar-width-icon": SIDEBAR_WIDTH_ICON,
60
+ ...style
61
+ };
62
+ return /* @__PURE__ */ jsx(SidebarContext.Provider, {
63
+ value: contextValue,
64
+ children: /* @__PURE__ */ jsx(TooltipProvider, {
65
+ delay: 0,
66
+ children: /* @__PURE__ */ jsx("div", {
67
+ ref,
68
+ "data-control-ui": "sidebar",
69
+ "data-control-family": "sidebar",
70
+ "data-slot": "wrapper",
71
+ style: wrapperStyle,
72
+ className: cn("group/sidebar-wrapper flex min-h-svh w-full", className),
73
+ ...props,
74
+ children
75
+ })
76
+ })
77
+ });
78
+ }
79
+ //#endregion
80
+ export { SidebarProvider, useSidebar };
@@ -1,55 +1,16 @@
1
- import { RenderProp, SelectionIndicator } from "../control-props.js";
2
1
  import { Button } from "./button.js";
3
2
  import { SidebarKnobStyle } from "../knob-contracts/sidebar-knobs.js";
4
- import { CSSProperties, ComponentProps, ReactNode } from "react";
3
+ import { SidebarGroup, SidebarGroupLabel, SidebarGroupLabelProps, SidebarMenu, SidebarMenuButton, SidebarMenuButtonProps, SidebarMenuButtonSize, SidebarMenuButtonVariant, SidebarMenuItem, SidebarMenuSub, SidebarSelectionIndicator, sidebarMenuButtonSizes, sidebarMenuButtonVariants } from "./sidebar-menu.js";
4
+ import { SidebarProvider, SidebarProviderProps, SidebarStyle, useSidebar } from "./sidebar-provider.js";
5
+ import { CSSProperties, ComponentProps } from "react";
5
6
  //#region src/ui/sidebar.d.ts
6
- declare const sidebarMenuButtonVariants: readonly ["default", "outline"];
7
- type SidebarMenuButtonVariant = (typeof sidebarMenuButtonVariants)[number];
8
- declare const sidebarMenuButtonSizes: readonly ["default", "sm", "lg"];
9
- type SidebarMenuButtonSize = (typeof sidebarMenuButtonSizes)[number];
10
7
  type SidebarRailProps = Omit<ComponentProps<"button">, "style"> & {
11
8
  style?: CSSProperties & SidebarKnobStyle;
12
9
  };
13
10
  type SidebarInsetProps = Omit<ComponentProps<"main">, "style"> & {
14
11
  style?: CSSProperties & SidebarKnobStyle;
15
12
  };
16
- type SidebarGroupLabelProps = Omit<ComponentProps<"div">, "style"> & {
17
- style?: CSSProperties & SidebarKnobStyle;
18
- } & {
19
- render?: RenderProp<ComponentProps<"div">>;
20
- };
21
- type SidebarMenuButtonProps = Omit<ComponentProps<"button">, "style"> & {
22
- style?: CSSProperties & SidebarKnobStyle;
23
- } & {
24
- render?: RenderProp<ComponentProps<"button">>;
25
- isActive?: boolean;
26
- tooltip?: ReactNode;
27
- variant?: SidebarMenuButtonVariant;
28
- size?: SidebarMenuButtonSize;
29
- };
30
- /** Exported so blocks can set width through `style` and stay type-checked. */
31
- type SidebarStyle = CSSProperties & SidebarKnobStyle & {
32
- "--sidebar-width"?: string;
33
- "--sidebar-width-icon"?: string;
34
- };
35
13
  type SidebarSurfaceStyle = CSSProperties & SidebarKnobStyle;
36
- type SidebarContextProps = {
37
- state: "expanded" | "collapsed";
38
- open: boolean;
39
- setOpen: (open: boolean) => void;
40
- openMobile: boolean;
41
- setOpenMobile: (open: boolean) => void;
42
- isMobile: boolean;
43
- toggleSidebar: () => void;
44
- };
45
- declare function useSidebar(): SidebarContextProps;
46
- type SidebarProviderProps = Omit<ComponentProps<"div">, "style"> & {
47
- defaultOpen?: boolean;
48
- open?: boolean;
49
- onOpenChange?: (open: boolean) => void;
50
- style?: SidebarStyle;
51
- };
52
- declare function SidebarProvider({ defaultOpen, open: openProp, onOpenChange: setOpenProp, ref, className, style, children, ...props }: SidebarProviderProps): import("react").JSX.Element;
53
14
  declare function Sidebar({ side, variant, collapsible, ref, className, children, style, ...props }: Omit<ComponentProps<"div">, "style"> & {
54
15
  side?: "left" | "right";
55
16
  variant?: "sidebar" | "floating" | "inset";
@@ -66,23 +27,5 @@ declare function SidebarFooter({ className, ...props }: ComponentProps<"div"> &
66
27
  style?: CSSProperties & SidebarKnobStyle;
67
28
  }): import("react").JSX.Element;
68
29
  declare function SidebarContent({ className, children, ...props }: ComponentProps<"div">): import("react").JSX.Element;
69
- declare function SidebarGroup({ className, ...props }: ComponentProps<"div"> & {
70
- style?: CSSProperties & SidebarKnobStyle;
71
- }): import("react").JSX.Element;
72
- declare function SidebarGroupLabel({ className, render, children, ...props }: SidebarGroupLabelProps): import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>>;
73
- type SidebarSelectionIndicator = SelectionIndicator;
74
- declare function SidebarMenu({ className, indicator, children, ...props }: ComponentProps<"ul"> & {
75
- /**
76
- * `slide` replaces per-row backgrounds with one pill that glides to hovered or active item.
77
- * Defaults to ControlUiSkin.indicators.sidebar, else `none`.
78
- */
79
- indicator?: SidebarSelectionIndicator;
80
- } & {
81
- style?: CSSProperties & SidebarKnobStyle;
82
- }): import("react").JSX.Element;
83
- declare function SidebarMenuItem({ className, ...props }: ComponentProps<"li"> & {
84
- style?: CSSProperties & SidebarKnobStyle;
85
- }): import("react").JSX.Element;
86
- declare function SidebarMenuButton({ render, isActive, variant, size, tooltip, className, children, ...props }: SidebarMenuButtonProps): import("react").JSX.Element;
87
30
  //#endregion
88
- export { Sidebar, SidebarContent, SidebarFooter, SidebarGroup, SidebarGroupLabel, SidebarGroupLabelProps, SidebarHeader, SidebarInset, SidebarInsetProps, SidebarMenu, SidebarMenuButton, SidebarMenuButtonProps, SidebarMenuButtonSize, SidebarMenuButtonVariant, SidebarMenuItem, SidebarProvider, SidebarProviderProps, SidebarRail, SidebarRailProps, SidebarSelectionIndicator, SidebarStyle, SidebarTrigger, sidebarMenuButtonSizes, sidebarMenuButtonVariants, useSidebar };
31
+ export { Sidebar, SidebarContent, SidebarFooter, SidebarGroup, SidebarGroupLabel, type SidebarGroupLabelProps, SidebarHeader, SidebarInset, SidebarInsetProps, SidebarMenu, SidebarMenuButton, type SidebarMenuButtonProps, type SidebarMenuButtonSize, type SidebarMenuButtonVariant, SidebarMenuItem, SidebarMenuSub, SidebarProvider, type SidebarProviderProps, SidebarRail, SidebarRailProps, type SidebarSelectionIndicator, type SidebarStyle, SidebarTrigger, sidebarMenuButtonSizes, sidebarMenuButtonVariants, useSidebar };
@@ -1,100 +1,21 @@
1
1
  "use client";
2
2
  import { cn } from "../lib/cn.js";
3
- import { skinIndicator, skinSidebarLayout, skinSidebarWidth } from "../skin.js";
3
+ import { skinSidebarLayout } from "../skin.js";
4
4
  import { Button } from "./button.js";
5
5
  import { ScrollArea } from "./scroll-area.js";
6
- import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "./tooltip.js";
7
- import { SIDEBAR_COOKIE_NAME } from "../control-props.js";
8
- import { useIsMobile } from "../hooks/use-mobile.js";
9
6
  import { Sheet, SheetContent, SheetDescription, SheetHeader, SheetTitle } from "./sheet.js";
10
- import { Suspense, createContext, lazy, useContext, useEffect, useRef, useState } from "react";
11
- import { useRender } from "@base-ui/react/use-render";
7
+ import { SidebarProvider, useSidebar } from "./sidebar-provider.js";
8
+ import { SidebarGroup, SidebarGroupLabel, SidebarMenu, SidebarMenuButton, SidebarMenuItem, SidebarMenuSub, sidebarMenuButtonSizes, sidebarMenuButtonVariants } from "./sidebar-menu.js";
12
9
  import { jsx, jsxs } from "react/jsx-runtime";
13
10
  import { PanelLeftIcon } from "lucide-react";
14
- import { cva } from "class-variance-authority";
15
11
  //#region src/ui/sidebar.tsx
16
- const sidebarMenuButtonVariants = ["default", "outline"];
17
- const sidebarMenuButtonSizes = [
18
- "default",
19
- "sm",
20
- "lg"
21
- ];
22
- const TrackHighlight = lazy(() => import("../extensions/track-highlight.js").then((module) => ({ default: module.TrackHighlight })));
23
- const SIDEBAR_COOKIE_MAX_AGE = 604800;
24
- const SIDEBAR_WIDTH = "16rem";
25
12
  const SIDEBAR_WIDTH_MOBILE = "18rem";
26
- const SIDEBAR_WIDTH_ICON = "3rem";
27
- const SIDEBAR_KEYBOARD_SHORTCUT = "b";
28
- const SIDEBAR_MOBILE_BREAKPOINT = 1024;
29
13
  const sidebarTriggerWidth = {
30
14
  xs: "w-[var(--control-h-xs)]",
31
15
  sm: "w-[var(--control-h-sm)]",
32
16
  md: "w-[var(--control-h-md)]",
33
17
  lg: "w-[var(--control-h-lg)]"
34
18
  };
35
- const SidebarContext = createContext(null);
36
- function useSidebar() {
37
- const context = useContext(SidebarContext);
38
- if (!context) throw new Error("useSidebar must be used within a SidebarProvider.");
39
- return context;
40
- }
41
- function SidebarProvider({ defaultOpen = true, open: openProp, onOpenChange: setOpenProp, ref, className, style, children, ...props }) {
42
- const isMobile = useIsMobile(SIDEBAR_MOBILE_BREAKPOINT);
43
- const [openMobile, setOpenMobile] = useState(false);
44
- const [_open, _setOpen] = useState(defaultOpen);
45
- const open = openProp ?? _open;
46
- const setOpen = (value) => {
47
- const openState = typeof value === "function" ? value(open) : value;
48
- if (setOpenProp) setOpenProp(openState);
49
- else _setOpen(openState);
50
- document.cookie = `${SIDEBAR_COOKIE_NAME}=${openState}; path=/; max-age=${SIDEBAR_COOKIE_MAX_AGE}`;
51
- };
52
- const toggleSidebar = () => isMobile ? setOpenMobile((prev) => !prev) : setOpen(!open);
53
- const toggleRef = useRef(toggleSidebar);
54
- useEffect(() => {
55
- toggleRef.current = toggleSidebar;
56
- });
57
- useEffect(() => {
58
- const handleKeyDown = (event) => {
59
- if (event.key === SIDEBAR_KEYBOARD_SHORTCUT && (event.metaKey || event.ctrlKey)) {
60
- event.preventDefault();
61
- toggleRef.current();
62
- }
63
- };
64
- window.addEventListener("keydown", handleKeyDown);
65
- return () => window.removeEventListener("keydown", handleKeyDown);
66
- }, []);
67
- const contextValue = {
68
- state: open ? "expanded" : "collapsed",
69
- open,
70
- setOpen,
71
- isMobile,
72
- openMobile,
73
- setOpenMobile,
74
- toggleSidebar
75
- };
76
- const wrapperStyle = {
77
- "--sidebar-width": skinSidebarWidth() ?? SIDEBAR_WIDTH,
78
- "--sidebar-width-icon": SIDEBAR_WIDTH_ICON,
79
- ...style
80
- };
81
- return /* @__PURE__ */ jsx(SidebarContext.Provider, {
82
- value: contextValue,
83
- children: /* @__PURE__ */ jsx(TooltipProvider, {
84
- delay: 0,
85
- children: /* @__PURE__ */ jsx("div", {
86
- ref,
87
- "data-control-ui": "sidebar",
88
- "data-control-family": "sidebar",
89
- "data-slot": "wrapper",
90
- style: wrapperStyle,
91
- className: cn("group/sidebar-wrapper flex min-h-svh w-full", className),
92
- ...props,
93
- children
94
- })
95
- })
96
- });
97
- }
98
19
  function Sidebar({ side = "left", variant, collapsible = "offcanvas", ref, className, children, style, ...props }) {
99
20
  const { isMobile, state, openMobile, setOpenMobile } = useSidebar();
100
21
  const resolvedVariant = variant ?? skinSidebarLayout() ?? "sidebar";
@@ -118,11 +39,6 @@ function Sidebar({ side = "left", variant, collapsible = "offcanvas", ref, class
118
39
  open: openMobile,
119
40
  onOpenChange: setOpenMobile,
120
41
  children: /* @__PURE__ */ jsxs(SheetContent, {
121
- ref,
122
- "data-control-ui": "sidebar",
123
- "data-control-family": "sidebar",
124
- "data-slot": "root",
125
- "data-surface": "panel",
126
42
  side,
127
43
  className: "w-(--sidebar-width) gap-0 p-0",
128
44
  style: mobileSheetStyle,
@@ -130,11 +46,23 @@ function Sidebar({ side = "left", variant, collapsible = "offcanvas", ref, class
130
46
  className: "sr-only",
131
47
  children: [/* @__PURE__ */ jsx(SheetTitle, { children: "Sidebar" }), /* @__PURE__ */ jsx(SheetDescription, { children: "Displays the mobile sidebar." })]
132
48
  }), /* @__PURE__ */ jsx("div", {
49
+ ref,
133
50
  "data-control-ui": "sidebar",
134
51
  "data-control-family": "sidebar",
135
- "data-slot": "inner",
136
- className: "flex h-full w-full flex-col",
137
- children
52
+ "data-slot": "root",
53
+ "data-surface": "panel",
54
+ "data-mobile": "",
55
+ "data-side": side,
56
+ className: cn("flex min-h-0 flex-1 flex-col", className),
57
+ style,
58
+ ...props,
59
+ children: /* @__PURE__ */ jsx("div", {
60
+ "data-control-ui": "sidebar",
61
+ "data-control-family": "sidebar",
62
+ "data-slot": "inner",
63
+ className: "flex min-h-0 flex-1 flex-col",
64
+ children
65
+ })
138
66
  })]
139
67
  })
140
68
  });
@@ -173,11 +101,13 @@ function Sidebar({ side = "left", variant, collapsible = "offcanvas", ref, class
173
101
  });
174
102
  }
175
103
  function SidebarTrigger({ className, onClick, size = "sm", ...props }) {
176
- const { toggleSidebar } = useSidebar();
104
+ const { toggleSidebar, isMobile, openMobile, open } = useSidebar();
177
105
  return /* @__PURE__ */ jsxs(Button, {
178
106
  "data-control-ui": "sidebar",
179
107
  "data-slot": "trigger",
108
+ "data-sidebar-trigger": "",
180
109
  variant: "ghost",
110
+ "aria-expanded": isMobile ? openMobile : open,
181
111
  size,
182
112
  className: cn(sidebarTriggerWidth[size], "px-0", className),
183
113
  onClick: (event) => {
@@ -211,7 +141,7 @@ function SidebarInset({ className, ...props }) {
211
141
  "data-control-ui": "sidebar",
212
142
  "data-control-family": "sidebar",
213
143
  "data-slot": "inset",
214
- className: cn("relative flex w-full flex-1 flex-col", className),
144
+ className: cn("relative flex min-w-0 w-full flex-1 flex-col", className),
215
145
  ...props
216
146
  });
217
147
  }
@@ -249,114 +179,5 @@ function SidebarContent({ className, children, ...props }) {
249
179
  })
250
180
  });
251
181
  }
252
- function SidebarGroup({ className, ...props }) {
253
- return /* @__PURE__ */ jsx("div", {
254
- "data-control-ui": "sidebar",
255
- "data-control-family": "sidebar",
256
- "data-slot": "group",
257
- className: cn("relative flex w-full min-w-0 flex-col", className),
258
- ...props
259
- });
260
- }
261
- function SidebarGroupLabel({ className, render, children, ...props }) {
262
- return useRender({
263
- defaultTagName: "div",
264
- render,
265
- props: {
266
- ...props,
267
- "data-control-ui": "sidebar",
268
- "data-control-family": "sidebar",
269
- "data-slot": "group-label",
270
- className: cn("flex h-[var(--control-h-sm)] shrink-0 items-center [&>svg]:size-4 [&>svg]:shrink-0", "group-data-[collapsible=icon]:-mt-[var(--control-h-sm)] group-data-[collapsible=icon]:opacity-0", className),
271
- children
272
- }
273
- });
274
- }
275
- const SidebarMenuContext = createContext("none");
276
- function SidebarMenu({ className, indicator, children, ...props }) {
277
- const resolvedIndicator = indicator ?? skinIndicator("sidebar") ?? "none";
278
- const sliding = resolvedIndicator === "slide";
279
- const list = /* @__PURE__ */ jsx("ul", {
280
- "data-control-ui": "sidebar",
281
- "data-control-family": "sidebar",
282
- "data-slot": "menu",
283
- "data-indicator": resolvedIndicator,
284
- className: cn("flex w-full min-w-0 flex-col", sliding ? void 0 : className),
285
- ...props,
286
- children: /* @__PURE__ */ jsx(SidebarMenuContext.Provider, {
287
- value: resolvedIndicator,
288
- children
289
- })
290
- });
291
- if (!sliding) return list;
292
- return /* @__PURE__ */ jsxs("div", {
293
- "data-control-ui": "sidebar",
294
- "data-control-family": "sidebar",
295
- "data-slot": "menu-track",
296
- "data-indicator": resolvedIndicator,
297
- className: cn("relative isolate", className),
298
- children: [/* @__PURE__ */ jsx(Suspense, {
299
- fallback: null,
300
- children: /* @__PURE__ */ jsx(TrackHighlight, {
301
- itemSelector: "[data-control-ui=\"sidebar\"][data-slot=\"menu-button\"]",
302
- activeSelector: "[data-control-ui=\"sidebar\"][data-slot=\"menu-button\"][data-active]"
303
- })
304
- }), list]
305
- });
306
- }
307
- function SidebarMenuItem({ className, ...props }) {
308
- return /* @__PURE__ */ jsx("li", {
309
- "data-control-ui": "sidebar",
310
- "data-control-family": "sidebar",
311
- "data-slot": "menu-item",
312
- className: cn("group/menu-item relative", className),
313
- ...props
314
- });
315
- }
316
- const sidebarMenuButtonClasses = cva("peer/menu-button flex w-full items-center overflow-hidden group-data-[collapsible=icon]:px-0! disabled:pointer-events-none aria-disabled:pointer-events-none [&>span:last-child]:truncate [&>svg]:size-4 [&>svg]:shrink-0", {
317
- variants: {
318
- variant: {
319
- default: null,
320
- outline: null
321
- },
322
- size: {
323
- default: "group-data-[collapsible=icon]:size-[var(--control-h-md)]!",
324
- sm: "group-data-[collapsible=icon]:size-[var(--control-h-sm)]!",
325
- lg: "group-data-[collapsible=icon]:size-[var(--control-h-lg)]!"
326
- }
327
- },
328
- defaultVariants: {
329
- variant: "default",
330
- size: "default"
331
- }
332
- });
333
- function SidebarMenuButton({ render, isActive = false, variant = "default", size = "default", tooltip, className, children, ...props }) {
334
- const { isMobile, state } = useSidebar();
335
- const button = useRender({
336
- defaultTagName: "button",
337
- render,
338
- props: {
339
- ...props,
340
- "data-control-ui": "sidebar",
341
- "data-control-family": "sidebar",
342
- "data-slot": "menu-button",
343
- "data-size": size,
344
- "data-variant": variant,
345
- "data-active": isActive || void 0,
346
- className: cn(sidebarMenuButtonClasses({
347
- variant,
348
- size
349
- }), className),
350
- children
351
- }
352
- });
353
- if (!tooltip) return button;
354
- return /* @__PURE__ */ jsxs(Tooltip, { children: [/* @__PURE__ */ jsx(TooltipTrigger, { render: button }), /* @__PURE__ */ jsx(TooltipContent, {
355
- side: "right",
356
- align: "center",
357
- hidden: state !== "collapsed" || isMobile,
358
- children: tooltip
359
- })] });
360
- }
361
182
  //#endregion
362
- export { Sidebar, SidebarContent, SidebarFooter, SidebarGroup, SidebarGroupLabel, SidebarHeader, SidebarInset, SidebarMenu, SidebarMenuButton, SidebarMenuItem, SidebarProvider, SidebarRail, SidebarTrigger, sidebarMenuButtonSizes, sidebarMenuButtonVariants, useSidebar };
183
+ export { Sidebar, SidebarContent, SidebarFooter, SidebarGroup, SidebarGroupLabel, SidebarHeader, SidebarInset, SidebarMenu, SidebarMenuButton, SidebarMenuItem, SidebarMenuSub, SidebarProvider, SidebarRail, SidebarTrigger, sidebarMenuButtonSizes, sidebarMenuButtonVariants, useSidebar };
@@ -12,9 +12,6 @@ const tableOfContentsVariants = [
12
12
  const DETECTION_MARGIN = "-80px 0px -20% 0px";
13
13
  const TOC_ITEM_SELECTOR = "[data-control-ui=\"table-of-contents\"][data-slot=\"item\"]";
14
14
  const TOC_ACTIVE_SELECTOR = "[data-control-ui=\"table-of-contents\"][data-slot=\"item\"][data-active]";
15
- const tableOfContentsItemClass = "block";
16
- const tableOfContentsHighlightClass = "";
17
- const tableOfContentsTrailClass = "absolute inset-y-0 left-0 w-0.5";
18
15
  function getScrollContainer(el) {
19
16
  let node = el.parentElement;
20
17
  while (node) {
@@ -91,8 +88,6 @@ function TableOfContents({ items, label = "On this page", variant = "both", clas
91
88
  const normalizedItems = normalizeItems(items, Math.min(...collectLevels(items), 2));
92
89
  const targetIds = flattenItems(normalizedItems).map((item) => item.href.replace(/^#/, ""));
93
90
  const activeSet = activeIdsInRange(useVisibleSections(targetIds), targetIds);
94
- const railStyle = style;
95
- const highlightStyle = style;
96
91
  if (items.length === 0) return null;
97
92
  return /* @__PURE__ */ jsxs("nav", {
98
93
  "data-control-ui": "table-of-contents",
@@ -119,8 +114,7 @@ function TableOfContents({ items, label = "On this page", variant = "both", clas
119
114
  "data-control-ui": "table-of-contents",
120
115
  "data-control-family": "table-of-contents",
121
116
  "data-slot": "rail",
122
- className: "pointer-events-none absolute inset-y-0 left-0 -z-20 w-px",
123
- style: railStyle
117
+ className: "pointer-events-none absolute inset-y-0 left-0 -z-20 w-px"
124
118
  }),
125
119
  /* @__PURE__ */ jsx(TrackHighlight, {
126
120
  "data-variant": variant,
@@ -128,14 +122,12 @@ function TableOfContents({ items, label = "On this page", variant = "both", clas
128
122
  activeSelector: TOC_ACTIVE_SELECTOR,
129
123
  range: true,
130
124
  followHover: false,
131
- style: highlightStyle,
132
- className: tableOfContentsHighlightClass,
133
125
  children: variant !== "background" && /* @__PURE__ */ jsx("div", {
134
126
  "aria-hidden": true,
135
127
  "data-control-ui": "table-of-contents",
136
128
  "data-control-family": "table-of-contents",
137
129
  "data-slot": "trail",
138
- className: tableOfContentsTrailClass
130
+ className: "absolute inset-y-0 left-0 w-0.5"
139
131
  })
140
132
  }),
141
133
  /* @__PURE__ */ jsx(TocList, {
@@ -167,7 +159,7 @@ function TocList({ items, activeSet, variant, root = false }) {
167
159
  "data-depth": item.depth,
168
160
  "aria-current": isActive ? "location" : void 0,
169
161
  href: item.href,
170
- className: tableOfContentsItemClass,
162
+ className: "block",
171
163
  children: item.label
172
164
  }), item.children && /* @__PURE__ */ jsx(TocList, {
173
165
  items: item.children,