@01.software/ui 0.2.0 → 0.2.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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # @01.software/ui
2
2
 
3
+ ## 0.2.1
4
+
5
+ ### Patch Changes
6
+
7
+ - f27ede2: Keep the newly opened `Menubar` menu open when the pointer moves between open menus while the previous menu plays its exit motion.
8
+
3
9
  ## 0.2.0
4
10
 
5
11
  ### Minor Changes
package/dist/menubar.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { ComponentProps } from 'react';
1
+ import { type ComponentProps } from 'react';
2
2
  import { Menubar as MenubarPrimitive } from 'radix-ui';
3
3
  declare const MenubarMenu: typeof MenubarPrimitive.Menu;
4
4
  declare const MenubarGroup: import("react").ForwardRefExoticComponent<MenubarPrimitive.MenubarGroupProps & import("react").RefAttributes<HTMLDivElement>>;
@@ -6,7 +6,7 @@ declare const MenubarRadioGroup: import("react").ForwardRefExoticComponent<Menub
6
6
  declare const MenubarSub: import("react").FC<MenubarPrimitive.MenubarSubProps>;
7
7
  declare function Menubar({ className, ...props }: ComponentProps<typeof MenubarPrimitive.Root>): import("react/jsx-runtime").JSX.Element;
8
8
  declare function MenubarTrigger({ className, ...props }: ComponentProps<typeof MenubarPrimitive.Trigger>): import("react/jsx-runtime").JSX.Element;
9
- declare function MenubarContent({ className, portalLabel, align, sideOffset, collisionPadding, ...props }: ComponentProps<typeof MenubarPrimitive.Content> & {
9
+ declare function MenubarContent({ className, portalLabel, align, sideOffset, collisionPadding, ref: forwardedRef, onFocusOutside, onPointerDownOutside, ...props }: ComponentProps<typeof MenubarPrimitive.Content> & {
10
10
  portalLabel?: string;
11
11
  }): import("react/jsx-runtime").JSX.Element;
12
12
  declare function MenubarItem({ className, inset, variant, ...props }: ComponentProps<typeof MenubarPrimitive.Item> & {
package/dist/menubar.js CHANGED
@@ -1,5 +1,6 @@
1
1
  'use client';
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { useCallback, useRef, } from 'react';
3
4
  import { Menubar as MenubarPrimitive } from 'radix-ui';
4
5
  import { Check, ChevronRight } from 'lucide-react';
5
6
  import { cn } from './internal/cn.js';
@@ -17,8 +18,45 @@ function Menubar({ className, ...props }) {
17
18
  function MenubarTrigger({ className, ...props }) {
18
19
  return (_jsx(MenubarPrimitive.Trigger, { "data-slot": "menubar-trigger", className: cn('data-[state=open]:bg-foreground/10 focus-visible:bg-foreground/10 min-h-6 cursor-default rounded-sm px-2 py-0.5 no-underline outline-none hover:no-underline focus-visible:outline-2 focus-visible:outline-offset-[-2px] focus-visible:outline-[var(--ink)] focus-visible:outline-solid disabled:opacity-40', className), ...props }));
19
20
  }
20
- function MenubarContent({ className, portalLabel, align = 'start', sideOffset = 4, collisionPadding = 16, ...props }) {
21
- return (_jsx(MenuContentPortal, { label: portalLabel, children: _jsx(MenubarPrimitive.Content, { "data-slot": "menubar-content", align: align, sideOffset: sideOffset, collisionPadding: collisionPadding, className: cn(menuContentClassName, 'max-h-(--radix-menubar-content-available-height)', className), ...props }) }));
21
+ /**
22
+ * Presence keeps a closing menu mounted during its exit motion. Moving between
23
+ * open menus must not let that closing layer dismiss the menu replacing it.
24
+ */
25
+ function useClosingLayerGuard(forwardedRef) {
26
+ const content = useRef(null);
27
+ // Stable, cleanup-preserving composition like Radix composeRefs.
28
+ const ref = useCallback((node) => {
29
+ content.current = node;
30
+ if (typeof forwardedRef === 'function') {
31
+ const cleanup = forwardedRef(node);
32
+ return () => {
33
+ content.current = null;
34
+ if (typeof cleanup === 'function')
35
+ cleanup();
36
+ else
37
+ forwardedRef(null);
38
+ };
39
+ }
40
+ if (forwardedRef)
41
+ forwardedRef.current = node;
42
+ return () => {
43
+ content.current = null;
44
+ if (forwardedRef)
45
+ forwardedRef.current = null;
46
+ };
47
+ }, [forwardedRef]);
48
+ function guard(handler) {
49
+ return (event) => {
50
+ handler?.(event);
51
+ if (content.current?.dataset.state === 'closed')
52
+ event.preventDefault();
53
+ };
54
+ }
55
+ return { ref, guard };
56
+ }
57
+ function MenubarContent({ className, portalLabel, align = 'start', sideOffset = 4, collisionPadding = 16, ref: forwardedRef, onFocusOutside, onPointerDownOutside, ...props }) {
58
+ const { ref, guard } = useClosingLayerGuard(forwardedRef);
59
+ return (_jsx(MenuContentPortal, { label: portalLabel, children: _jsx(MenubarPrimitive.Content, { ref: ref, "data-slot": "menubar-content", align: align, sideOffset: sideOffset, collisionPadding: collisionPadding, onFocusOutside: guard(onFocusOutside), onPointerDownOutside: guard(onPointerDownOutside), className: cn(menuContentClassName, 'max-h-(--radix-menubar-content-available-height)', className), ...props }) }));
22
60
  }
23
61
  function MenubarItem({ className, inset = false, variant = 'default', ...props }) {
24
62
  return (_jsx(MenubarPrimitive.Item, { "data-slot": "menubar-item", className: cn(menuItemClassName, inset && 'pl-7', variant === 'destructive' && 'text-destructive', className), ...props }));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@01.software/ui",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "description": "Browser UI primitives and precompiled theme styles for React 19.",
5
5
  "type": "module",
6
6
  "sideEffects": [