@xsolla/xui-context-menu 0.172.2 → 0.173.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 CHANGED
@@ -131,6 +131,7 @@ A horizontal rule with `role="separator"`. No content props.
131
131
  | `maxHeight` | `number` | Caps panel height (px); body scrolls and search stays sticky. |
132
132
  | `onSelect` | `(item: ContextMenuOptionItemProps) => void` | Fires for the preset path on option activation. |
133
133
  | `aria-label` | `string` | Accessible name for the menu container. |
134
+ | `testID` | `string` | Testing handle; forwarded as `data-testid` when `data-testid` is not provided. |
134
135
  | `data-testid` | `string` | Testing handle. |
135
136
 
136
137
  ## Behaviour & accessibility
@@ -1,21 +1,51 @@
1
1
  import * as React$1 from 'react';
2
- import React__default, { ReactNode, RefObject } from 'react';
2
+ import React__default, { RefObject, ReactNode, ChangeEvent, CSSProperties } from 'react';
3
+ import * as _xsolla_xui_core from '@xsolla/xui-core';
3
4
  import { ThemeOverrideProps } from '@xsolla/xui-core';
4
5
 
6
+ type CellType = "option" | "search" | "heading" | "divider";
7
+ interface CellMeta {
8
+ type: CellType;
9
+ onSelect?: () => void;
10
+ disabled?: boolean;
11
+ }
12
+ interface UseKeyboardNavigationOptions {
13
+ isOpen: boolean;
14
+ cells: Array<{
15
+ id: string;
16
+ meta: CellMeta;
17
+ }>;
18
+ activeIndex: number;
19
+ setActiveIndex: (index: number) => void;
20
+ onClose: () => void;
21
+ triggerRef?: RefObject<HTMLElement | null>;
22
+ }
23
+ declare const useKeyboardNavigation: ({ isOpen, cells, activeIndex, setActiveIndex, onClose, triggerRef, }: UseKeyboardNavigationOptions) => {
24
+ handleKeyDown: (event: React.KeyboardEvent) => void;
25
+ };
26
+
5
27
  type ContextMenuSize = "sm" | "md" | "lg" | "xl";
6
- type ContextMenuItemType = "option" | "search" | "heading" | "divider";
7
- type ContextMenuItemLeadingControl = "checkbox" | "radio";
8
- interface ContextMenuOptionItemProps {
9
- type: "option";
28
+ type ContextMenuPlacement = "bottom-start" | "top-start" | "bottom-end" | "top-end";
29
+ type ContextMenuPresetType = "list" | "loading" | "phone" | "checkbox" | "status" | "brandLogo" | "radio" | "avatar";
30
+ interface ContextMenuPosition {
31
+ x: number;
32
+ y: number;
33
+ }
34
+ interface ContextMenuItemBaseProps extends ThemeOverrideProps {
10
35
  size?: ContextMenuSize;
11
- leadingControl?: ContextMenuItemLeadingControl;
36
+ testID?: string;
37
+ "data-testid"?: string;
38
+ }
39
+ interface ContextMenuOptionItemProps extends ContextMenuItemBaseProps {
40
+ type: "option";
41
+ label: ReactNode;
42
+ description?: ReactNode;
43
+ leadingControl?: "checkbox" | "radio";
12
44
  leadingIcon?: ReactNode;
13
45
  status?: ReactNode;
14
46
  iconWrapper?: ReactNode;
15
47
  slot?: ReactNode;
16
48
  slotContent?: ReactNode;
17
- label: ReactNode;
18
- description?: ReactNode;
19
49
  value?: ReactNode;
20
50
  hint?: ReactNode;
21
51
  trailingIcon?: ReactNode;
@@ -27,88 +57,74 @@ interface ContextMenuOptionItemProps {
27
57
  destructive?: boolean;
28
58
  onSelect?: () => void;
29
59
  onCheckedChange?: (checked: boolean) => void;
30
- "data-testid"?: string;
31
- /** Test ID for testing frameworks */
32
- testID?: string;
33
60
  }
34
- interface ContextMenuSearchItemProps {
61
+ interface ContextMenuSearchItemProps extends ContextMenuItemBaseProps {
35
62
  type: "search";
36
- size?: ContextMenuSize;
37
- value: string;
38
- onValueChange: (value: string) => void;
63
+ value?: string;
64
+ onChange?: (event: ChangeEvent<HTMLInputElement>) => void;
65
+ onValueChange?: (value: string) => void;
39
66
  placeholder?: string;
40
67
  autoFocus?: boolean;
41
68
  "aria-label"?: string;
42
- "data-testid"?: string;
43
- /** Test ID for testing frameworks */
44
- testID?: string;
45
69
  }
46
- interface ContextMenuHeadingItemProps {
70
+ interface ContextMenuHeadingItemProps extends ContextMenuItemBaseProps {
47
71
  type: "heading";
48
- size?: ContextMenuSize;
49
72
  label: ReactNode;
50
73
  description?: ReactNode;
51
- "data-testid"?: string;
52
- /** Test ID for testing frameworks */
53
- testID?: string;
54
74
  }
55
- interface ContextMenuDividerItemProps {
75
+ interface ContextMenuDividerItemProps extends ContextMenuItemBaseProps {
56
76
  type: "divider";
57
- size?: ContextMenuSize;
58
- "data-testid"?: string;
59
- /** Test ID for testing frameworks */
60
- testID?: string;
61
77
  }
62
78
  type ContextMenuItemProps = ContextMenuOptionItemProps | ContextMenuSearchItemProps | ContextMenuHeadingItemProps | ContextMenuDividerItemProps;
63
- type ContextMenuPanelType = "list" | "phone" | "checkbox" | "status" | "brandLogo" | "radio" | "avatar";
64
- type ContextMenuPlacement = "bottom-start" | "top-start" | "bottom-end" | "top-end";
65
- interface ContextMenuPosition {
66
- x: number;
67
- y: number;
68
- }
69
- interface ContextMenuProps {
70
- type?: ContextMenuPanelType;
71
- items?: ReadonlyArray<ContextMenuOptionItemProps | ContextMenuHeadingItemProps | ContextMenuDividerItemProps>;
79
+ interface ContextMenuProps extends ThemeOverrideProps {
80
+ type?: ContextMenuPresetType;
81
+ items?: ReadonlyArray<ContextMenuItemProps>;
72
82
  children?: ReactNode;
73
83
  size?: ContextMenuSize;
74
84
  searchable?: boolean;
75
85
  loading?: boolean;
86
+ isLoading?: boolean;
76
87
  emptyMessage?: string;
77
88
  empty?: ReactNode;
78
89
  trigger?: ReactNode;
79
- position?: ContextMenuPosition;
80
90
  placement?: ContextMenuPlacement;
91
+ position?: ContextMenuPosition;
81
92
  isOpen?: boolean;
82
93
  onOpenChange?: (open: boolean) => void;
83
94
  closeOnSelect?: boolean;
84
- width?: number;
95
+ width?: number | string;
85
96
  maxHeight?: number;
86
97
  onSelect?: (item: ContextMenuOptionItemProps) => void;
87
98
  "aria-label"?: string;
88
- "data-testid"?: string;
89
- /** Test ID for testing frameworks */
90
99
  testID?: string;
100
+ "data-testid"?: string;
101
+ style?: CSSProperties;
91
102
  }
92
- interface ContextMenuCellMeta {
93
- type: ContextMenuItemType;
94
- onSelect?: () => void;
103
+ interface ContextMenuSubmenuProps {
104
+ /** Text label for the submenu trigger item */
105
+ label: ReactNode;
106
+ /** Leading icon for the trigger item */
107
+ icon?: ReactNode;
108
+ /** Whether the trigger item is disabled */
95
109
  disabled?: boolean;
110
+ /** Submenu panel contents */
111
+ children: ReactNode;
112
+ /** Size inherited from parent */
113
+ size?: ContextMenuSize;
114
+ "data-testid"?: string;
96
115
  }
97
116
  interface ContextMenuContextValue {
98
117
  size: ContextMenuSize;
99
- /** Stable id of the owning menu; tags portaled submenus for outside-click. */
100
118
  menuId: string;
101
119
  closeMenu: () => void;
102
- registerCell: (id: string, meta: ContextMenuCellMeta) => number;
120
+ activeIndex: number;
121
+ setActiveIndex: (index: number) => void;
122
+ registerCell: (id: string, meta: CellMeta) => number;
103
123
  unregisterCell: (id: string) => void;
104
- /** Live position of a cell in the registry (-1 if not registered). */
105
124
  getCellIndex: (id: string) => number;
106
- /** Bumps whenever the cell registry changes; drives index re-derivation. */
107
125
  cellsVersion: number;
108
- activeIndex: number;
109
- setActiveIndex: (i: number) => void;
110
126
  query: string;
111
- setQuery: (q: string) => void;
127
+ setQuery: (query: string) => void;
112
128
  }
113
129
  interface ContextMenuSizing {
114
130
  paddingVertical: number;
@@ -119,14 +135,23 @@ interface ContextMenuSizing {
119
135
  iconSize: number;
120
136
  gap: number;
121
137
  minWidth: number;
138
+ searchPaddingHorizontal: number;
139
+ searchPaddingVertical: number;
140
+ searchIconSize: number;
141
+ searchFontSize: number;
142
+ searchLineHeight: number;
122
143
  }
123
144
 
124
- type Props$1 = ContextMenuProps & ThemeOverrideProps;
125
- declare const ContextMenu: React__default.FC<Props$1>;
145
+ declare const ContextMenu: React__default.ForwardRefExoticComponent<ContextMenuProps & React__default.RefAttributes<HTMLElement>> & {
146
+ Item: React__default.FC<ContextMenuItemProps & _xsolla_xui_core.ThemeOverrideProps>;
147
+ Submenu: React__default.FC<ContextMenuSubmenuProps>;
148
+ };
126
149
 
127
150
  type Props = ContextMenuItemProps & ThemeOverrideProps;
128
151
  declare const ContextMenuItem: React__default.FC<Props>;
129
152
 
153
+ declare const ContextMenuSubmenu: React__default.FC<ContextMenuSubmenuProps>;
154
+
130
155
  declare const ContextMenuContext: React$1.Context<ContextMenuContextValue | undefined>;
131
156
  declare const useContextMenu: () => ContextMenuContextValue | undefined;
132
157
  declare const useContextMenuRequired: () => ContextMenuContextValue;
@@ -145,25 +170,4 @@ interface ResolvedPosition {
145
170
  }
146
171
  declare const useContextMenuPosition: ({ triggerRef, panelRef, isOpen, placement, offset, }: UseContextMenuPositionOptions) => ResolvedPosition | undefined;
147
172
 
148
- type CellType = "option" | "search" | "heading" | "divider";
149
- interface CellMeta {
150
- type: CellType;
151
- onSelect?: () => void;
152
- disabled?: boolean;
153
- }
154
- interface UseKeyboardNavigationOptions {
155
- isOpen: boolean;
156
- cells: Array<{
157
- id: string;
158
- meta: CellMeta;
159
- }>;
160
- activeIndex: number;
161
- setActiveIndex: (index: number) => void;
162
- onClose: () => void;
163
- triggerRef?: RefObject<HTMLElement | null>;
164
- }
165
- declare const useKeyboardNavigation: ({ isOpen, cells, activeIndex, setActiveIndex, onClose, triggerRef, }: UseKeyboardNavigationOptions) => {
166
- handleKeyDown: (event: React.KeyboardEvent) => void;
167
- };
168
-
169
- export { ContextMenu, ContextMenuContext, type ContextMenuContextValue, type ContextMenuDividerItemProps, type ContextMenuHeadingItemProps, ContextMenuItem, type ContextMenuItemLeadingControl, type ContextMenuItemProps, type ContextMenuItemType, type ContextMenuOptionItemProps, type ContextMenuPanelType, type ContextMenuPlacement, type ContextMenuPosition, type ContextMenuProps, type ContextMenuSearchItemProps, type ContextMenuSize, type ContextMenuSizing, useContextMenu, useContextMenuPosition, useContextMenuRequired, useKeyboardNavigation };
173
+ export { ContextMenu, ContextMenuContext, type ContextMenuContextValue, type ContextMenuDividerItemProps, type ContextMenuHeadingItemProps, ContextMenuItem, type ContextMenuItemProps, type ContextMenuOptionItemProps, type ContextMenuPlacement, type ContextMenuPosition, type ContextMenuPresetType, type ContextMenuProps, type ContextMenuSearchItemProps, type ContextMenuSize, type ContextMenuSizing, ContextMenuSubmenu, type ContextMenuSubmenuProps, useContextMenu, useContextMenuPosition, useContextMenuRequired, useKeyboardNavigation };
package/native/index.d.ts CHANGED
@@ -1,21 +1,51 @@
1
1
  import * as React$1 from 'react';
2
- import React__default, { ReactNode, RefObject } from 'react';
2
+ import React__default, { RefObject, ReactNode, ChangeEvent, CSSProperties } from 'react';
3
+ import * as _xsolla_xui_core from '@xsolla/xui-core';
3
4
  import { ThemeOverrideProps } from '@xsolla/xui-core';
4
5
 
6
+ type CellType = "option" | "search" | "heading" | "divider";
7
+ interface CellMeta {
8
+ type: CellType;
9
+ onSelect?: () => void;
10
+ disabled?: boolean;
11
+ }
12
+ interface UseKeyboardNavigationOptions {
13
+ isOpen: boolean;
14
+ cells: Array<{
15
+ id: string;
16
+ meta: CellMeta;
17
+ }>;
18
+ activeIndex: number;
19
+ setActiveIndex: (index: number) => void;
20
+ onClose: () => void;
21
+ triggerRef?: RefObject<HTMLElement | null>;
22
+ }
23
+ declare const useKeyboardNavigation: ({ isOpen, cells, activeIndex, setActiveIndex, onClose, triggerRef, }: UseKeyboardNavigationOptions) => {
24
+ handleKeyDown: (event: React.KeyboardEvent) => void;
25
+ };
26
+
5
27
  type ContextMenuSize = "sm" | "md" | "lg" | "xl";
6
- type ContextMenuItemType = "option" | "search" | "heading" | "divider";
7
- type ContextMenuItemLeadingControl = "checkbox" | "radio";
8
- interface ContextMenuOptionItemProps {
9
- type: "option";
28
+ type ContextMenuPlacement = "bottom-start" | "top-start" | "bottom-end" | "top-end";
29
+ type ContextMenuPresetType = "list" | "loading" | "phone" | "checkbox" | "status" | "brandLogo" | "radio" | "avatar";
30
+ interface ContextMenuPosition {
31
+ x: number;
32
+ y: number;
33
+ }
34
+ interface ContextMenuItemBaseProps extends ThemeOverrideProps {
10
35
  size?: ContextMenuSize;
11
- leadingControl?: ContextMenuItemLeadingControl;
36
+ testID?: string;
37
+ "data-testid"?: string;
38
+ }
39
+ interface ContextMenuOptionItemProps extends ContextMenuItemBaseProps {
40
+ type: "option";
41
+ label: ReactNode;
42
+ description?: ReactNode;
43
+ leadingControl?: "checkbox" | "radio";
12
44
  leadingIcon?: ReactNode;
13
45
  status?: ReactNode;
14
46
  iconWrapper?: ReactNode;
15
47
  slot?: ReactNode;
16
48
  slotContent?: ReactNode;
17
- label: ReactNode;
18
- description?: ReactNode;
19
49
  value?: ReactNode;
20
50
  hint?: ReactNode;
21
51
  trailingIcon?: ReactNode;
@@ -27,88 +57,74 @@ interface ContextMenuOptionItemProps {
27
57
  destructive?: boolean;
28
58
  onSelect?: () => void;
29
59
  onCheckedChange?: (checked: boolean) => void;
30
- "data-testid"?: string;
31
- /** Test ID for testing frameworks */
32
- testID?: string;
33
60
  }
34
- interface ContextMenuSearchItemProps {
61
+ interface ContextMenuSearchItemProps extends ContextMenuItemBaseProps {
35
62
  type: "search";
36
- size?: ContextMenuSize;
37
- value: string;
38
- onValueChange: (value: string) => void;
63
+ value?: string;
64
+ onChange?: (event: ChangeEvent<HTMLInputElement>) => void;
65
+ onValueChange?: (value: string) => void;
39
66
  placeholder?: string;
40
67
  autoFocus?: boolean;
41
68
  "aria-label"?: string;
42
- "data-testid"?: string;
43
- /** Test ID for testing frameworks */
44
- testID?: string;
45
69
  }
46
- interface ContextMenuHeadingItemProps {
70
+ interface ContextMenuHeadingItemProps extends ContextMenuItemBaseProps {
47
71
  type: "heading";
48
- size?: ContextMenuSize;
49
72
  label: ReactNode;
50
73
  description?: ReactNode;
51
- "data-testid"?: string;
52
- /** Test ID for testing frameworks */
53
- testID?: string;
54
74
  }
55
- interface ContextMenuDividerItemProps {
75
+ interface ContextMenuDividerItemProps extends ContextMenuItemBaseProps {
56
76
  type: "divider";
57
- size?: ContextMenuSize;
58
- "data-testid"?: string;
59
- /** Test ID for testing frameworks */
60
- testID?: string;
61
77
  }
62
78
  type ContextMenuItemProps = ContextMenuOptionItemProps | ContextMenuSearchItemProps | ContextMenuHeadingItemProps | ContextMenuDividerItemProps;
63
- type ContextMenuPanelType = "list" | "phone" | "checkbox" | "status" | "brandLogo" | "radio" | "avatar";
64
- type ContextMenuPlacement = "bottom-start" | "top-start" | "bottom-end" | "top-end";
65
- interface ContextMenuPosition {
66
- x: number;
67
- y: number;
68
- }
69
- interface ContextMenuProps {
70
- type?: ContextMenuPanelType;
71
- items?: ReadonlyArray<ContextMenuOptionItemProps | ContextMenuHeadingItemProps | ContextMenuDividerItemProps>;
79
+ interface ContextMenuProps extends ThemeOverrideProps {
80
+ type?: ContextMenuPresetType;
81
+ items?: ReadonlyArray<ContextMenuItemProps>;
72
82
  children?: ReactNode;
73
83
  size?: ContextMenuSize;
74
84
  searchable?: boolean;
75
85
  loading?: boolean;
86
+ isLoading?: boolean;
76
87
  emptyMessage?: string;
77
88
  empty?: ReactNode;
78
89
  trigger?: ReactNode;
79
- position?: ContextMenuPosition;
80
90
  placement?: ContextMenuPlacement;
91
+ position?: ContextMenuPosition;
81
92
  isOpen?: boolean;
82
93
  onOpenChange?: (open: boolean) => void;
83
94
  closeOnSelect?: boolean;
84
- width?: number;
95
+ width?: number | string;
85
96
  maxHeight?: number;
86
97
  onSelect?: (item: ContextMenuOptionItemProps) => void;
87
98
  "aria-label"?: string;
88
- "data-testid"?: string;
89
- /** Test ID for testing frameworks */
90
99
  testID?: string;
100
+ "data-testid"?: string;
101
+ style?: CSSProperties;
91
102
  }
92
- interface ContextMenuCellMeta {
93
- type: ContextMenuItemType;
94
- onSelect?: () => void;
103
+ interface ContextMenuSubmenuProps {
104
+ /** Text label for the submenu trigger item */
105
+ label: ReactNode;
106
+ /** Leading icon for the trigger item */
107
+ icon?: ReactNode;
108
+ /** Whether the trigger item is disabled */
95
109
  disabled?: boolean;
110
+ /** Submenu panel contents */
111
+ children: ReactNode;
112
+ /** Size inherited from parent */
113
+ size?: ContextMenuSize;
114
+ "data-testid"?: string;
96
115
  }
97
116
  interface ContextMenuContextValue {
98
117
  size: ContextMenuSize;
99
- /** Stable id of the owning menu; tags portaled submenus for outside-click. */
100
118
  menuId: string;
101
119
  closeMenu: () => void;
102
- registerCell: (id: string, meta: ContextMenuCellMeta) => number;
120
+ activeIndex: number;
121
+ setActiveIndex: (index: number) => void;
122
+ registerCell: (id: string, meta: CellMeta) => number;
103
123
  unregisterCell: (id: string) => void;
104
- /** Live position of a cell in the registry (-1 if not registered). */
105
124
  getCellIndex: (id: string) => number;
106
- /** Bumps whenever the cell registry changes; drives index re-derivation. */
107
125
  cellsVersion: number;
108
- activeIndex: number;
109
- setActiveIndex: (i: number) => void;
110
126
  query: string;
111
- setQuery: (q: string) => void;
127
+ setQuery: (query: string) => void;
112
128
  }
113
129
  interface ContextMenuSizing {
114
130
  paddingVertical: number;
@@ -119,14 +135,23 @@ interface ContextMenuSizing {
119
135
  iconSize: number;
120
136
  gap: number;
121
137
  minWidth: number;
138
+ searchPaddingHorizontal: number;
139
+ searchPaddingVertical: number;
140
+ searchIconSize: number;
141
+ searchFontSize: number;
142
+ searchLineHeight: number;
122
143
  }
123
144
 
124
- type Props$1 = ContextMenuProps & ThemeOverrideProps;
125
- declare const ContextMenu: React__default.FC<Props$1>;
145
+ declare const ContextMenu: React__default.ForwardRefExoticComponent<ContextMenuProps & React__default.RefAttributes<HTMLElement>> & {
146
+ Item: React__default.FC<ContextMenuItemProps & _xsolla_xui_core.ThemeOverrideProps>;
147
+ Submenu: React__default.FC<ContextMenuSubmenuProps>;
148
+ };
126
149
 
127
150
  type Props = ContextMenuItemProps & ThemeOverrideProps;
128
151
  declare const ContextMenuItem: React__default.FC<Props>;
129
152
 
153
+ declare const ContextMenuSubmenu: React__default.FC<ContextMenuSubmenuProps>;
154
+
130
155
  declare const ContextMenuContext: React$1.Context<ContextMenuContextValue | undefined>;
131
156
  declare const useContextMenu: () => ContextMenuContextValue | undefined;
132
157
  declare const useContextMenuRequired: () => ContextMenuContextValue;
@@ -145,25 +170,4 @@ interface ResolvedPosition {
145
170
  }
146
171
  declare const useContextMenuPosition: ({ triggerRef, panelRef, isOpen, placement, offset, }: UseContextMenuPositionOptions) => ResolvedPosition | undefined;
147
172
 
148
- type CellType = "option" | "search" | "heading" | "divider";
149
- interface CellMeta {
150
- type: CellType;
151
- onSelect?: () => void;
152
- disabled?: boolean;
153
- }
154
- interface UseKeyboardNavigationOptions {
155
- isOpen: boolean;
156
- cells: Array<{
157
- id: string;
158
- meta: CellMeta;
159
- }>;
160
- activeIndex: number;
161
- setActiveIndex: (index: number) => void;
162
- onClose: () => void;
163
- triggerRef?: RefObject<HTMLElement | null>;
164
- }
165
- declare const useKeyboardNavigation: ({ isOpen, cells, activeIndex, setActiveIndex, onClose, triggerRef, }: UseKeyboardNavigationOptions) => {
166
- handleKeyDown: (event: React.KeyboardEvent) => void;
167
- };
168
-
169
- export { ContextMenu, ContextMenuContext, type ContextMenuContextValue, type ContextMenuDividerItemProps, type ContextMenuHeadingItemProps, ContextMenuItem, type ContextMenuItemLeadingControl, type ContextMenuItemProps, type ContextMenuItemType, type ContextMenuOptionItemProps, type ContextMenuPanelType, type ContextMenuPlacement, type ContextMenuPosition, type ContextMenuProps, type ContextMenuSearchItemProps, type ContextMenuSize, type ContextMenuSizing, useContextMenu, useContextMenuPosition, useContextMenuRequired, useKeyboardNavigation };
173
+ export { ContextMenu, ContextMenuContext, type ContextMenuContextValue, type ContextMenuDividerItemProps, type ContextMenuHeadingItemProps, ContextMenuItem, type ContextMenuItemProps, type ContextMenuOptionItemProps, type ContextMenuPlacement, type ContextMenuPosition, type ContextMenuPresetType, type ContextMenuProps, type ContextMenuSearchItemProps, type ContextMenuSize, type ContextMenuSizing, ContextMenuSubmenu, type ContextMenuSubmenuProps, useContextMenu, useContextMenuPosition, useContextMenuRequired, useKeyboardNavigation };