@enonic/ui 0.16.0 → 0.18.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/dist/enonic-ui.cjs +1 -26
- package/dist/enonic-ui.es.js +62 -6701
- package/dist/styles/preset.css +1 -1
- package/dist/styles/style.css +1 -1
- package/dist/styles/tokens.css +1 -1
- package/dist/types/components/button/button.d.ts +1 -0
- package/dist/types/components/icon-button/icon-button.d.ts +1 -0
- package/dist/types/components/index.d.ts +1 -0
- package/dist/types/components/listbox/listbox.d.ts +8 -3
- package/dist/types/components/menu/menu.d.ts +31 -0
- package/dist/types/components/menubar/menubar.d.ts +111 -0
- package/dist/types/components/toggle/index.d.ts +1 -0
- package/dist/types/components/toggle/toggle.d.ts +13 -0
- package/dist/types/hooks/index.d.ts +6 -1
- package/dist/types/hooks/use-active-item-focus.d.ts +83 -0
- package/dist/types/hooks/use-click-outside.d.ts +99 -0
- package/dist/types/hooks/use-floating-position.d.ts +58 -0
- package/dist/types/hooks/use-roving-tabindex.d.ts +69 -0
- package/dist/types/hooks/use-scroll-active-into-view.d.ts +83 -0
- package/dist/types/providers/listbox-provider.d.ts +6 -1
- package/dist/types/providers/menubar-provider.d.ts +2 -5
- package/package.json +27 -27
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { RefObject } from 'react';
|
|
2
|
+
export type UseActiveItemFocusConfig = {
|
|
3
|
+
/** Reference to the item element to focus */
|
|
4
|
+
ref: RefObject<HTMLElement> | null;
|
|
5
|
+
/** Whether this item is currently active */
|
|
6
|
+
isActive: boolean;
|
|
7
|
+
/** Whether this item is disabled */
|
|
8
|
+
disabled: boolean;
|
|
9
|
+
/**
|
|
10
|
+
* Focus mode - determines when to auto-focus:
|
|
11
|
+
* - 'roving-tabindex': Auto-focus when active (default)
|
|
12
|
+
* - 'activedescendant': Don't auto-focus (container manages focus)
|
|
13
|
+
*/
|
|
14
|
+
focusMode?: 'roving-tabindex' | 'activedescendant';
|
|
15
|
+
/**
|
|
16
|
+
* When true, only focus if focus is already within the container.
|
|
17
|
+
* This prevents mouse hover from causing focus rings when navigating with keyboard.
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* In Listbox, we only want to auto-focus during keyboard navigation,
|
|
21
|
+
* not when the user hovers with their mouse. We check if focus is
|
|
22
|
+
* already within the listbox to determine if keyboard nav is active.
|
|
23
|
+
*/
|
|
24
|
+
checkFocusWithin?: {
|
|
25
|
+
/** Enable the focus-within check */
|
|
26
|
+
enabled: boolean;
|
|
27
|
+
/** ARIA role of the container to check (e.g., 'listbox', 'menu') */
|
|
28
|
+
containerRole: string;
|
|
29
|
+
};
|
|
30
|
+
};
|
|
31
|
+
/**
|
|
32
|
+
* Automatically focuses an element when it becomes active, typically used
|
|
33
|
+
* in keyboard navigation patterns like roving tabindex.
|
|
34
|
+
*
|
|
35
|
+
* This hook handles the common pattern where an item should receive DOM focus
|
|
36
|
+
* when it becomes the "active" item in a list, menu, or navigation structure.
|
|
37
|
+
* It includes safeguards to:
|
|
38
|
+
* - Only focus when not disabled
|
|
39
|
+
* - Only focus when not already focused (prevents infinite loops)
|
|
40
|
+
* - Optionally check if focus is within the container (prevents hover-induced focus)
|
|
41
|
+
* - Respect focus mode (roving-tabindex vs activedescendant)
|
|
42
|
+
*
|
|
43
|
+
* @param config - Configuration object for auto-focus behavior
|
|
44
|
+
*
|
|
45
|
+
* @example
|
|
46
|
+
* ```tsx
|
|
47
|
+
* // Basic usage (Menu item)
|
|
48
|
+
* function MenuItem() {
|
|
49
|
+
* const itemRef = useRef<HTMLDivElement>(null);
|
|
50
|
+
* const { active } = useMenu();
|
|
51
|
+
* const isActive = active === id;
|
|
52
|
+
*
|
|
53
|
+
* useActiveItemFocus({
|
|
54
|
+
* ref: itemRef,
|
|
55
|
+
* isActive,
|
|
56
|
+
* disabled: false,
|
|
57
|
+
* });
|
|
58
|
+
*
|
|
59
|
+
* return <div ref={itemRef}>Item</div>;
|
|
60
|
+
* }
|
|
61
|
+
*
|
|
62
|
+
* // With focus-within check (Listbox item)
|
|
63
|
+
* function ListboxItem() {
|
|
64
|
+
* const itemRef = useRef<HTMLDivElement>(null);
|
|
65
|
+
* const { active, focusMode } = useListbox();
|
|
66
|
+
* const isActive = active === id;
|
|
67
|
+
*
|
|
68
|
+
* useActiveItemFocus({
|
|
69
|
+
* ref: itemRef,
|
|
70
|
+
* isActive,
|
|
71
|
+
* disabled: false,
|
|
72
|
+
* focusMode,
|
|
73
|
+
* checkFocusWithin: {
|
|
74
|
+
* enabled: true,
|
|
75
|
+
* containerRole: 'listbox',
|
|
76
|
+
* },
|
|
77
|
+
* });
|
|
78
|
+
*
|
|
79
|
+
* return <div ref={itemRef}>Item</div>;
|
|
80
|
+
* }
|
|
81
|
+
* ```
|
|
82
|
+
*/
|
|
83
|
+
export declare function useActiveItemFocus({ ref, isActive, disabled, focusMode, checkFocusWithin, }: UseActiveItemFocusConfig): void;
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { RefObject } from 'react';
|
|
2
|
+
export type UseClickOutsideConfig = {
|
|
3
|
+
/** Whether the click outside listener is active */
|
|
4
|
+
enabled: boolean;
|
|
5
|
+
/** Reference to the content element (clicks inside are ignored) */
|
|
6
|
+
contentRef: RefObject<HTMLElement>;
|
|
7
|
+
/**
|
|
8
|
+
* Optional references to elements that should be excluded from "outside" detection.
|
|
9
|
+
* Typically used for trigger buttons that toggle the content visibility.
|
|
10
|
+
*/
|
|
11
|
+
excludeRefs?: (RefObject<HTMLElement> | undefined)[];
|
|
12
|
+
/** Callback when pointer down occurs outside */
|
|
13
|
+
onPointerDownOutside?: (event: PointerEvent) => void;
|
|
14
|
+
/** Callback when any interaction occurs outside */
|
|
15
|
+
onInteractOutside?: (event: Event) => void;
|
|
16
|
+
/**
|
|
17
|
+
* Callback to close/hide the content.
|
|
18
|
+
* Only called if event.defaultPrevented is false.
|
|
19
|
+
*/
|
|
20
|
+
onClose?: () => void;
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* Detects clicks/pointer events outside a content element and triggers callbacks.
|
|
24
|
+
*
|
|
25
|
+
* This hook is commonly used for dismissible UI elements like dropdowns, menus,
|
|
26
|
+
* dialogs, and popovers that should close when the user clicks outside.
|
|
27
|
+
*
|
|
28
|
+
* Features:
|
|
29
|
+
* - Ignores clicks inside the content element
|
|
30
|
+
* - Supports excluding additional elements (e.g., trigger buttons)
|
|
31
|
+
* - Respects event.defaultPrevented to allow custom handling
|
|
32
|
+
* - Only active when enabled
|
|
33
|
+
* - Properly cleans up event listeners
|
|
34
|
+
*
|
|
35
|
+
* @param config - Configuration object for click outside detection
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* ```tsx
|
|
39
|
+
* // Basic usage (Dialog)
|
|
40
|
+
* function Dialog() {
|
|
41
|
+
* const [open, setOpen] = useState(false);
|
|
42
|
+
* const contentRef = useRef<HTMLDivElement>(null);
|
|
43
|
+
*
|
|
44
|
+
* useClickOutside({
|
|
45
|
+
* enabled: open,
|
|
46
|
+
* contentRef,
|
|
47
|
+
* onClose: () => setOpen(false),
|
|
48
|
+
* });
|
|
49
|
+
*
|
|
50
|
+
* if (!open) return null;
|
|
51
|
+
* return <div ref={contentRef}>Dialog content</div>;
|
|
52
|
+
* }
|
|
53
|
+
*
|
|
54
|
+
* // With trigger exclusion (Menu)
|
|
55
|
+
* function Menu() {
|
|
56
|
+
* const [open, setOpen] = useState(false);
|
|
57
|
+
* const triggerRef = useRef<HTMLButtonElement>(null);
|
|
58
|
+
* const contentRef = useRef<HTMLDivElement>(null);
|
|
59
|
+
*
|
|
60
|
+
* useClickOutside({
|
|
61
|
+
* enabled: open,
|
|
62
|
+
* contentRef,
|
|
63
|
+
* excludeRefs: [triggerRef],
|
|
64
|
+
* onPointerDownOutside: (e) => console.log('Outside click', e),
|
|
65
|
+
* onInteractOutside: (e) => console.log('Outside interaction', e),
|
|
66
|
+
* onClose: () => setOpen(false),
|
|
67
|
+
* });
|
|
68
|
+
*
|
|
69
|
+
* return (
|
|
70
|
+
* <>
|
|
71
|
+
* <button ref={triggerRef}>Open Menu</button>
|
|
72
|
+
* {open && <div ref={contentRef}>Menu content</div>}
|
|
73
|
+
* </>
|
|
74
|
+
* );
|
|
75
|
+
* }
|
|
76
|
+
*
|
|
77
|
+
* // With custom close prevention
|
|
78
|
+
* function CustomDialog() {
|
|
79
|
+
* const [open, setOpen] = useState(false);
|
|
80
|
+
* const contentRef = useRef<HTMLDivElement>(null);
|
|
81
|
+
*
|
|
82
|
+
* useClickOutside({
|
|
83
|
+
* enabled: open,
|
|
84
|
+
* contentRef,
|
|
85
|
+
* onPointerDownOutside: (e) => {
|
|
86
|
+
* const shouldClose = confirm('Close dialog?');
|
|
87
|
+
* if (!shouldClose) {
|
|
88
|
+
* e.preventDefault(); // Prevents onClose from being called
|
|
89
|
+
* }
|
|
90
|
+
* },
|
|
91
|
+
* onClose: () => setOpen(false),
|
|
92
|
+
* });
|
|
93
|
+
*
|
|
94
|
+
* if (!open) return null;
|
|
95
|
+
* return <div ref={contentRef}>Dialog content</div>;
|
|
96
|
+
* }
|
|
97
|
+
* ```
|
|
98
|
+
*/
|
|
99
|
+
export declare function useClickOutside({ enabled, contentRef, excludeRefs, onPointerDownOutside, onInteractOutside, onClose, }: UseClickOutsideConfig): void;
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { RefObject } from 'react';
|
|
2
|
+
export type FloatingPosition = {
|
|
3
|
+
top: number;
|
|
4
|
+
left?: number;
|
|
5
|
+
right?: number;
|
|
6
|
+
};
|
|
7
|
+
export type UseFloatingPositionConfig = {
|
|
8
|
+
/** Whether the floating element is open/visible */
|
|
9
|
+
enabled: boolean;
|
|
10
|
+
/** Reference to the trigger element */
|
|
11
|
+
triggerRef: RefObject<HTMLElement> | null;
|
|
12
|
+
/** Reference to the floating content element */
|
|
13
|
+
contentRef: RefObject<HTMLElement> | null;
|
|
14
|
+
/** Horizontal alignment relative to trigger */
|
|
15
|
+
align?: 'start' | 'end';
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* Calculates optimal position for floating elements (menus, dropdowns) relative to a trigger,
|
|
19
|
+
* with automatic viewport collision detection and flip behavior.
|
|
20
|
+
*
|
|
21
|
+
* This hook handles:
|
|
22
|
+
* - Positioning below trigger with configurable alignment
|
|
23
|
+
* - Vertical flipping when overflowing bottom edge
|
|
24
|
+
* - Horizontal adjustment to stay within viewport bounds
|
|
25
|
+
* - Automatic repositioning on window resize and scroll
|
|
26
|
+
*
|
|
27
|
+
* @param config - Configuration object for positioning behavior
|
|
28
|
+
* @returns Position object with top and left/right coordinates, or null if not yet calculated
|
|
29
|
+
*
|
|
30
|
+
* @example
|
|
31
|
+
* ```tsx
|
|
32
|
+
* function Menu() {
|
|
33
|
+
* const triggerRef = useRef<HTMLButtonElement>(null);
|
|
34
|
+
* const contentRef = useRef<HTMLDivElement>(null);
|
|
35
|
+
* const position = useFloatingPosition({
|
|
36
|
+
* enabled: open,
|
|
37
|
+
* triggerRef,
|
|
38
|
+
* contentRef,
|
|
39
|
+
* align: 'start'
|
|
40
|
+
* });
|
|
41
|
+
*
|
|
42
|
+
* return (
|
|
43
|
+
* <div
|
|
44
|
+
* ref={contentRef}
|
|
45
|
+
* style={{
|
|
46
|
+
* position: 'fixed',
|
|
47
|
+
* top: position ? `${position.top}px` : '0',
|
|
48
|
+
* left: position?.left !== undefined ? `${position.left}px` : undefined,
|
|
49
|
+
* right: position?.right !== undefined ? `${position.right}px` : undefined,
|
|
50
|
+
* }}
|
|
51
|
+
* >
|
|
52
|
+
* Menu content
|
|
53
|
+
* </div>
|
|
54
|
+
* );
|
|
55
|
+
* }
|
|
56
|
+
* ```
|
|
57
|
+
*/
|
|
58
|
+
export declare function useFloatingPosition({ enabled, triggerRef, contentRef, align, }: UseFloatingPositionConfig): FloatingPosition | null;
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
export type UseRovingTabIndexConfig = {
|
|
2
|
+
/** The ID of this item */
|
|
3
|
+
id: string;
|
|
4
|
+
/** Currently active item ID (undefined if no item is active) */
|
|
5
|
+
active: string | undefined;
|
|
6
|
+
/** Whether this item is disabled */
|
|
7
|
+
disabled: boolean;
|
|
8
|
+
/** Function to get all registered item IDs */
|
|
9
|
+
getItems: () => string[];
|
|
10
|
+
/** Function to check if a specific item is disabled */
|
|
11
|
+
isItemDisabled: (id: string) => boolean;
|
|
12
|
+
/**
|
|
13
|
+
* Focus mode for the component
|
|
14
|
+
* - 'roving-tabindex': Items are individually focusable (default)
|
|
15
|
+
* - 'activedescendant': Container manages focus via aria-activedescendant
|
|
16
|
+
*/
|
|
17
|
+
focusMode?: 'roving-tabindex' | 'activedescendant';
|
|
18
|
+
};
|
|
19
|
+
export type UseRovingTabIndexReturn = {
|
|
20
|
+
/** Whether this item should be focusable (tabIndex=0) */
|
|
21
|
+
isFocusable: boolean;
|
|
22
|
+
/** The tabIndex value to apply to this item */
|
|
23
|
+
tabIndex: number;
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* Implements roving tabindex pattern for keyboard navigation.
|
|
27
|
+
*
|
|
28
|
+
* In roving tabindex, only one item in a list is focusable at a time (tabIndex=0),
|
|
29
|
+
* while all other items have tabIndex=-1. This allows users to:
|
|
30
|
+
* - Tab into the list (focuses the active or first available item)
|
|
31
|
+
* - Use arrow keys to navigate within the list
|
|
32
|
+
* - Tab out of the list
|
|
33
|
+
*
|
|
34
|
+
* The hook automatically determines which item should be focusable based on:
|
|
35
|
+
* 1. The currently active item (if set and not disabled)
|
|
36
|
+
* 2. The first non-disabled item (fallback)
|
|
37
|
+
* 3. The first item in the list (if all items are disabled)
|
|
38
|
+
* 4. This item itself (final fallback if no other items exist)
|
|
39
|
+
*
|
|
40
|
+
* @param config - Configuration object for roving tabindex behavior
|
|
41
|
+
* @returns Object containing isFocusable flag and tabIndex value
|
|
42
|
+
*
|
|
43
|
+
* @example
|
|
44
|
+
* ```tsx
|
|
45
|
+
* function MenuItem({ id, disabled }: MenuItemProps) {
|
|
46
|
+
* const { active, getItems, isItemDisabled } = useMenu();
|
|
47
|
+
* const { isFocusable, tabIndex } = useRovingTabIndex({
|
|
48
|
+
* id,
|
|
49
|
+
* active,
|
|
50
|
+
* disabled,
|
|
51
|
+
* getItems,
|
|
52
|
+
* isItemDisabled,
|
|
53
|
+
* });
|
|
54
|
+
*
|
|
55
|
+
* return (
|
|
56
|
+
* <div
|
|
57
|
+
* role="menuitem"
|
|
58
|
+
* tabIndex={tabIndex}
|
|
59
|
+
* data-focusable={isFocusable || undefined}
|
|
60
|
+
* >
|
|
61
|
+
* {children}
|
|
62
|
+
* </div>
|
|
63
|
+
* );
|
|
64
|
+
* }
|
|
65
|
+
* ```
|
|
66
|
+
*
|
|
67
|
+
* @see {@link https://www.w3.org/WAI/ARIA/apg/practices/keyboard-interface/#kbd_roving_tabindex}
|
|
68
|
+
*/
|
|
69
|
+
export declare function useRovingTabIndex({ id, active, disabled, getItems, isItemDisabled, focusMode, }: UseRovingTabIndexConfig): UseRovingTabIndexReturn;
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { RefObject } from 'react';
|
|
2
|
+
export type UseScrollActiveIntoViewConfig = {
|
|
3
|
+
/** Reference to the container element */
|
|
4
|
+
containerRef: RefObject<HTMLElement> | null;
|
|
5
|
+
/** ID of the currently active item (undefined if no active item) */
|
|
6
|
+
activeId: string | undefined;
|
|
7
|
+
/**
|
|
8
|
+
* Scroll orientation:
|
|
9
|
+
* - 'vertical': Only scroll vertically (block: 'nearest')
|
|
10
|
+
* - 'horizontal': Scroll both horizontally and vertically (block + inline: 'nearest')
|
|
11
|
+
*/
|
|
12
|
+
orientation?: 'vertical' | 'horizontal';
|
|
13
|
+
/**
|
|
14
|
+
* Optional function to construct the element ID from the active ID.
|
|
15
|
+
* If not provided, uses activeId directly.
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* // For Listbox, which prefixes IDs:
|
|
19
|
+
* buildElementId: (id) => `${baseId}-listbox-option-${id}`
|
|
20
|
+
*/
|
|
21
|
+
buildElementId?: (activeId: string) => string;
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* Automatically scrolls the active item into view within a scrollable container.
|
|
25
|
+
*
|
|
26
|
+
* This hook is commonly used in keyboard-navigable lists, menus, and navigation
|
|
27
|
+
* components to ensure the currently active item is visible when it changes.
|
|
28
|
+
*
|
|
29
|
+
* Features:
|
|
30
|
+
* - Smooth scrolling behavior with 'nearest' algorithm (minimal scroll distance)
|
|
31
|
+
* - Supports both vertical and horizontal scrolling
|
|
32
|
+
* - Supports custom ID construction for prefixed/namespaced IDs
|
|
33
|
+
* - Only scrolls when activeId changes
|
|
34
|
+
*
|
|
35
|
+
* @param config - Configuration object for scroll behavior
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* ```tsx
|
|
39
|
+
* // Vertical list (Menu)
|
|
40
|
+
* function MenuContent() {
|
|
41
|
+
* const contentRef = useRef<HTMLDivElement>(null);
|
|
42
|
+
* const { active } = useMenu();
|
|
43
|
+
*
|
|
44
|
+
* useScrollActiveIntoView({
|
|
45
|
+
* containerRef: contentRef,
|
|
46
|
+
* activeId: active,
|
|
47
|
+
* orientation: 'vertical',
|
|
48
|
+
* });
|
|
49
|
+
*
|
|
50
|
+
* return <div ref={contentRef}>...</div>;
|
|
51
|
+
* }
|
|
52
|
+
*
|
|
53
|
+
* // Horizontal navigation (Menubar)
|
|
54
|
+
* function Menubar() {
|
|
55
|
+
* const menubarRef = useRef<HTMLDivElement>(null);
|
|
56
|
+
* const { active } = useMenubar();
|
|
57
|
+
*
|
|
58
|
+
* useScrollActiveIntoView({
|
|
59
|
+
* containerRef: menubarRef,
|
|
60
|
+
* activeId: active,
|
|
61
|
+
* orientation: 'horizontal',
|
|
62
|
+
* });
|
|
63
|
+
*
|
|
64
|
+
* return <div ref={menubarRef}>...</div>;
|
|
65
|
+
* }
|
|
66
|
+
*
|
|
67
|
+
* // With ID prefix (Listbox)
|
|
68
|
+
* function ListboxContent({ baseId }: { baseId: string }) {
|
|
69
|
+
* const contentRef = useRef<HTMLDivElement>(null);
|
|
70
|
+
* const { active } = useListbox();
|
|
71
|
+
*
|
|
72
|
+
* useScrollActiveIntoView({
|
|
73
|
+
* containerRef: contentRef,
|
|
74
|
+
* activeId: active,
|
|
75
|
+
* orientation: 'vertical',
|
|
76
|
+
* buildElementId: (id) => `${baseId}-listbox-option-${id}`,
|
|
77
|
+
* });
|
|
78
|
+
*
|
|
79
|
+
* return <div ref={contentRef}>...</div>;
|
|
80
|
+
* }
|
|
81
|
+
* ```
|
|
82
|
+
*/
|
|
83
|
+
export declare function useScrollActiveIntoView({ containerRef, activeId, orientation, buildElementId, }: UseScrollActiveIntoViewConfig): void;
|
|
@@ -9,7 +9,12 @@ export type ListboxContextValue = {
|
|
|
9
9
|
selection: ReadonlySet<string>;
|
|
10
10
|
selectionMode: 'single' | 'multiple';
|
|
11
11
|
disabled?: boolean;
|
|
12
|
-
|
|
12
|
+
/**
|
|
13
|
+
* Focus management mode:
|
|
14
|
+
* - 'roving-tabindex': Items are individually focusable (default)
|
|
15
|
+
* - 'activedescendant': Container manages focus via aria-activedescendant
|
|
16
|
+
*/
|
|
17
|
+
focusMode?: 'roving-tabindex' | 'activedescendant';
|
|
13
18
|
/**
|
|
14
19
|
* Set active item.
|
|
15
20
|
* Accepts `null` for compatibility with controlled prop API, but converts it to `undefined` internally.
|
|
@@ -23,9 +23,7 @@ export type MenubarContextValue = {
|
|
|
23
23
|
isItemDisabled: (id: string) => boolean;
|
|
24
24
|
/**
|
|
25
25
|
* ID of the currently open menu (if any).
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
* @phase2
|
|
26
|
+
* Tracks which menu is expanded in the menubar for conditional hover behavior.
|
|
29
27
|
*/
|
|
30
28
|
openMenuId: string | undefined;
|
|
31
29
|
setOpenMenuId: (id: string | undefined) => void;
|
|
@@ -67,9 +65,8 @@ export declare const useMenubar: () => MenubarContextValue;
|
|
|
67
65
|
* Hook to optionally access menubar context.
|
|
68
66
|
* Returns undefined if not within a MenubarProvider.
|
|
69
67
|
*
|
|
70
|
-
* Useful for components that can work both inside and outside a menubar
|
|
68
|
+
* Useful for components that can work both inside and outside a menubar.
|
|
71
69
|
*
|
|
72
|
-
* @phase2 Used by Menu components to detect if they're within a Menubar
|
|
73
70
|
* @returns {MenubarContextValue | undefined} The menubar context or undefined
|
|
74
71
|
*/
|
|
75
72
|
export declare const useMenubarOptional: () => MenubarContextValue | undefined;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@enonic/ui",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.18.0",
|
|
4
4
|
"description": "Enonic UI Component Library",
|
|
5
5
|
"author": "Enonic",
|
|
6
6
|
"license": "MIT",
|
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
"dependencies": {
|
|
47
47
|
"class-variance-authority": "~0.7.1",
|
|
48
48
|
"clsx": "~2.1.1",
|
|
49
|
-
"tailwind-merge": "~3.
|
|
49
|
+
"tailwind-merge": "~3.4.0"
|
|
50
50
|
},
|
|
51
51
|
"peerDependencies": {
|
|
52
52
|
"@radix-ui/react-slot": "^1.2.0",
|
|
@@ -68,44 +68,44 @@
|
|
|
68
68
|
}
|
|
69
69
|
},
|
|
70
70
|
"devDependencies": {
|
|
71
|
-
"@chromatic-com/storybook": "~4.1.
|
|
72
|
-
"@eslint/js": "~9.
|
|
71
|
+
"@chromatic-com/storybook": "~4.1.2",
|
|
72
|
+
"@eslint/js": "~9.39.1",
|
|
73
73
|
"@preact/preset-vite": "~2.10.2",
|
|
74
74
|
"@size-limit/file": "~11.2.0",
|
|
75
75
|
"@size-limit/preset-small-lib": "~11.2.0",
|
|
76
|
-
"@storybook/addon-a11y": "~
|
|
77
|
-
"@storybook/addon-docs": "~
|
|
78
|
-
"@storybook/addon-links": "~
|
|
79
|
-
"@storybook/addon-themes": "~
|
|
80
|
-
"@storybook/preact-vite": "~
|
|
81
|
-
"@tailwindcss/vite": "~4.1.
|
|
82
|
-
"@trivago/prettier-plugin-sort-imports": "~
|
|
83
|
-
"@types/node": "~24.
|
|
84
|
-
"@types/react": "~19.2.
|
|
85
|
-
"@types/react-dom": "~19.2.
|
|
86
|
-
"@typescript-eslint/eslint-plugin": "~8.46.
|
|
87
|
-
"@typescript-eslint/parser": "~8.46.
|
|
88
|
-
"eslint": "~9.
|
|
76
|
+
"@storybook/addon-a11y": "~10.0.7",
|
|
77
|
+
"@storybook/addon-docs": "~10.0.7",
|
|
78
|
+
"@storybook/addon-links": "~10.0.7",
|
|
79
|
+
"@storybook/addon-themes": "~10.0.7",
|
|
80
|
+
"@storybook/preact-vite": "~10.0.7",
|
|
81
|
+
"@tailwindcss/vite": "~4.1.17",
|
|
82
|
+
"@trivago/prettier-plugin-sort-imports": "~6.0.0",
|
|
83
|
+
"@types/node": "~24.10.0",
|
|
84
|
+
"@types/react": "~19.2.3",
|
|
85
|
+
"@types/react-dom": "~19.2.2",
|
|
86
|
+
"@typescript-eslint/eslint-plugin": "~8.46.4",
|
|
87
|
+
"@typescript-eslint/parser": "~8.46.4",
|
|
88
|
+
"eslint": "~9.39.1",
|
|
89
89
|
"eslint-import-resolver-typescript": "~4.4.4",
|
|
90
90
|
"eslint-plugin-import": "~2.32.0",
|
|
91
91
|
"eslint-plugin-jsx-a11y": "~6.10.2",
|
|
92
92
|
"eslint-plugin-react": "~7.37.5",
|
|
93
|
-
"eslint-plugin-react-hooks": "~7.0.
|
|
93
|
+
"eslint-plugin-react-hooks": "~7.0.1",
|
|
94
94
|
"husky": "~9.1.7",
|
|
95
|
-
"lint-staged": "~16.2.
|
|
96
|
-
"lucide-preact": "~0.
|
|
97
|
-
"lucide-react": "~0.
|
|
95
|
+
"lint-staged": "~16.2.6",
|
|
96
|
+
"lucide-preact": "~0.553.0",
|
|
97
|
+
"lucide-react": "~0.553.0",
|
|
98
98
|
"postcss": "~8.5.6",
|
|
99
99
|
"prettier": "~3.6.2",
|
|
100
|
-
"rollup-plugin-visualizer": "~6.0.
|
|
100
|
+
"rollup-plugin-visualizer": "~6.0.5",
|
|
101
101
|
"size-limit": "~11.2.0",
|
|
102
|
-
"storybook": "~
|
|
103
|
-
"tailwindcss": "~4.1.
|
|
104
|
-
"terser": "~5.44.
|
|
102
|
+
"storybook": "~10.0.7",
|
|
103
|
+
"tailwindcss": "~4.1.17",
|
|
104
|
+
"terser": "~5.44.1",
|
|
105
105
|
"tw-animate-css": "~1.4.0",
|
|
106
106
|
"typescript": "~5.9.3",
|
|
107
|
-
"typescript-eslint": "~8.46.
|
|
108
|
-
"vite": "~7.
|
|
107
|
+
"typescript-eslint": "~8.46.4",
|
|
108
|
+
"vite": "~7.2.2",
|
|
109
109
|
"vite-plugin-dts": "~4.5.4",
|
|
110
110
|
"vite-plugin-environment": "~1.1.3"
|
|
111
111
|
},
|