1
This commit is contained in:
+12
@@ -0,0 +1,12 @@
|
||||
import * as React from 'react';
|
||||
import type { MenuMode } from '../interface';
|
||||
/**
|
||||
* Get focusable elements from the element set under provided container
|
||||
*/
|
||||
export declare function getFocusableElements(container: HTMLElement, elements: Set<HTMLElement>): HTMLElement[];
|
||||
export declare const refreshElements: (keys: string[], id: string) => {
|
||||
elements: Set<HTMLElement>;
|
||||
key2element: Map<string, HTMLElement>;
|
||||
element2key: Map<HTMLElement, string>;
|
||||
};
|
||||
export declare function useAccessibility<T extends HTMLElement>(mode: MenuMode, activeKey: string, isRtl: boolean, id: string, containerRef: React.RefObject<HTMLUListElement>, getKeys: () => string[], getKeyPath: (key: string, includeOverflow?: boolean) => string[], triggerActiveKey: (key: string) => void, triggerAccessibilityOpen: (key: string, open?: boolean) => void, originOnKeyDown?: React.KeyboardEventHandler<T>): React.KeyboardEventHandler<T>;
|
||||
+293
@@ -0,0 +1,293 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.getFocusableElements = getFocusableElements;
|
||||
exports.refreshElements = void 0;
|
||||
exports.useAccessibility = useAccessibility;
|
||||
var _focus = require("@rc-component/util/lib/Dom/focus");
|
||||
var _KeyCode = _interopRequireDefault(require("@rc-component/util/lib/KeyCode"));
|
||||
var _raf = _interopRequireDefault(require("@rc-component/util/lib/raf"));
|
||||
var React = _interopRequireWildcard(require("react"));
|
||||
var _IdContext = require("../context/IdContext");
|
||||
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
|
||||
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
|
||||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
||||
// destruct to reduce minify size
|
||||
const {
|
||||
LEFT,
|
||||
RIGHT,
|
||||
UP,
|
||||
DOWN,
|
||||
ENTER,
|
||||
ESC,
|
||||
HOME,
|
||||
END
|
||||
} = _KeyCode.default;
|
||||
const ArrowKeys = [UP, DOWN, LEFT, RIGHT];
|
||||
function getOffset(mode, isRootLevel, isRtl, which) {
|
||||
const prev = 'prev';
|
||||
const next = 'next';
|
||||
const children = 'children';
|
||||
const parent = 'parent';
|
||||
|
||||
// Inline enter is special that we use unique operation
|
||||
if (mode === 'inline' && which === ENTER) {
|
||||
return {
|
||||
inlineTrigger: true
|
||||
};
|
||||
}
|
||||
const inline = {
|
||||
[UP]: prev,
|
||||
[DOWN]: next
|
||||
};
|
||||
const horizontal = {
|
||||
[LEFT]: isRtl ? next : prev,
|
||||
[RIGHT]: isRtl ? prev : next,
|
||||
[DOWN]: children,
|
||||
[ENTER]: children
|
||||
};
|
||||
const vertical = {
|
||||
[UP]: prev,
|
||||
[DOWN]: next,
|
||||
[ENTER]: children,
|
||||
[ESC]: parent,
|
||||
[LEFT]: isRtl ? children : parent,
|
||||
[RIGHT]: isRtl ? parent : children
|
||||
};
|
||||
const offsets = {
|
||||
inline,
|
||||
horizontal,
|
||||
vertical,
|
||||
inlineSub: inline,
|
||||
horizontalSub: vertical,
|
||||
verticalSub: vertical
|
||||
};
|
||||
const type = offsets[`${mode}${isRootLevel ? '' : 'Sub'}`]?.[which];
|
||||
switch (type) {
|
||||
case prev:
|
||||
return {
|
||||
offset: -1,
|
||||
sibling: true
|
||||
};
|
||||
case next:
|
||||
return {
|
||||
offset: 1,
|
||||
sibling: true
|
||||
};
|
||||
case parent:
|
||||
return {
|
||||
offset: -1,
|
||||
sibling: false
|
||||
};
|
||||
case children:
|
||||
return {
|
||||
offset: 1,
|
||||
sibling: false
|
||||
};
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
function findContainerUL(element) {
|
||||
let current = element;
|
||||
while (current) {
|
||||
if (current.getAttribute('data-menu-list')) {
|
||||
return current;
|
||||
}
|
||||
current = current.parentElement;
|
||||
}
|
||||
|
||||
// Normally should not reach this line
|
||||
/* istanbul ignore next */
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find focused element within element set provided
|
||||
*/
|
||||
function getFocusElement(activeElement, elements) {
|
||||
let current = activeElement || document.activeElement;
|
||||
while (current) {
|
||||
if (elements.has(current)) {
|
||||
return current;
|
||||
}
|
||||
current = current.parentElement;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get focusable elements from the element set under provided container
|
||||
*/
|
||||
function getFocusableElements(container, elements) {
|
||||
const list = (0, _focus.getFocusNodeList)(container, true);
|
||||
return list.filter(ele => elements.has(ele));
|
||||
}
|
||||
function getNextFocusElement(parentQueryContainer, elements, focusMenuElement, offset = 1) {
|
||||
// Key on the menu item will not get validate parent container
|
||||
if (!parentQueryContainer) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// List current level menu item elements
|
||||
const sameLevelFocusableMenuElementList = getFocusableElements(parentQueryContainer, elements);
|
||||
|
||||
// Find next focus index
|
||||
const count = sameLevelFocusableMenuElementList.length;
|
||||
let focusIndex = sameLevelFocusableMenuElementList.findIndex(ele => focusMenuElement === ele);
|
||||
if (offset < 0) {
|
||||
if (focusIndex === -1) {
|
||||
focusIndex = count - 1;
|
||||
} else {
|
||||
focusIndex -= 1;
|
||||
}
|
||||
} else if (offset > 0) {
|
||||
focusIndex += 1;
|
||||
}
|
||||
focusIndex = (focusIndex + count) % count;
|
||||
|
||||
// Focus menu item
|
||||
return sameLevelFocusableMenuElementList[focusIndex];
|
||||
}
|
||||
const refreshElements = (keys, id) => {
|
||||
const elements = new Set();
|
||||
const key2element = new Map();
|
||||
const element2key = new Map();
|
||||
keys.forEach(key => {
|
||||
const element = document.querySelector(`[data-menu-id='${(0, _IdContext.getMenuId)(id, key)}']`);
|
||||
if (element) {
|
||||
elements.add(element);
|
||||
element2key.set(element, key);
|
||||
key2element.set(key, element);
|
||||
}
|
||||
});
|
||||
return {
|
||||
elements,
|
||||
key2element,
|
||||
element2key
|
||||
};
|
||||
};
|
||||
exports.refreshElements = refreshElements;
|
||||
function useAccessibility(mode, activeKey, isRtl, id, containerRef, getKeys, getKeyPath, triggerActiveKey, triggerAccessibilityOpen, originOnKeyDown) {
|
||||
const rafRef = React.useRef();
|
||||
const activeRef = React.useRef();
|
||||
activeRef.current = activeKey;
|
||||
const cleanRaf = () => {
|
||||
_raf.default.cancel(rafRef.current);
|
||||
};
|
||||
React.useEffect(() => () => {
|
||||
cleanRaf();
|
||||
}, []);
|
||||
return e => {
|
||||
const {
|
||||
which
|
||||
} = e;
|
||||
if ([...ArrowKeys, ENTER, ESC, HOME, END].includes(which)) {
|
||||
const keys = getKeys();
|
||||
let refreshedElements = refreshElements(keys, id);
|
||||
const {
|
||||
elements,
|
||||
key2element,
|
||||
element2key
|
||||
} = refreshedElements;
|
||||
|
||||
// First we should find current focused MenuItem/SubMenu element
|
||||
const activeElement = key2element.get(activeKey);
|
||||
const focusMenuElement = getFocusElement(activeElement, elements);
|
||||
const focusMenuKey = element2key.get(focusMenuElement);
|
||||
const offsetObj = getOffset(mode, getKeyPath(focusMenuKey, true).length === 1, isRtl, which);
|
||||
|
||||
// Some mode do not have fully arrow operation like inline
|
||||
if (!offsetObj && which !== HOME && which !== END) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Arrow prevent default to avoid page scroll
|
||||
if (ArrowKeys.includes(which) || [HOME, END].includes(which)) {
|
||||
e.preventDefault();
|
||||
}
|
||||
const tryFocus = menuElement => {
|
||||
if (menuElement) {
|
||||
let focusTargetElement = menuElement;
|
||||
|
||||
// Focus to link instead of menu item if possible
|
||||
const link = menuElement.querySelector('a');
|
||||
if (link?.getAttribute('href')) {
|
||||
focusTargetElement = link;
|
||||
}
|
||||
const targetKey = element2key.get(menuElement);
|
||||
triggerActiveKey(targetKey);
|
||||
|
||||
/**
|
||||
* Do not `useEffect` here since `tryFocus` may trigger async
|
||||
* which makes React sync update the `activeKey`
|
||||
* that force render before `useRef` set the next activeKey
|
||||
*/
|
||||
cleanRaf();
|
||||
rafRef.current = (0, _raf.default)(() => {
|
||||
if (activeRef.current === targetKey) {
|
||||
focusTargetElement.focus();
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
if ([HOME, END].includes(which) || offsetObj.sibling || !focusMenuElement) {
|
||||
// ========================== Sibling ==========================
|
||||
// Find walkable focus menu element container
|
||||
let parentQueryContainer;
|
||||
if (!focusMenuElement || mode === 'inline') {
|
||||
parentQueryContainer = containerRef.current;
|
||||
} else {
|
||||
parentQueryContainer = findContainerUL(focusMenuElement);
|
||||
}
|
||||
|
||||
// Get next focus element
|
||||
let targetElement;
|
||||
const focusableElements = getFocusableElements(parentQueryContainer, elements);
|
||||
if (which === HOME) {
|
||||
targetElement = focusableElements[0];
|
||||
} else if (which === END) {
|
||||
targetElement = focusableElements[focusableElements.length - 1];
|
||||
} else {
|
||||
targetElement = getNextFocusElement(parentQueryContainer, elements, focusMenuElement, offsetObj.offset);
|
||||
}
|
||||
// Focus menu item
|
||||
tryFocus(targetElement);
|
||||
|
||||
// ======================= InlineTrigger =======================
|
||||
} else if (offsetObj.inlineTrigger) {
|
||||
// Inline trigger no need switch to sub menu item
|
||||
triggerAccessibilityOpen(focusMenuKey);
|
||||
// =========================== Level ===========================
|
||||
} else if (offsetObj.offset > 0) {
|
||||
triggerAccessibilityOpen(focusMenuKey, true);
|
||||
cleanRaf();
|
||||
rafRef.current = (0, _raf.default)(() => {
|
||||
// Async should resync elements
|
||||
refreshedElements = refreshElements(keys, id);
|
||||
const controlId = focusMenuElement.getAttribute('aria-controls');
|
||||
const subQueryContainer = document.getElementById(controlId);
|
||||
|
||||
// Get sub focusable menu item
|
||||
const targetElement = getNextFocusElement(subQueryContainer, refreshedElements.elements);
|
||||
|
||||
// Focus menu item
|
||||
tryFocus(targetElement);
|
||||
}, 5);
|
||||
} else if (offsetObj.offset < 0) {
|
||||
const keyPath = getKeyPath(focusMenuKey, true);
|
||||
const parentKey = keyPath[keyPath.length - 2];
|
||||
const parentMenuElement = key2element.get(parentKey);
|
||||
|
||||
// Focus menu item
|
||||
triggerAccessibilityOpen(parentKey, false);
|
||||
tryFocus(parentMenuElement);
|
||||
}
|
||||
}
|
||||
|
||||
// Pass origin key down event
|
||||
originOnKeyDown?.(e);
|
||||
};
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
import * as React from 'react';
|
||||
import type { MenuHoverEventHandler } from '../interface';
|
||||
interface ActiveObj {
|
||||
active: boolean;
|
||||
onMouseEnter?: React.MouseEventHandler<HTMLElement>;
|
||||
onMouseLeave?: React.MouseEventHandler<HTMLElement>;
|
||||
}
|
||||
export default function useActive(eventKey: string, disabled: boolean, onMouseEnter?: MenuHoverEventHandler, onMouseLeave?: MenuHoverEventHandler): ActiveObj;
|
||||
export {};
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.default = useActive;
|
||||
var React = _interopRequireWildcard(require("react"));
|
||||
var _MenuContext = require("../context/MenuContext");
|
||||
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
|
||||
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
|
||||
function useActive(eventKey, disabled, onMouseEnter, onMouseLeave) {
|
||||
const {
|
||||
// Active
|
||||
activeKey,
|
||||
onActive,
|
||||
onInactive
|
||||
} = React.useContext(_MenuContext.MenuContext);
|
||||
const ret = {
|
||||
active: activeKey === eventKey
|
||||
};
|
||||
|
||||
// Skip when disabled
|
||||
if (!disabled) {
|
||||
ret.onMouseEnter = domEvent => {
|
||||
onMouseEnter?.({
|
||||
key: eventKey,
|
||||
domEvent
|
||||
});
|
||||
onActive(eventKey);
|
||||
};
|
||||
ret.onMouseLeave = domEvent => {
|
||||
onMouseLeave?.({
|
||||
key: eventKey,
|
||||
domEvent
|
||||
});
|
||||
onInactive(eventKey);
|
||||
};
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
import * as React from 'react';
|
||||
export default function useDirectionStyle(level: number): React.CSSProperties;
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.default = useDirectionStyle;
|
||||
var React = _interopRequireWildcard(require("react"));
|
||||
var _MenuContext = require("../context/MenuContext");
|
||||
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
|
||||
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
|
||||
function useDirectionStyle(level) {
|
||||
const {
|
||||
mode,
|
||||
rtl,
|
||||
inlineIndent
|
||||
} = React.useContext(_MenuContext.MenuContext);
|
||||
if (mode !== 'inline') {
|
||||
return null;
|
||||
}
|
||||
const len = level;
|
||||
return rtl ? {
|
||||
paddingRight: len * inlineIndent
|
||||
} : {
|
||||
paddingLeft: len * inlineIndent
|
||||
};
|
||||
}
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
export declare const OVERFLOW_KEY = "rc-menu-more";
|
||||
export default function useKeyRecords(): {
|
||||
registerPath: (key: string, keyPath: string[]) => void;
|
||||
unregisterPath: (key: string, keyPath: string[]) => void;
|
||||
refreshOverflowKeys: (keys: string[]) => void;
|
||||
isSubPathKey: (pathKeys: string[], eventKey: string) => boolean;
|
||||
getKeyPath: (eventKey: string, includeOverflow?: boolean) => string[];
|
||||
getKeys: () => string[];
|
||||
getSubPathKeys: (key: string) => Set<string>;
|
||||
};
|
||||
+104
@@ -0,0 +1,104 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.OVERFLOW_KEY = void 0;
|
||||
exports.default = useKeyRecords;
|
||||
var _react = _interopRequireWildcard(require("react"));
|
||||
var React = _react;
|
||||
var _warning = _interopRequireDefault(require("@rc-component/util/lib/warning"));
|
||||
var _timeUtil = require("../utils/timeUtil");
|
||||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
||||
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
|
||||
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
|
||||
const PATH_SPLIT = '__RC_UTIL_PATH_SPLIT__';
|
||||
const getPathStr = keyPath => keyPath.join(PATH_SPLIT);
|
||||
const getPathKeys = keyPathStr => keyPathStr.split(PATH_SPLIT);
|
||||
const OVERFLOW_KEY = exports.OVERFLOW_KEY = 'rc-menu-more';
|
||||
function useKeyRecords() {
|
||||
const [, internalForceUpdate] = React.useState({});
|
||||
const key2pathRef = (0, _react.useRef)(new Map());
|
||||
const path2keyRef = (0, _react.useRef)(new Map());
|
||||
const [overflowKeys, setOverflowKeys] = React.useState([]);
|
||||
const updateRef = (0, _react.useRef)(0);
|
||||
const destroyRef = (0, _react.useRef)(false);
|
||||
const forceUpdate = () => {
|
||||
if (!destroyRef.current) {
|
||||
internalForceUpdate({});
|
||||
}
|
||||
};
|
||||
const registerPath = (0, _react.useCallback)((key, keyPath) => {
|
||||
// Warning for invalidate or duplicated `key`
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
(0, _warning.default)(!key2pathRef.current.has(key), `Duplicated key '${key}' used in Menu by path [${keyPath.join(' > ')}]`);
|
||||
}
|
||||
|
||||
// Fill map
|
||||
const connectedPath = getPathStr(keyPath);
|
||||
path2keyRef.current.set(connectedPath, key);
|
||||
key2pathRef.current.set(key, connectedPath);
|
||||
updateRef.current += 1;
|
||||
const id = updateRef.current;
|
||||
(0, _timeUtil.nextSlice)(() => {
|
||||
if (id === updateRef.current) {
|
||||
forceUpdate();
|
||||
}
|
||||
});
|
||||
}, []);
|
||||
const unregisterPath = (0, _react.useCallback)((key, keyPath) => {
|
||||
const connectedPath = getPathStr(keyPath);
|
||||
path2keyRef.current.delete(connectedPath);
|
||||
key2pathRef.current.delete(key);
|
||||
}, []);
|
||||
const refreshOverflowKeys = (0, _react.useCallback)(keys => {
|
||||
setOverflowKeys(keys);
|
||||
}, []);
|
||||
const getKeyPath = (0, _react.useCallback)((eventKey, includeOverflow) => {
|
||||
const fullPath = key2pathRef.current.get(eventKey) || '';
|
||||
const keys = getPathKeys(fullPath);
|
||||
if (includeOverflow && overflowKeys.includes(keys[0])) {
|
||||
keys.unshift(OVERFLOW_KEY);
|
||||
}
|
||||
return keys;
|
||||
}, [overflowKeys]);
|
||||
const isSubPathKey = (0, _react.useCallback)((pathKeys, eventKey) => pathKeys.filter(item => item !== undefined).some(pathKey => {
|
||||
const pathKeyList = getKeyPath(pathKey, true);
|
||||
return pathKeyList.includes(eventKey);
|
||||
}), [getKeyPath]);
|
||||
const getKeys = () => {
|
||||
const keys = [...key2pathRef.current.keys()];
|
||||
if (overflowKeys.length) {
|
||||
keys.push(OVERFLOW_KEY);
|
||||
}
|
||||
return keys;
|
||||
};
|
||||
|
||||
/**
|
||||
* Find current key related child path keys
|
||||
*/
|
||||
const getSubPathKeys = (0, _react.useCallback)(key => {
|
||||
const connectedPath = `${key2pathRef.current.get(key)}${PATH_SPLIT}`;
|
||||
const pathKeys = new Set();
|
||||
[...path2keyRef.current.keys()].forEach(pathKey => {
|
||||
if (pathKey.startsWith(connectedPath)) {
|
||||
pathKeys.add(path2keyRef.current.get(pathKey));
|
||||
}
|
||||
});
|
||||
return pathKeys;
|
||||
}, []);
|
||||
React.useEffect(() => () => {
|
||||
destroyRef.current = true;
|
||||
}, []);
|
||||
return {
|
||||
// Register
|
||||
registerPath,
|
||||
unregisterPath,
|
||||
refreshOverflowKeys,
|
||||
// Util
|
||||
isSubPathKey,
|
||||
getKeyPath,
|
||||
getKeys,
|
||||
getSubPathKeys
|
||||
};
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
/**
|
||||
* Cache callback function that always return same ref instead.
|
||||
* This is used for context optimization.
|
||||
*/
|
||||
export default function useMemoCallback<T extends (...args: any[]) => void>(func: T): T;
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.default = useMemoCallback;
|
||||
var React = _interopRequireWildcard(require("react"));
|
||||
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
|
||||
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
|
||||
/**
|
||||
* Cache callback function that always return same ref instead.
|
||||
* This is used for context optimization.
|
||||
*/
|
||||
function useMemoCallback(func) {
|
||||
const funRef = React.useRef(func);
|
||||
funRef.current = func;
|
||||
const callback = React.useCallback((...args) => funRef.current?.(...args), []);
|
||||
return func ? callback : undefined;
|
||||
}
|
||||
Reference in New Issue
Block a user