@ctrl-ui/react 0.8.13 → 0.8.14

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.
@@ -23,8 +23,6 @@ function useColorArea(onChange, targetRef) {
23
23
  function onEnd() {
24
24
  setDragging(false);
25
25
  }
26
- const previousSelect = document.body.style.userSelect;
27
- document.body.style.userSelect = "none";
28
26
  window.addEventListener("pointermove", onMove);
29
27
  window.addEventListener("pointerup", onEnd);
30
28
  window.addEventListener("pointercancel", onEnd);
@@ -32,7 +30,6 @@ function useColorArea(onChange, targetRef) {
32
30
  window.removeEventListener("pointermove", onMove);
33
31
  window.removeEventListener("pointerup", onEnd);
34
32
  window.removeEventListener("pointercancel", onEnd);
35
- document.body.style.userSelect = previousSelect;
36
33
  };
37
34
  }, [dragging, areaRef]);
38
35
  function onPointerDown(event) {
@@ -145,7 +145,10 @@ async function highlightToTokens(code, language) {
145
145
  const key = `${lang}\n${code}`;
146
146
  const cached = cacheGet(key);
147
147
  if (cached !== void 0) return cached;
148
- const { tokens } = (await getHighlighter()).codeToTokens(code, {
148
+ const highlighter = await getHighlighter();
149
+ const shared = cacheGet(key);
150
+ if (shared !== void 0) return shared;
151
+ const { tokens } = highlighter.codeToTokens(code, {
149
152
  lang,
150
153
  theme: CODE_THEME_NAME
151
154
  });
@@ -0,0 +1,7 @@
1
+ import { PointerEvent } from "react";
2
+ import { BaseUIEvent } from "@base-ui/react/types";
3
+ //#region src/lib/popup-item-focus.d.ts
4
+ export declare const popupItemFocusProps: {
5
+ onPointerLeave(event: BaseUIEvent<PointerEvent<HTMLElement>>): void;
6
+ };
7
+ //#endregion
@@ -0,0 +1,9 @@
1
+ //#region src/lib/popup-item-focus.ts
2
+ const popupItemFocusProps = { onPointerLeave(event) {
3
+ if (event.pointerType === "touch" || !(event.relatedTarget instanceof Element)) return;
4
+ const nextItem = event.relatedTarget.closest("[role=\"option\"], [role=\"menuitem\"], [role=\"menuitemcheckbox\"], [role=\"menuitemradio\"]");
5
+ const list = event.currentTarget.closest("[role=\"listbox\"], [role=\"menu\"]");
6
+ if (nextItem && list && nextItem.closest("[role=\"listbox\"], [role=\"menu\"]") === list) event.preventBaseUIHandler();
7
+ } };
8
+ //#endregion
9
+ export { popupItemFocusProps };
@@ -13,7 +13,7 @@
13
13
  --code-token-comment: oklch(0.48 0.015 285);
14
14
  --code-token-keyword: oklch(0.53 0.2 18);
15
15
  --code-token-parameter: oklch(0.52 0.09 55);
16
- --code-token-function: oklch(0.54 0.17 300);
16
+ --code-token-function: oklch(0.53 0.17 300);
17
17
  --code-token-punctuation: oklch(0.5 0.02 285);
18
18
  --code-token-link: oklch(0.5 0.15 250);
19
19
 
@@ -81,6 +81,17 @@
81
81
  padding: calc(var(--spacing) * 4) calc(var(--spacing) * 4) 0;
82
82
  }
83
83
 
84
+ :where([data-control-family="popup"][data-popup-kind="dialog"][data-slot="body"]),
85
+ :where([data-control-family="popup"][data-popup-kind="alert-dialog"][data-slot="body"]) {
86
+ gap: calc(var(--spacing) * 4);
87
+ padding-inline: calc(var(--spacing) * 4);
88
+ }
89
+
90
+ :where([data-control-family="popup"][data-popup-kind="dialog"][data-slot="body"]:not(:has(~ [data-slot="footer"]))),
91
+ :where([data-control-family="popup"][data-popup-kind="alert-dialog"][data-slot="body"]:not(:has(~ [data-slot="footer"]))) {
92
+ padding-block-end: calc(var(--spacing) * 4);
93
+ }
94
+
84
95
  :where([data-control-family="popup"][data-popup-kind="dialog"][data-slot="footer"]),
85
96
  :where([data-control-family="popup"][data-popup-kind="alert-dialog"][data-slot="footer"]) {
86
97
  gap: calc(var(--spacing) * 2);
@@ -1,3 +1,9 @@
1
+ @property --_popover-viewport-height {
2
+ syntax: "<length> | auto";
3
+ inherits: false;
4
+ initial-value: auto;
5
+ }
6
+
1
7
  @layer components {
2
8
  :where([data-control-family="popup"][data-popup-kind="popover"][data-slot="viewport"]) {
3
9
  block-size: var(--_popover-viewport-height, auto);
@@ -42,58 +42,68 @@
42
42
  translate: 0 100%;
43
43
  }
44
44
 
45
- :where(
46
- [data-control-family="tabs"][data-slot="root"]:has(> [data-slot="panel"][data-starting-style])
47
- > [data-slot="panel"][inert][data-ending-style]
48
- ) {
49
- translate: 0 0;
50
- transition: none;
51
- }
52
-
53
45
  :where([data-control-family="tabs"][data-slot="panel"][data-slide="panel"][data-starting-style]) {
54
46
  transition: none;
55
47
  }
56
48
 
57
- :where([data-control-family="tabs"][data-slot="root"][data-slide-starting] > [data-slot="panel"][data-slide="panel"]) {
49
+ :where([data-control-family="tabs"][data-slot="panel"][data-slide-starting][data-slide="panel"]) {
58
50
  transition: none;
59
51
  }
60
52
 
61
- :where([data-control-family="tabs"][data-slot="root"][data-slide-starting] > [data-slot="panel"][inert]) {
53
+ :where([data-control-family="tabs"][data-slot="panel"][data-slide-starting][inert]) {
62
54
  translate: 0 0;
63
55
  }
64
56
 
65
- :where(
66
- [data-control-family="tabs"][data-slot="root"][data-slide-starting]
67
- > [data-slot="panel"]:not([inert])[data-activation-direction="right"]
68
- ) {
57
+ :where([data-control-family="tabs"][data-slot="panel"][data-slide-starting]:not([inert])[data-activation-direction="right"]) {
69
58
  translate: 100% 0;
70
59
  }
71
60
 
72
- :where(
73
- [data-control-family="tabs"][data-slot="root"][data-slide-starting]
74
- > [data-slot="panel"]:not([inert])[data-activation-direction="left"]
75
- ) {
61
+ :where([data-control-family="tabs"][data-slot="panel"][data-slide-starting]:not([inert])[data-activation-direction="left"]) {
76
62
  translate: -100% 0;
77
63
  }
78
64
 
79
- :where(
80
- [data-control-family="tabs"][data-slot="root"][data-slide-starting]
81
- > [data-slot="panel"]:not([inert])[data-activation-direction="down"]
82
- ) {
65
+ :where([data-control-family="tabs"][data-slot="panel"][data-slide-starting]:not([inert])[data-activation-direction="down"]) {
83
66
  translate: 0 100%;
84
67
  }
85
68
 
86
- :where(
87
- [data-control-family="tabs"][data-slot="root"][data-slide-starting]
88
- > [data-slot="panel"]:not([inert])[data-activation-direction="up"]
89
- ) {
69
+ :where([data-control-family="tabs"][data-slot="panel"][data-slide-starting]:not([inert])[data-activation-direction="up"]) {
90
70
  translate: 0 -100%;
91
71
  }
92
72
 
93
73
  @supports (height: calc-size(auto, size)) {
94
- :where([data-control-family="tabs"][data-slot="root"][data-slide-starting] > [data-slot="panel"][data-slide="panel"]:not([inert])) {
95
- height: var(--aui-slide-prev-height, calc-size(auto, size));
74
+ :where([data-control-family="tabs"][data-slot="panel"][data-slide-starting][data-slide="panel"]:not([inert])) {
75
+ height: var(--_tabs-prev-height);
96
76
  }
97
77
  }
98
78
  }
99
79
  }
80
+
81
+ @property --_tabs-prev-height {
82
+ syntax: "<length>";
83
+ inherits: false;
84
+ initial-value: 0px;
85
+ }
86
+
87
+ @property --_tabs-panel-top {
88
+ syntax: "<length>";
89
+ inherits: false;
90
+ initial-value: 0px;
91
+ }
92
+
93
+ @property --_tabs-panel-left {
94
+ syntax: "<length>";
95
+ inherits: false;
96
+ initial-value: 0px;
97
+ }
98
+
99
+ @property --_tabs-panel-width {
100
+ syntax: "<length>";
101
+ inherits: false;
102
+ initial-value: 0px;
103
+ }
104
+
105
+ @property --_tabs-panel-height {
106
+ syntax: "<length>";
107
+ inherits: false;
108
+ initial-value: 0px;
109
+ }
@@ -183,6 +183,7 @@
183
183
  }
184
184
 
185
185
  :where([data-control-family="tabs"][data-slot="panel"]) {
186
+ min-height: 0;
186
187
  outline-style: none;
187
188
  }
188
189
 
@@ -832,3 +832,34 @@
832
832
  }
833
833
  }
834
834
  }
835
+
836
+ /* Measured panel and list dimensions are consumed locally. */
837
+ @property --collapsible-panel-height {
838
+ syntax: "<length> | auto";
839
+ inherits: false;
840
+ initial-value: auto;
841
+ }
842
+
843
+ @property --collapsible-panel-width {
844
+ syntax: "<length> | auto";
845
+ inherits: false;
846
+ initial-value: auto;
847
+ }
848
+
849
+ @property --accordion-panel-height {
850
+ syntax: "<length> | auto";
851
+ inherits: false;
852
+ initial-value: auto;
853
+ }
854
+
855
+ @property --accordion-panel-width {
856
+ syntax: "<length> | auto";
857
+ inherits: false;
858
+ initial-value: auto;
859
+ }
860
+
861
+ @property --cmdk-list-height {
862
+ syntax: "<length>";
863
+ inherits: false;
864
+ initial-value: 0px;
865
+ }
@@ -23,6 +23,9 @@ export declare function AlertDialogContent({ className, children, ...props }: Al
23
23
  export declare function AlertDialogHeader({ className, ...props }: ComponentProps<"div"> & {
24
24
  style?: CSSProperties & PopupKnobStyle;
25
25
  }): import("react").JSX.Element;
26
+ export declare function AlertDialogBody({ className, ...props }: ComponentProps<"div"> & {
27
+ style?: CSSProperties & PopupKnobStyle;
28
+ }): import("react").JSX.Element;
26
29
  export declare function AlertDialogFooter({ className, ...props }: ComponentProps<"div"> & {
27
30
  style?: CSSProperties & PopupKnobStyle;
28
31
  }): import("react").JSX.Element;
@@ -68,6 +68,16 @@ function AlertDialogHeader({ className, ...props }) {
68
68
  ...props
69
69
  });
70
70
  }
71
+ function AlertDialogBody({ className, ...props }) {
72
+ return /* @__PURE__ */ jsx("div", {
73
+ "data-control-ui": "alert-dialog",
74
+ "data-control-family": "popup",
75
+ "data-popup-kind": "alert-dialog",
76
+ "data-slot": "body",
77
+ className: cn("grid", className),
78
+ ...props
79
+ });
80
+ }
71
81
  function AlertDialogFooter({ className, ...props }) {
72
82
  return /* @__PURE__ */ jsx("div", {
73
83
  "data-control-ui": "alert-dialog",
@@ -99,4 +109,4 @@ function AlertDialogDescription({ className, ...props }) {
99
109
  });
100
110
  }
101
111
  //#endregion
102
- export { AlertDialog, AlertDialogClose, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, AlertDialogTrigger };
112
+ export { AlertDialog, AlertDialogBody, AlertDialogClose, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, AlertDialogTrigger };
@@ -75,7 +75,7 @@ export declare function ContextMenuContent({ className, children, ...props }: Co
75
75
  export declare function ContextMenuItem({ className, inset, ...props }: ContextMenuItemProps): import("react").JSX.Element;
76
76
  export declare function ContextMenuCheckboxItem({ className, children, ...props }: ContextMenuCheckboxItemProps): import("react").JSX.Element;
77
77
  export declare function ContextMenuRadioGroup<TValue extends string = string>({ className, ...props }: ContextMenuRadioGroupProps<TValue>): import("react").JSX.Element;
78
- export declare function ContextMenuRadioItem({ className, children, ...props }: ContextMenuRadioItemProps): import("react").JSX.Element;
78
+ export declare function ContextMenuRadioItem({ className, children, value, ...props }: ContextMenuRadioItemProps): import("react").JSX.Element;
79
79
  export declare function ContextMenuLabel({ className, inset, ...props }: ContextMenuLabelProps): import("react").JSX.Element;
80
80
  export declare function ContextMenuSeparator({ className, ...props }: ContextMenuSeparatorProps): import("react").JSX.Element;
81
81
  export declare function ContextMenuShortcut({ className, ...props }: ContextMenuShortcutProps): import("react").JSX.Element;
@@ -3,7 +3,9 @@ import { cn } from "../lib/cn.js";
3
3
  import { controlEffectsAttribute } from "../skin.js";
4
4
  import { useSkin } from "../skin-provider.js";
5
5
  import { popupItemStructureClasses } from "../surface-variants.js";
6
+ import { popupItemFocusProps } from "../lib/popup-item-focus.js";
6
7
  import { jsx, jsxs } from "react/jsx-runtime";
8
+ import { mergeProps } from "@base-ui/react/merge-props";
7
9
  import { ContextMenu as ContextMenu$1 } from "@base-ui/react/context-menu";
8
10
  //#region src/ui/context-menu.tsx
9
11
  const popupClasses = "min-w-[10rem]";
@@ -63,7 +65,7 @@ function ContextMenuItem({ className, inset = false, ...props }) {
63
65
  "data-popup-part": "item",
64
66
  "data-inset": inset || void 0,
65
67
  className: cn(itemClasses, className),
66
- ...props
68
+ ...mergeProps(popupItemFocusProps, props)
67
69
  });
68
70
  }
69
71
  function ContextMenuCheckboxItem({ className, children, ...props }) {
@@ -74,7 +76,7 @@ function ContextMenuCheckboxItem({ className, children, ...props }) {
74
76
  "data-control-family": "popup",
75
77
  "data-popup-part": "item",
76
78
  className: cn(itemClasses, className),
77
- ...props,
79
+ ...mergeProps(popupItemFocusProps, props),
78
80
  children: [/* @__PURE__ */ jsx("span", {
79
81
  className: "pointer-events-none absolute start-2 flex size-4 items-center justify-center",
80
82
  children: /* @__PURE__ */ jsx(ContextMenu$1.CheckboxItemIndicator, { children: /* @__PURE__ */ jsx("svg", {
@@ -103,15 +105,16 @@ function ContextMenuRadioGroup({ className, ...props }) {
103
105
  ...props
104
106
  });
105
107
  }
106
- function ContextMenuRadioItem({ className, children, ...props }) {
108
+ function ContextMenuRadioItem({ className, children, value, ...props }) {
107
109
  return /* @__PURE__ */ jsxs(ContextMenu$1.RadioItem, {
110
+ value,
108
111
  "data-control-ui": "context-menu",
109
112
  "data-popup-kind": "context-menu",
110
113
  "data-slot": "radio-item",
111
114
  "data-control-family": "popup",
112
115
  "data-popup-part": "item",
113
116
  className: cn(itemClasses, className),
114
- ...props,
117
+ ...mergeProps(popupItemFocusProps, props),
115
118
  children: [/* @__PURE__ */ jsx("span", {
116
119
  className: "pointer-events-none absolute start-2 flex size-4 items-center justify-center",
117
120
  children: /* @__PURE__ */ jsx(ContextMenu$1.RadioItemIndicator, { children: /* @__PURE__ */ jsx("span", {
@@ -27,6 +27,9 @@ export declare function DialogContent({ className, children, showCloseButton, cl
27
27
  export declare function DialogHeader({ className, ...props }: ComponentProps<"div"> & {
28
28
  style?: CSSProperties & PopupKnobStyle;
29
29
  }): import("react").JSX.Element;
30
+ export declare function DialogBody({ className, ...props }: ComponentProps<"div"> & {
31
+ style?: CSSProperties & PopupKnobStyle;
32
+ }): import("react").JSX.Element;
30
33
  export declare function DialogFooter({ className, ...props }: ComponentProps<"div"> & {
31
34
  style?: CSSProperties & PopupKnobStyle;
32
35
  }): import("react").JSX.Element;
package/dist/ui/dialog.js CHANGED
@@ -73,6 +73,16 @@ function DialogHeader({ className, ...props }) {
73
73
  ...props
74
74
  });
75
75
  }
76
+ function DialogBody({ className, ...props }) {
77
+ return /* @__PURE__ */ jsx("div", {
78
+ "data-control-ui": "dialog",
79
+ "data-control-family": "popup",
80
+ "data-popup-kind": "dialog",
81
+ "data-slot": "body",
82
+ className: cn("grid", className),
83
+ ...props
84
+ });
85
+ }
76
86
  function DialogFooter({ className, ...props }) {
77
87
  return /* @__PURE__ */ jsx("div", {
78
88
  "data-control-ui": "dialog",
@@ -104,4 +114,4 @@ function DialogDescription({ className, ...props }) {
104
114
  });
105
115
  }
106
116
  //#endregion
107
- export { Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DialogTrigger };
117
+ export { Dialog, DialogBody, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DialogTrigger };
@@ -44,7 +44,7 @@ export declare function DropdownMenuPortal(props: Menu.Portal.Props): import("re
44
44
  export declare function DropdownMenuGroup(props: DropdownMenuGroupProps): import("react").JSX.Element;
45
45
  export declare function DropdownMenuCheckboxItem({ className, children, ...props }: DropdownMenuCheckboxItemProps): import("react").JSX.Element;
46
46
  export declare function DropdownMenuRadioGroup(props: DropdownMenuRadioGroupProps): import("react").JSX.Element;
47
- export declare function DropdownMenuRadioItem({ className, children, ...props }: DropdownMenuRadioItemProps): import("react").JSX.Element;
47
+ export declare function DropdownMenuRadioItem({ className, children, value, ...props }: DropdownMenuRadioItemProps): import("react").JSX.Element;
48
48
  export declare function DropdownMenuSub(props: DropdownMenuSubProps): import("react").JSX.Element;
49
49
  export declare function DropdownMenuSubTrigger({ className, children, ...props }: DropdownMenuSubTriggerProps): import("react").JSX.Element;
50
50
  export declare function DropdownMenuSubContent(props: DropdownMenuSubContentProps): import("react").JSX.Element;
@@ -3,7 +3,9 @@ import { cn } from "../lib/cn.js";
3
3
  import { controlEffectsAttribute } from "../skin.js";
4
4
  import { useSkin } from "../skin-provider.js";
5
5
  import { popupItemStructureClasses } from "../surface-variants.js";
6
+ import { popupItemFocusProps } from "../lib/popup-item-focus.js";
6
7
  import { jsx, jsxs } from "react/jsx-runtime";
8
+ import { mergeProps } from "@base-ui/react/merge-props";
7
9
  import { Menu } from "@base-ui/react/menu";
8
10
  //#region src/ui/dropdown-menu.tsx
9
11
  const dropdownMenuTriggerVariants = ["surface", "ghost"];
@@ -62,7 +64,7 @@ function DropdownMenuItem({ className, ...props }) {
62
64
  "data-control-family": "popup",
63
65
  "data-popup-part": "item",
64
66
  className: cn(popupItemStructureClasses, className),
65
- ...props
67
+ ...mergeProps(popupItemFocusProps, props)
66
68
  });
67
69
  }
68
70
  function DropdownMenuSeparator({ className, ...props }) {
@@ -103,7 +105,7 @@ function DropdownMenuCheckboxItem({ className, children, ...props }) {
103
105
  "data-popup-part": "item",
104
106
  "data-slot": "checkbox-item",
105
107
  className: cn("relative", popupItemStructureClasses, className),
106
- ...props,
108
+ ...mergeProps(popupItemFocusProps, props),
107
109
  children: [/* @__PURE__ */ jsx(Menu.CheckboxItemIndicator, {
108
110
  className: "pointer-events-none absolute start-2 flex size-4 items-center justify-center",
109
111
  children: /* @__PURE__ */ jsx(DropdownMenuCheck, {})
@@ -118,14 +120,15 @@ function DropdownMenuRadioGroup(props) {
118
120
  ...props
119
121
  });
120
122
  }
121
- function DropdownMenuRadioItem({ className, children, ...props }) {
123
+ function DropdownMenuRadioItem({ className, children, value, ...props }) {
122
124
  return /* @__PURE__ */ jsxs(Menu.RadioItem, {
125
+ value,
123
126
  "data-control-ui": "dropdown-menu",
124
127
  "data-control-family": "popup",
125
128
  "data-popup-part": "item",
126
129
  "data-slot": "radio-item",
127
130
  className: cn("relative", popupItemStructureClasses, className),
128
- ...props,
131
+ ...mergeProps(popupItemFocusProps, props),
129
132
  children: [/* @__PURE__ */ jsx(Menu.RadioItemIndicator, {
130
133
  className: "pointer-events-none absolute start-2 flex size-4 items-center justify-center",
131
134
  children: /* @__PURE__ */ jsx(DropdownMenuCheck, {})
package/dist/ui/item.js CHANGED
@@ -38,7 +38,7 @@ function Item({ variant = "default", render, className, children, ...props }) {
38
38
  "data-control-family": "item",
39
39
  "data-slot": "root",
40
40
  "data-variant": variant,
41
- className: cn("flex items-center [&[href]]:cursor-pointer", className),
41
+ className: cn("flex flex-wrap items-center [&[href]]:cursor-pointer", className),
42
42
  children
43
43
  }
44
44
  });
@@ -1,4 +1,4 @@
1
- import { DialogCloseProps, DialogContentProps, DialogDescription, DialogFooter, DialogHeader, DialogProps, DialogTitle, DialogTrigger } from "./dialog.js";
1
+ import { DialogBody, DialogCloseProps, DialogContentProps, DialogDescription, DialogFooter, DialogHeader, DialogProps, DialogTitle, DialogTrigger } from "./dialog.js";
2
2
  import { ComponentProps } from "react";
3
3
  //#region src/ui/responsive-dialog.d.ts
4
4
  export type ResponsiveDialogProps = DialogProps;
@@ -11,6 +11,7 @@ export declare function ResponsiveDialogTrigger(props: Omit<ComponentProps<typeo
11
11
  export declare function ResponsiveDialogClose({ className, children, variant, size, tone, iconOnly, ...props }: DialogCloseProps): import("react").JSX.Element;
12
12
  export declare function ResponsiveDialogContent({ className, dialogClassName, drawerClassName, children, showCloseButton, closeLabel, ...props }: ResponsiveDialogContentProps): import("react").JSX.Element;
13
13
  export declare function ResponsiveDialogHeader(props: ComponentProps<typeof DialogHeader>): import("react").JSX.Element;
14
+ export declare function ResponsiveDialogBody(props: ComponentProps<typeof DialogBody>): import("react").JSX.Element;
14
15
  export declare function ResponsiveDialogFooter(props: ComponentProps<typeof DialogFooter>): import("react").JSX.Element;
15
16
  export declare function ResponsiveDialogTitle(props: ComponentProps<typeof DialogTitle>): import("react").JSX.Element;
16
17
  export declare function ResponsiveDialogDescription(props: ComponentProps<typeof DialogDescription>): import("react").JSX.Element;
@@ -3,7 +3,7 @@ import { cn } from "../lib/cn.js";
3
3
  import { Button } from "./button.js";
4
4
  import { PopupCloseButton } from "../popup-parts.js";
5
5
  import { Drawer, DrawerBody, DrawerClose, DrawerContent, DrawerDescription, DrawerFooter, DrawerHeader, DrawerTitle, DrawerTrigger } from "./drawer.js";
6
- import { Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DialogTrigger } from "./dialog.js";
6
+ import { Dialog, DialogBody, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DialogTrigger } from "./dialog.js";
7
7
  import { createContext, useContext, useState, useSyncExternalStore } from "react";
8
8
  import { jsx, jsxs } from "react/jsx-runtime";
9
9
  //#region src/ui/responsive-dialog.tsx
@@ -94,6 +94,9 @@ function ResponsiveDialogContent({ className, dialogClassName, drawerClassName,
94
94
  function ResponsiveDialogHeader(props) {
95
95
  return useResponsiveDialogContext() ? /* @__PURE__ */ jsx(DrawerHeader, { ...props }) : /* @__PURE__ */ jsx(DialogHeader, { ...props });
96
96
  }
97
+ function ResponsiveDialogBody(props) {
98
+ return /* @__PURE__ */ jsx(DialogBody, { ...props });
99
+ }
97
100
  function ResponsiveDialogFooter(props) {
98
101
  return useResponsiveDialogContext() ? /* @__PURE__ */ jsx(DrawerFooter, { ...props }) : /* @__PURE__ */ jsx(DialogFooter, { ...props });
99
102
  }
@@ -104,4 +107,4 @@ function ResponsiveDialogDescription(props) {
104
107
  return useResponsiveDialogContext() ? /* @__PURE__ */ jsx(DrawerDescription, { ...props }) : /* @__PURE__ */ jsx(DialogDescription, { ...props });
105
108
  }
106
109
  //#endregion
107
- export { ResponsiveDialog, ResponsiveDialogClose, ResponsiveDialogContent, ResponsiveDialogDescription, ResponsiveDialogFooter, ResponsiveDialogHeader, ResponsiveDialogTitle, ResponsiveDialogTrigger };
110
+ export { ResponsiveDialog, ResponsiveDialogBody, ResponsiveDialogClose, ResponsiveDialogContent, ResponsiveDialogDescription, ResponsiveDialogFooter, ResponsiveDialogHeader, ResponsiveDialogTitle, ResponsiveDialogTrigger };
package/dist/ui/select.js CHANGED
@@ -5,7 +5,9 @@ import { useSkin } from "../skin-provider.js";
5
5
  import { Button } from "./button.js";
6
6
  import { ScrollArea } from "./scroll-area.js";
7
7
  import { popupItemStructureClasses } from "../surface-variants.js";
8
+ import { popupItemFocusProps } from "../lib/popup-item-focus.js";
8
9
  import { jsx, jsxs } from "react/jsx-runtime";
10
+ import { mergeProps } from "@base-ui/react/merge-props";
9
11
  import { Select as Select$1 } from "@base-ui/react/select";
10
12
  //#region src/ui/select.tsx
11
13
  const selectTriggerVariants = ["surface", "ghost"];
@@ -118,7 +120,7 @@ function SelectItem({ className, children, disabled, ...props }) {
118
120
  "data-popup-part": "item",
119
121
  disabled,
120
122
  className: cn(popupItemStructureClasses, className),
121
- ...props,
123
+ ...mergeProps(popupItemFocusProps, props),
122
124
  children: [/* @__PURE__ */ jsx(Select$1.ItemText, {
123
125
  "data-control-ui": "select",
124
126
  "data-control-family": "popup",
package/dist/ui/tabs.js CHANGED
@@ -18,6 +18,9 @@ function refreshTabsPanelHeight(panel) {
18
18
  if (panel.node.inert || panel.node.hidden) return;
19
19
  panel.height = panel.node.getBoundingClientRect().height;
20
20
  }
21
+ function setTabsPanelsStarting(panels, starting) {
22
+ for (const panel of panels) panel.toggleAttribute("data-slide-starting", starting);
23
+ }
21
24
  const TabsPanelsContext = createContext(null);
22
25
  function useTabsPanels() {
23
26
  const context = useContext(TabsPanelsContext);
@@ -31,17 +34,20 @@ function setRef(ref, value) {
31
34
  function Tabs({ className, onValueChange, children, ...props }) {
32
35
  const rootRef = useRef(null);
33
36
  const activePanelRef = useRef(null);
37
+ const startingPanelsRef = useRef([]);
38
+ const previousHeightRef = useRef(null);
34
39
  const clearPreviousHeightFrame = useRef(0);
35
40
  const [exitingValue, setExitingValue] = useState(null);
36
41
  const [holdPreviousHeight] = useState(() => (height) => {
37
- const root = rootRef.current;
38
- if (!root) return;
39
- root.style.setProperty("--aui-slide-prev-height", height);
42
+ if (!rootRef.current) return;
43
+ previousHeightRef.current = height;
40
44
  cancelAnimationFrame(clearPreviousHeightFrame.current);
41
45
  clearPreviousHeightFrame.current = requestAnimationFrame(() => {
42
46
  clearPreviousHeightFrame.current = requestAnimationFrame(() => {
43
- root.style.removeProperty("--aui-slide-prev-height");
44
- root.removeAttribute("data-slide-starting");
47
+ previousHeightRef.current = null;
48
+ activePanelRef.current?.node.style.removeProperty("--_tabs-prev-height");
49
+ setTabsPanelsStarting(startingPanelsRef.current, false);
50
+ startingPanelsRef.current = [];
45
51
  });
46
52
  });
47
53
  });
@@ -49,10 +55,14 @@ function Tabs({ className, onValueChange, children, ...props }) {
49
55
  const [registerPanel] = useState(() => (value, node) => {
50
56
  if (!(node && !node.inert && !node.hidden)) return;
51
57
  const previousPanel = activePanelRef.current;
52
- const root = rootRef.current;
53
- if (root && previousPanel && previousPanel.value !== value) {
54
- root.setAttribute("data-slide-starting", "");
55
- holdPreviousHeight(root.style.getPropertyValue("--aui-slide-prev-height") || `${previousPanel.height}px`);
58
+ const switchingPanels = rootRef.current && previousPanel && previousPanel.value !== value;
59
+ if (switchingPanels) {
60
+ setTabsPanelsStarting(startingPanelsRef.current, false);
61
+ startingPanelsRef.current = [previousPanel.node, node];
62
+ setTabsPanelsStarting(startingPanelsRef.current, true);
63
+ const previousHeight = previousHeightRef.current || `${previousPanel.height}px`;
64
+ node.style.setProperty("--_tabs-prev-height", previousHeight);
65
+ holdPreviousHeight(previousHeight);
56
66
  setExitingValue(previousPanel.value);
57
67
  }
58
68
  activePanelRef.current = {
@@ -60,11 +70,12 @@ function Tabs({ className, onValueChange, children, ...props }) {
60
70
  node,
61
71
  height: node.getBoundingClientRect().height
62
72
  };
63
- if (root) {
64
- root.style.setProperty("--_tabs-panel-top", `${node.offsetTop}px`);
65
- root.style.setProperty("--_tabs-panel-left", `${node.offsetLeft}px`);
66
- root.style.setProperty("--_tabs-panel-width", `${node.offsetWidth}px`);
67
- root.style.setProperty("--_tabs-panel-height", `${node.offsetHeight}px`);
73
+ if (switchingPanels) {
74
+ const { offsetTop, offsetLeft, offsetWidth, offsetHeight } = node;
75
+ previousPanel.node.style.setProperty("--_tabs-panel-top", `${offsetTop}px`);
76
+ previousPanel.node.style.setProperty("--_tabs-panel-left", `${offsetLeft}px`);
77
+ previousPanel.node.style.setProperty("--_tabs-panel-width", `${offsetWidth}px`);
78
+ previousPanel.node.style.setProperty("--_tabs-panel-height", `${offsetHeight}px`);
68
79
  }
69
80
  return () => {
70
81
  const currentPanel = activePanelRef.current;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ctrl-ui/react",
3
- "version": "0.8.13",
3
+ "version": "0.8.14",
4
4
  "description": "Control UI components, blocks, and primitives with neutral defaults and consumer-owned themes.",
5
5
  "license": "MIT",
6
6
  "repository": {