@basic-ui/core 0.0.45 → 0.0.47
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/build/cjs/index.js +85 -10
- package/build/cjs/index.js.map +1 -1
- package/build/esm/Menu/ContextMenuTrigger.d.ts +11 -0
- package/build/esm/Menu/ContextMenuTrigger.js +51 -0
- package/build/esm/Menu/ContextMenuTrigger.js.map +1 -0
- package/build/esm/Menu/Menu.js +11 -2
- package/build/esm/Menu/Menu.js.map +1 -1
- package/build/esm/Menu/MenuItem.js +0 -1
- package/build/esm/Menu/MenuItem.js.map +1 -1
- package/build/esm/Menu/MenuList.js +23 -6
- package/build/esm/Menu/MenuList.js.map +1 -1
- package/build/esm/Menu/MenuPopover.js +6 -2
- package/build/esm/Menu/MenuPopover.js.map +1 -1
- package/build/esm/Menu/context.d.ts +5 -1
- package/build/esm/Menu/context.js.map +1 -1
- package/build/esm/Menu/fixtures/countryList.d.ts +1 -0
- package/build/esm/Menu/fixtures/countryList.js +2 -0
- package/build/esm/Menu/fixtures/countryList.js.map +1 -0
- package/build/esm/Menu/index.d.ts +1 -0
- package/build/esm/Menu/index.js +1 -0
- package/build/esm/Menu/index.js.map +1 -1
- package/build/esm/hooks/useControlledState.js +3 -1
- package/build/esm/hooks/useControlledState.js.map +1 -1
- package/build/tsconfig-build.tsbuildinfo +1 -1
- package/package.json +2 -2
- package/src/Menu/ContextMenu.story.tsx +73 -0
- package/src/Menu/ContextMenuTrigger.tsx +63 -0
- package/src/Menu/Menu.story.tsx +2 -2
- package/src/Menu/Menu.tsx +14 -1
- package/src/Menu/MenuComplex.story.tsx +58 -0
- package/src/Menu/MenuItem.tsx +0 -1
- package/src/Menu/MenuList.tsx +38 -9
- package/src/Menu/MenuPopover.tsx +9 -2
- package/src/Menu/context.ts +5 -1
- package/src/Menu/fixtures/countryList.ts +198 -0
- package/src/Menu/index.ts +1 -0
- package/src/hooks/useControlledState.ts +7 -1
package/build/cjs/index.js
CHANGED
|
@@ -216,11 +216,13 @@ function wrapEvent(theirHandler, ourHandler) {
|
|
|
216
216
|
function useControlledState(valueProp, onChangeProp, defaultValue, defaultOnChange) {
|
|
217
217
|
const isControlled = valueProp !== undefined;
|
|
218
218
|
const wasControlled = react.useRef(isControlled);
|
|
219
|
+
const hasWarned = react.useRef(false);
|
|
219
220
|
const [valueState, setValueState] = react.useState(defaultValue);
|
|
220
221
|
|
|
221
222
|
if (isControlled) {
|
|
222
|
-
if (wasControlled.current && process.env.NODE_ENV !== 'production') {
|
|
223
|
+
if (wasControlled.current && process.env.NODE_ENV !== 'production' && !hasWarned.current) {
|
|
223
224
|
console.warn('Trying to change from controlled to uncontrolled.');
|
|
225
|
+
hasWarned.current = true;
|
|
224
226
|
}
|
|
225
227
|
|
|
226
228
|
return [// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
@@ -1914,12 +1916,20 @@ const Menu = /*#__PURE__*/react.forwardRef(function Menu(props, forwardedRef) {
|
|
|
1914
1916
|
setState(isOpen);
|
|
1915
1917
|
});
|
|
1916
1918
|
menuListIdRef.current = react.useId();
|
|
1919
|
+
const offset = react.useRef([0, 0]);
|
|
1920
|
+
const offsetFn = react.useCallback(({
|
|
1921
|
+
reference
|
|
1922
|
+
}) => [offset.current[0], offset.current[1] - reference.height], []);
|
|
1923
|
+
const isContextMenu = react.useRef(false);
|
|
1917
1924
|
const value = {
|
|
1918
1925
|
menuListIdRef,
|
|
1919
1926
|
openWithArrowKeyRef,
|
|
1920
1927
|
open,
|
|
1921
1928
|
onChange,
|
|
1922
|
-
buttonRef
|
|
1929
|
+
buttonRef,
|
|
1930
|
+
offset,
|
|
1931
|
+
offsetFn,
|
|
1932
|
+
isContextMenu
|
|
1923
1933
|
};
|
|
1924
1934
|
return /*#__PURE__*/jsxRuntime.jsx(MenuProvider, {
|
|
1925
1935
|
value: value,
|
|
@@ -1998,6 +2008,51 @@ const MenuButton = /*#__PURE__*/react.forwardRef(function MenuButton(props, forw
|
|
|
1998
2008
|
});
|
|
1999
2009
|
});
|
|
2000
2010
|
|
|
2011
|
+
const ContextMenuTrigger = /*#__PURE__*/react.forwardRef(function MenuButton(props, forwardedRef) {
|
|
2012
|
+
const {
|
|
2013
|
+
as: Comp = 'div',
|
|
2014
|
+
id: preferredId,
|
|
2015
|
+
onContextMenu,
|
|
2016
|
+
disabled,
|
|
2017
|
+
...otherProps
|
|
2018
|
+
} = props;
|
|
2019
|
+
const {
|
|
2020
|
+
menuListIdRef,
|
|
2021
|
+
open,
|
|
2022
|
+
buttonRef,
|
|
2023
|
+
onChange,
|
|
2024
|
+
offset,
|
|
2025
|
+
isContextMenu
|
|
2026
|
+
} = useMenuContext();
|
|
2027
|
+
const idGenerated = react.useId();
|
|
2028
|
+
const id = preferredId || idGenerated;
|
|
2029
|
+
|
|
2030
|
+
const handleContextMenu = e => {
|
|
2031
|
+
if (disabled) {
|
|
2032
|
+
return;
|
|
2033
|
+
}
|
|
2034
|
+
|
|
2035
|
+
const rect = e.currentTarget.getBoundingClientRect();
|
|
2036
|
+
offset.current = [e.nativeEvent.x - rect.x, e.nativeEvent.y - rect.y];
|
|
2037
|
+
isContextMenu.current = true;
|
|
2038
|
+
buttonRef.current = e.currentTarget;
|
|
2039
|
+
onChange && onChange(e, !open);
|
|
2040
|
+
e.preventDefault();
|
|
2041
|
+
};
|
|
2042
|
+
|
|
2043
|
+
return /*#__PURE__*/jsxRuntime.jsx(Comp, {
|
|
2044
|
+
ref: forwardedRef,
|
|
2045
|
+
id: id,
|
|
2046
|
+
"aria-haspopup": true,
|
|
2047
|
+
"aria-controls": menuListIdRef.current,
|
|
2048
|
+
"aria-expanded": open ? true : undefined,
|
|
2049
|
+
"data-menu-trigger": "",
|
|
2050
|
+
onContextMenu: wrapEvent(onContextMenu, handleContextMenu),
|
|
2051
|
+
disabled: disabled,
|
|
2052
|
+
...otherProps
|
|
2053
|
+
});
|
|
2054
|
+
});
|
|
2055
|
+
|
|
2001
2056
|
const MenuItem = /*#__PURE__*/react.forwardRef(function MenuItem(props, forwardedRef) {
|
|
2002
2057
|
const {
|
|
2003
2058
|
as: Comp = 'li',
|
|
@@ -2035,7 +2090,6 @@ const MenuItem = /*#__PURE__*/react.forwardRef(function MenuItem(props, forwarde
|
|
|
2035
2090
|
const handleKeyDown = e => {
|
|
2036
2091
|
switch (e.key) {
|
|
2037
2092
|
case 'Enter':
|
|
2038
|
-
case ' ':
|
|
2039
2093
|
if (!disabled) {
|
|
2040
2094
|
handleSelect(e);
|
|
2041
2095
|
}
|
|
@@ -2073,12 +2127,15 @@ const MenuList = /*#__PURE__*/react.forwardRef(function MenuList(props, forwarde
|
|
|
2073
2127
|
defaultActiveItemValue,
|
|
2074
2128
|
...otherProps
|
|
2075
2129
|
} = props;
|
|
2130
|
+
const itemSearchStr = react.useRef('');
|
|
2131
|
+
const itemSearchClearTimeout = react.useRef();
|
|
2076
2132
|
const {
|
|
2077
2133
|
menuListIdRef,
|
|
2078
2134
|
buttonRef,
|
|
2079
2135
|
onChange,
|
|
2080
2136
|
openWithArrowKeyRef,
|
|
2081
|
-
open
|
|
2137
|
+
open,
|
|
2138
|
+
isContextMenu
|
|
2082
2139
|
} = useMenuContext();
|
|
2083
2140
|
const [navigationItem, setNavigationItem] = react.useState();
|
|
2084
2141
|
const [mounted, setMounted] = react.useState(false);
|
|
@@ -2114,7 +2171,9 @@ const MenuList = /*#__PURE__*/react.forwardRef(function MenuList(props, forwarde
|
|
|
2114
2171
|
setMounted(true);
|
|
2115
2172
|
}, [mounted, navigationItem, onNavigate, openWithArrowKeyRef, scope, defaultActiveItemValue]);
|
|
2116
2173
|
useOnClickOutside(menuListRef, e => {
|
|
2117
|
-
|
|
2174
|
+
console.log(isContextMenu.current);
|
|
2175
|
+
|
|
2176
|
+
if (isContextMenu.current || e.target instanceof HTMLElement && e.target !== buttonRef.current && !buttonRef.current?.contains(e.target)) {
|
|
2118
2177
|
onChange && onChange(e, false);
|
|
2119
2178
|
}
|
|
2120
2179
|
|
|
@@ -2129,6 +2188,7 @@ const MenuList = /*#__PURE__*/react.forwardRef(function MenuList(props, forwarde
|
|
|
2129
2188
|
onChange && onChange(e, false);
|
|
2130
2189
|
e.preventDefault(); // prevents focusing on next element, because we will be handling it
|
|
2131
2190
|
|
|
2191
|
+
itemSearchStr.current = '';
|
|
2132
2192
|
buttonRef.current?.focus();
|
|
2133
2193
|
break;
|
|
2134
2194
|
}
|
|
@@ -2138,6 +2198,7 @@ const MenuList = /*#__PURE__*/react.forwardRef(function MenuList(props, forwarde
|
|
|
2138
2198
|
case 'ArrowDown':
|
|
2139
2199
|
case 'ArrowUp':
|
|
2140
2200
|
e.preventDefault();
|
|
2201
|
+
itemSearchStr.current = '';
|
|
2141
2202
|
const allItems = scope ? scope.current.queryAllNodes(queryScope) : [];
|
|
2142
2203
|
const currentIndex = allItems.findIndex(e => e === navigationItem);
|
|
2143
2204
|
|
|
@@ -2173,21 +2234,30 @@ const MenuList = /*#__PURE__*/react.forwardRef(function MenuList(props, forwarde
|
|
|
2173
2234
|
|
|
2174
2235
|
default:
|
|
2175
2236
|
{
|
|
2176
|
-
if (e.key.length === 1) {
|
|
2237
|
+
if (e.key.length === 1 && !e.ctrlKey && !e.altKey) {
|
|
2177
2238
|
// A-Z
|
|
2178
2239
|
e.preventDefault();
|
|
2240
|
+
|
|
2241
|
+
if (itemSearchStr.current.length === 0 || itemSearchStr.current.slice(-1) !== e.key) {
|
|
2242
|
+
itemSearchStr.current = itemSearchStr.current + e.key;
|
|
2243
|
+
}
|
|
2244
|
+
|
|
2245
|
+
clearTimeout(itemSearchClearTimeout.current);
|
|
2246
|
+
itemSearchClearTimeout.current = setTimeout(() => {
|
|
2247
|
+
itemSearchStr.current = '';
|
|
2248
|
+
}, 500);
|
|
2179
2249
|
const allItems = scope ? scope.current.queryAllNodes(queryScope) : [];
|
|
2180
2250
|
const currentIndex = allItems.findIndex(e => e === navigationItem);
|
|
2181
|
-
const
|
|
2251
|
+
const searchStr = itemSearchStr.current;
|
|
2182
2252
|
let nextIndex = -1;
|
|
2183
2253
|
|
|
2184
|
-
for (let i = 1; i < allItems.length; i++) {
|
|
2254
|
+
for (let i = searchStr.length === 1 ? 1 : 0; i < allItems.length; i++) {
|
|
2185
2255
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
2186
2256
|
const idx = getCircularIndex(currentIndex + i, allItems.length);
|
|
2187
2257
|
const dom = allItems[idx];
|
|
2188
2258
|
const domText = dom.innerText.toLowerCase();
|
|
2189
2259
|
|
|
2190
|
-
if (domText.length > 0 && domText.
|
|
2260
|
+
if (domText.length > 0 && domText.startsWith(searchStr)) {
|
|
2191
2261
|
nextIndex = idx;
|
|
2192
2262
|
break;
|
|
2193
2263
|
}
|
|
@@ -2360,7 +2430,9 @@ const MenuPopover = /*#__PURE__*/react.forwardRef(function MenuPopover(props, fo
|
|
|
2360
2430
|
} = props;
|
|
2361
2431
|
const {
|
|
2362
2432
|
buttonRef,
|
|
2363
|
-
open
|
|
2433
|
+
open,
|
|
2434
|
+
offsetFn,
|
|
2435
|
+
isContextMenu
|
|
2364
2436
|
} = useMenuContext();
|
|
2365
2437
|
|
|
2366
2438
|
if (!open) {
|
|
@@ -2371,6 +2443,8 @@ const MenuPopover = /*#__PURE__*/react.forwardRef(function MenuPopover(props, fo
|
|
|
2371
2443
|
as: as,
|
|
2372
2444
|
ref: forwardedRef,
|
|
2373
2445
|
anchorEl: buttonRef,
|
|
2446
|
+
offsetFn: offsetFn,
|
|
2447
|
+
placement: isContextMenu.current ? 'bottom-start' : undefined,
|
|
2374
2448
|
...otherProps
|
|
2375
2449
|
});
|
|
2376
2450
|
});
|
|
@@ -3963,6 +4037,7 @@ exports.ComboboxLabel = ComboboxLabel;
|
|
|
3963
4037
|
exports.ComboboxList = ComboboxList;
|
|
3964
4038
|
exports.ComboboxOption = ComboboxOption;
|
|
3965
4039
|
exports.ComboboxPopover = ComboboxPopover;
|
|
4040
|
+
exports.ContextMenuTrigger = ContextMenuTrigger;
|
|
3966
4041
|
exports.FocusLock = FocusLock;
|
|
3967
4042
|
exports.Menu = Menu;
|
|
3968
4043
|
exports.MenuButton = MenuButton;
|