grep-components 2.24.0 → 2.25.0-GREPF-2862.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.
|
@@ -6,6 +6,6 @@ interface Context {
|
|
|
6
6
|
classes?: Record<'nav' | 'tree' | 'node' | 'link', string>;
|
|
7
7
|
offsetTop?: number;
|
|
8
8
|
}
|
|
9
|
-
declare const
|
|
10
|
-
export {
|
|
11
|
-
export default
|
|
9
|
+
declare const Context: React.Context<Context>;
|
|
10
|
+
export { Context as GrepTableOfContentContex };
|
|
11
|
+
export default Context;
|
|
@@ -4,5 +4,5 @@ export interface IdentifyElement {
|
|
|
4
4
|
export declare const generateElementId: IdentifyElement;
|
|
5
5
|
export declare const identifyElement: (identify?: IdentifyElement) => (element: HTMLElement) => string;
|
|
6
6
|
export declare const identifyElements: (elements: Array<HTMLElement>, identify?: IdentifyElement) => void;
|
|
7
|
-
export declare const
|
|
8
|
-
export default
|
|
7
|
+
export declare const identifiedElements: (elements: Array<HTMLElement>, identify?: IdentifyElement) => Record<string, HTMLElement>;
|
|
8
|
+
export default identifiedElements;
|
package/dist/index.js
CHANGED
|
@@ -3,7 +3,7 @@ import LocalizedFormatPlugin from 'dayjs/plugin/localizedFormat.js';
|
|
|
3
3
|
import isBetweenPlugin from 'dayjs/plugin/isBetween.js';
|
|
4
4
|
import { blueGrey, grey, brown, deepOrange, orange, amber, yellow, lime, lightGreen, green, teal, cyan, lightBlue, blue, indigo, deepPurple, purple, pink, red } from '@mui/material/colors';
|
|
5
5
|
import * as React from 'react';
|
|
6
|
-
import React__default, { useRef, useMemo, createContext, useContext, forwardRef, createElement, useState, useCallback, useEffect, useLayoutEffect, memo, useReducer, cloneElement } from 'react';
|
|
6
|
+
import React__default, { useRef, useMemo, createContext, useContext, forwardRef, createElement, useState, useCallback, useEffect, useLayoutEffect, memo, useReducer, cloneElement, use } from 'react';
|
|
7
7
|
import AccountCircle from '@mui/icons-material/AccountCircle';
|
|
8
8
|
import ArrowDropdown from '@mui/icons-material/ArrowDropDown';
|
|
9
9
|
import { Button, Box, Typography, Tabs, Tab, Collapse, MenuList, Tooltip, MenuItem as MenuItem$1, Menu as Menu$1, Container, List, ListItem, ListItemText, ListItemButton, CircularProgress, TextField, FormControl, InputLabel, Select, OutlinedInput, Input, Checkbox, FormHelperText, IconButton as IconButton$1, ToggleButtonGroup, ToggleButton, AppBar as AppBar$1, Toolbar as Toolbar$1, Divider as Divider$1, Dialog as Dialog$1, DialogTitle as DialogTitle$1, DialogContent as DialogContent$1, DialogContentText as DialogContentText$1, DialogActions as DialogActions$1 } from '@mui/material';
|
|
@@ -1705,7 +1705,7 @@ const CollapsableMenuItem = ({ items, onClick, children, onClose: _onclose, tool
|
|
|
1705
1705
|
const handleClick = items ? onToggleClick : onClick;
|
|
1706
1706
|
useEffect(() => {
|
|
1707
1707
|
document.addEventListener('click', onScrimClick, { capture: true });
|
|
1708
|
-
return () => document.removeEventListener('click', onScrimClick);
|
|
1708
|
+
return () => document.removeEventListener('click', onScrimClick, { capture: true });
|
|
1709
1709
|
}, [listItemRef, onScrimClick]);
|
|
1710
1710
|
const { classes } = useStyles$f({ open });
|
|
1711
1711
|
const renderInner = () => (React__default.createElement(Box, { sx: { display: 'flex', flexDirection: 'column', width: '100%' } },
|
|
@@ -2155,35 +2155,35 @@ const getElementIndex = (el) => Number(el.getAttribute('data-index') || -1);
|
|
|
2155
2155
|
const GrepTable = ({ placeholderText, dropdownItems, isRowDisabled, pagination, outlined, columns, header, data, onSelectedRowChange, sortBy, sortDirection, onSortBy, onRowClick, size, caption, stickyHeader, padding, disableSelectOnClick = false, menuButtonLabel, underlineOnFocus, rowTabIndex, rowStyle, rowsPerPageOptions = [5, 10, 25, 50], ...props }) => {
|
|
2156
2156
|
const [rowsPerPage, setRowsPerPage] = React__default.useState(props.rowsPerPage || 10);
|
|
2157
2157
|
const [menuAnchor, setMenuAnchor] = React__default.useState(null);
|
|
2158
|
-
const [currentPage,
|
|
2159
|
-
const [selectedRowIndex,
|
|
2160
|
-
const [expandedRowIndex,
|
|
2158
|
+
const [currentPage, setCurrentPage] = React__default.useState(0);
|
|
2159
|
+
const [selectedRowIndex, setSelectedRowIndex] = React__default.useState();
|
|
2160
|
+
const [expandedRowIndex, setExpandedRowIndex] = React__default.useState();
|
|
2161
2161
|
const [dropdownContext, setDropdownContext] = React__default.useState();
|
|
2162
2162
|
const selectedRow = data[selectedRowIndex] || null;
|
|
2163
|
-
const
|
|
2163
|
+
const _setCurrentPage = useCallback((index, rowIndex, shouldExpand) => {
|
|
2164
2164
|
index = pagination && index >= 0 ? index : 0;
|
|
2165
|
-
|
|
2166
|
-
|
|
2165
|
+
setCurrentPage(index);
|
|
2166
|
+
setSelectedRowIndex(rowIndex);
|
|
2167
2167
|
if (shouldExpand) {
|
|
2168
|
-
|
|
2168
|
+
setExpandedRowIndex(rowIndex);
|
|
2169
2169
|
}
|
|
2170
2170
|
}, [
|
|
2171
|
-
|
|
2172
|
-
|
|
2173
|
-
|
|
2171
|
+
setCurrentPage,
|
|
2172
|
+
setSelectedRowIndex,
|
|
2173
|
+
setExpandedRowIndex,
|
|
2174
2174
|
rowsPerPage,
|
|
2175
2175
|
pagination,
|
|
2176
2176
|
]);
|
|
2177
|
-
const
|
|
2177
|
+
const _setSelectedRowIndex = (index, shouldExpand = true) => {
|
|
2178
2178
|
const hasIndexChanged = index === selectedRowIndex;
|
|
2179
2179
|
const pageIndex = Math.floor(index / rowsPerPage);
|
|
2180
|
-
|
|
2180
|
+
_setCurrentPage(pageIndex, index, shouldExpand);
|
|
2181
2181
|
if (hasIndexChanged && onSelectedRowChange) {
|
|
2182
2182
|
onSelectedRowChange(data[index]);
|
|
2183
2183
|
}
|
|
2184
2184
|
};
|
|
2185
2185
|
const setSelectedElement = (el, shouldExpand = true) => {
|
|
2186
|
-
|
|
2186
|
+
_setSelectedRowIndex(getElementIndex(el), shouldExpand);
|
|
2187
2187
|
};
|
|
2188
2188
|
const tableRef = React__default.useRef(null);
|
|
2189
2189
|
// focus selected row first tabable item
|
|
@@ -2198,8 +2198,8 @@ const GrepTable = ({ placeholderText, dropdownItems, isRowDisabled, pagination,
|
|
|
2198
2198
|
}
|
|
2199
2199
|
}, [tableRef, selectedRowIndex]);
|
|
2200
2200
|
React__default.useEffect(() => {
|
|
2201
|
-
|
|
2202
|
-
}, [data.length,
|
|
2201
|
+
_setCurrentPage(0);
|
|
2202
|
+
}, [data.length, _setCurrentPage]);
|
|
2203
2203
|
const _openDropdown = (e, row) => {
|
|
2204
2204
|
const { onContextIdChanged } = props;
|
|
2205
2205
|
if (onContextIdChanged) {
|
|
@@ -2214,7 +2214,7 @@ const GrepTable = ({ placeholderText, dropdownItems, isRowDisabled, pagination,
|
|
|
2214
2214
|
}, [onRowClick]);
|
|
2215
2215
|
const _handlePageChange = (event, newPage) => {
|
|
2216
2216
|
event && event.preventDefault();
|
|
2217
|
-
|
|
2217
|
+
_setCurrentPage(newPage);
|
|
2218
2218
|
};
|
|
2219
2219
|
const _handleChangeRowsPerPage = (event) => {
|
|
2220
2220
|
setRowsPerPage(Number(event.target.value));
|
|
@@ -2294,7 +2294,7 @@ const GrepTable = ({ placeholderText, dropdownItems, isRowDisabled, pagination,
|
|
|
2294
2294
|
const moveSelectedRow = (steps) => {
|
|
2295
2295
|
const i = (selectedRowIndex || 0) + steps;
|
|
2296
2296
|
if (i >= 0 && i <= maxIndex) {
|
|
2297
|
-
|
|
2297
|
+
_setSelectedRowIndex(i);
|
|
2298
2298
|
}
|
|
2299
2299
|
};
|
|
2300
2300
|
switch (e.key) {
|
|
@@ -2313,15 +2313,15 @@ const GrepTable = ({ placeholderText, dropdownItems, isRowDisabled, pagination,
|
|
|
2313
2313
|
moveSelectedRow(rowsPerPage);
|
|
2314
2314
|
break;
|
|
2315
2315
|
case Key.Home:
|
|
2316
|
-
|
|
2316
|
+
_setSelectedRowIndex(0);
|
|
2317
2317
|
break;
|
|
2318
2318
|
case Key.End:
|
|
2319
|
-
|
|
2319
|
+
_setSelectedRowIndex(maxIndex);
|
|
2320
2320
|
break;
|
|
2321
2321
|
case Key.Tab:
|
|
2322
2322
|
requestAnimationFrame(() => {
|
|
2323
2323
|
// check is any children still has focus
|
|
2324
|
-
!containsFocus(tableRef.current) &&
|
|
2324
|
+
!containsFocus(tableRef.current) && _setSelectedRowIndex(-1);
|
|
2325
2325
|
});
|
|
2326
2326
|
break;
|
|
2327
2327
|
case Key.Enter:
|
|
@@ -2608,16 +2608,16 @@ const GrepInput = ({ variant = 'standard', ...props }) => {
|
|
|
2608
2608
|
};
|
|
2609
2609
|
|
|
2610
2610
|
const GrepSelect = (props) => {
|
|
2611
|
-
const
|
|
2611
|
+
const inputLabelRef = React.useRef(null);
|
|
2612
2612
|
const [labelWidth, setLabelWidth] = React.useState(0);
|
|
2613
2613
|
React.useEffect(() => {
|
|
2614
|
-
setLabelWidth(
|
|
2614
|
+
setLabelWidth(inputLabelRef.current.offsetWidth);
|
|
2615
2615
|
}, []);
|
|
2616
2616
|
const { unselectOption = true, errorMessage, selectItems, helperText, fullWidth, outlined, disabled, required, label, labelProps, inputProps, value, size, id, useCheckedSelect, ...rest } = props;
|
|
2617
2617
|
const error = errorMessage ? errorMessage.length > 0 : false;
|
|
2618
2618
|
const selected = value;
|
|
2619
2619
|
return (React.createElement(FormControl, { variant: outlined ? 'outlined' : 'standard', className: props.className, fullWidth: fullWidth, required: required, style: props.style, error: error, size: size, disabled: disabled },
|
|
2620
|
-
React.createElement(InputLabel, { htmlFor: id, ref:
|
|
2620
|
+
React.createElement(InputLabel, { htmlFor: id, ref: inputLabelRef, style: {
|
|
2621
2621
|
minWidth: 'max-content',
|
|
2622
2622
|
overflow: 'visible',
|
|
2623
2623
|
}, ...labelProps }, label),
|
|
@@ -2648,7 +2648,7 @@ const defaultOptions$2 = {
|
|
|
2648
2648
|
};
|
|
2649
2649
|
const useDate = (value = null, options) => {
|
|
2650
2650
|
const { utc, preserveTime } = { ...options, ...defaultOptions$2 };
|
|
2651
|
-
const [date,
|
|
2651
|
+
const [date, setDate] = useState(null);
|
|
2652
2652
|
const getDate = useCallback((value) => {
|
|
2653
2653
|
if (value) {
|
|
2654
2654
|
const date = dayjs(value);
|
|
@@ -2656,13 +2656,13 @@ const useDate = (value = null, options) => {
|
|
|
2656
2656
|
}
|
|
2657
2657
|
return null;
|
|
2658
2658
|
}, [preserveTime]);
|
|
2659
|
-
const
|
|
2659
|
+
const _setDate = (next) => {
|
|
2660
2660
|
const nextDate = getDate(next);
|
|
2661
|
-
hasDateChanged(date, nextDate) &&
|
|
2661
|
+
hasDateChanged(date, nextDate) && setDate(nextDate);
|
|
2662
2662
|
};
|
|
2663
2663
|
// eslint-disable-next-line @eslint-react/use-memo
|
|
2664
|
-
useMemo(() =>
|
|
2665
|
-
return [date,
|
|
2664
|
+
useMemo(() => _setDate(value ? parseDate(value, { utc }) : null), [value, utc]);
|
|
2665
|
+
return [date, _setDate];
|
|
2666
2666
|
};
|
|
2667
2667
|
|
|
2668
2668
|
var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
|
|
@@ -7806,7 +7806,7 @@ function getItemGap$1(clientRects, index, activeIndex) {
|
|
|
7806
7806
|
}
|
|
7807
7807
|
|
|
7808
7808
|
const ID_PREFIX = 'Sortable';
|
|
7809
|
-
const Context = /*#__PURE__*/React__default.createContext({
|
|
7809
|
+
const Context$1 = /*#__PURE__*/React__default.createContext({
|
|
7810
7810
|
activeIndex: -1,
|
|
7811
7811
|
containerId: ID_PREFIX,
|
|
7812
7812
|
disableTransforms: false,
|
|
@@ -7865,7 +7865,7 @@ function SortableContext(_ref) {
|
|
|
7865
7865
|
strategy
|
|
7866
7866
|
}), // eslint-disable-next-line react-hooks/exhaustive-deps
|
|
7867
7867
|
[activeIndex, containerId, disabled.draggable, disabled.droppable, disableTransforms, items, overIndex, droppableRects, useDragOverlay, strategy]);
|
|
7868
|
-
return React__default.createElement(Context.Provider, {
|
|
7868
|
+
return React__default.createElement(Context$1.Provider, {
|
|
7869
7869
|
value: contextValue
|
|
7870
7870
|
}, children);
|
|
7871
7871
|
}
|
|
@@ -7989,7 +7989,7 @@ function useSortable(_ref) {
|
|
|
7989
7989
|
overIndex,
|
|
7990
7990
|
useDragOverlay,
|
|
7991
7991
|
strategy: globalStrategy
|
|
7992
|
-
} = useContext(Context);
|
|
7992
|
+
} = useContext(Context$1);
|
|
7993
7993
|
const disabled = normalizeLocalDisabled(localDisabled, globalDisabled);
|
|
7994
7994
|
const index = items.indexOf(id);
|
|
7995
7995
|
const data = useMemo(() => ({
|
|
@@ -8621,16 +8621,16 @@ function r(e){var t,f,n="";if("string"==typeof e||"number"==typeof e)n+=e;else i
|
|
|
8621
8621
|
|
|
8622
8622
|
function StyleWrapperPlugin({ showCharcount, maxChars, helperText, readOnly, classes, label, children, autoFocus, toolbarAnchor, hasCustomToolbar, }) {
|
|
8623
8623
|
const [editor] = useLexicalComposerContext();
|
|
8624
|
-
const [hasFocus,
|
|
8624
|
+
const [hasFocus, setHasFocus] = useState(() => {
|
|
8625
8625
|
return editor.getRootElement() === document.activeElement;
|
|
8626
8626
|
});
|
|
8627
8627
|
const [charCount, setCharCount] = useState(0);
|
|
8628
8628
|
useEffect(() => {
|
|
8629
8629
|
return mergeRegister(editor.registerCommand(BLUR_COMMAND, () => {
|
|
8630
|
-
|
|
8630
|
+
setHasFocus(editor.getRootElement() === document.activeElement);
|
|
8631
8631
|
return false;
|
|
8632
8632
|
}, COMMAND_PRIORITY_EDITOR), editor.registerCommand(FOCUS_COMMAND, () => {
|
|
8633
|
-
|
|
8633
|
+
setHasFocus(editor.getRootElement() === document.activeElement);
|
|
8634
8634
|
return false;
|
|
8635
8635
|
}, COMMAND_PRIORITY_EDITOR));
|
|
8636
8636
|
}, []);
|
|
@@ -9839,11 +9839,11 @@ const GrepDialogServiceProvider = ({ children, }) => {
|
|
|
9839
9839
|
setDialogState(options);
|
|
9840
9840
|
setDialogOpen(true);
|
|
9841
9841
|
};
|
|
9842
|
-
return (React__default.createElement(GrepDialogServiceContext
|
|
9842
|
+
return (React__default.createElement(GrepDialogServiceContext, { value: openDialog },
|
|
9843
9843
|
React__default.createElement(GrepDialog, { open: dialogOpen, onClose: () => setDialogOpen(false), ...dialogState }),
|
|
9844
9844
|
children));
|
|
9845
9845
|
};
|
|
9846
|
-
const useGrepDialog = () =>
|
|
9846
|
+
const useGrepDialog = () => use(GrepDialogServiceContext);
|
|
9847
9847
|
|
|
9848
9848
|
/**
|
|
9849
9849
|
* lodash (Custom Build) <https://lodash.com/>
|
|
@@ -10318,15 +10318,15 @@ const initial = {
|
|
|
10318
10318
|
throw Error('not implemented');
|
|
10319
10319
|
},
|
|
10320
10320
|
};
|
|
10321
|
-
const
|
|
10322
|
-
|
|
10321
|
+
const Context = React__default.createContext(initial);
|
|
10322
|
+
Context.displayName = 'Grep.ToC.Context';
|
|
10323
10323
|
|
|
10324
10324
|
const defaultSelector = [...new Array(9)]
|
|
10325
10325
|
.map((_, i) => `h${i + 1}:not([role="presentation"])`)
|
|
10326
10326
|
.join(',');
|
|
10327
10327
|
const GrepTableOfContentProvider = ({ ...props }) => {
|
|
10328
10328
|
const { container, identifier, onSelected, classes, scrollTarget, children, offsetTop = -10, identifyElementFn = identifyElement, } = props;
|
|
10329
|
-
const [selected,
|
|
10329
|
+
const [selected, setSelected] = useState();
|
|
10330
10330
|
const [initialized, setInitialized] = useState();
|
|
10331
10331
|
const hash = useLocation().hash;
|
|
10332
10332
|
const scrollToElement = useCallback((element) => {
|
|
@@ -10340,10 +10340,10 @@ const GrepTableOfContentProvider = ({ ...props }) => {
|
|
|
10340
10340
|
return identifyElementFn(identifier || generateElementId);
|
|
10341
10341
|
}, [identifier, identifyElementFn]);
|
|
10342
10342
|
const elements = useContentElements(container, props.selector || defaultSelector, { identify });
|
|
10343
|
-
const
|
|
10343
|
+
const _setSelected = useCallback(throttle((element, scroll) => {
|
|
10344
10344
|
element && scroll && scrollToElement(element);
|
|
10345
|
-
|
|
10346
|
-
}, 50, { trailing: false }), [
|
|
10345
|
+
setSelected(element);
|
|
10346
|
+
}, 50, { trailing: false }), [setSelected, scrollToElement]);
|
|
10347
10347
|
const getViewportElement = useCallback(() => {
|
|
10348
10348
|
const records = Object.values(elements);
|
|
10349
10349
|
if (!records.length)
|
|
@@ -10364,13 +10364,13 @@ const GrepTableOfContentProvider = ({ ...props }) => {
|
|
|
10364
10364
|
return;
|
|
10365
10365
|
const onScroll = throttle(() => {
|
|
10366
10366
|
const element = getViewportElement();
|
|
10367
|
-
|
|
10367
|
+
_setSelected(element);
|
|
10368
10368
|
}, 50);
|
|
10369
10369
|
target.addEventListener('scroll', onScroll, false);
|
|
10370
10370
|
return () => {
|
|
10371
10371
|
return target.removeEventListener('scroll', onScroll);
|
|
10372
10372
|
};
|
|
10373
|
-
}, [scrollTarget,
|
|
10373
|
+
}, [scrollTarget, _setSelected, offsetTop, getViewportElement]);
|
|
10374
10374
|
// notify observer when selected change
|
|
10375
10375
|
useEffect(() => {
|
|
10376
10376
|
selected && onSelected && onSelected(selected);
|
|
@@ -10378,15 +10378,15 @@ const GrepTableOfContentProvider = ({ ...props }) => {
|
|
|
10378
10378
|
// observe changes in hash
|
|
10379
10379
|
useEffect(() => {
|
|
10380
10380
|
if (hash && elements[hash]) {
|
|
10381
|
-
|
|
10381
|
+
_setSelected(elements[hash], true);
|
|
10382
10382
|
}
|
|
10383
|
-
}, [hash,
|
|
10383
|
+
}, [hash, _setSelected]);
|
|
10384
10384
|
// set selected element on initial load
|
|
10385
10385
|
if (!initialized && elements && elements[hash]) {
|
|
10386
|
-
|
|
10386
|
+
_setSelected(elements[hash], true);
|
|
10387
10387
|
setInitialized(true);
|
|
10388
10388
|
}
|
|
10389
|
-
return (React__default.createElement(
|
|
10389
|
+
return (React__default.createElement(Context, { value: { elements, selected, classes, setSelected: _setSelected } }, children));
|
|
10390
10390
|
};
|
|
10391
10391
|
GrepTableOfContentProvider.displayName = 'Grep.ToC.Provider';
|
|
10392
10392
|
|
|
@@ -10424,7 +10424,7 @@ const GrepTableOfContentNavTreeNode = (props) => {
|
|
|
10424
10424
|
const linkRef = useRef(null);
|
|
10425
10425
|
const { node, style, renderChilds, setSelectedValue, percentageRendered } = props;
|
|
10426
10426
|
const { lvl, el, index, children } = node;
|
|
10427
|
-
const { selected, setSelected, classes, elements } =
|
|
10427
|
+
const { selected, setSelected, classes, elements } = use(Context);
|
|
10428
10428
|
const isSelected = el === selected;
|
|
10429
10429
|
const { classes: styles } = useStyles$2({ lvl });
|
|
10430
10430
|
const className = clsx('grep-toc__nav-tree-node', isSelected && 'grep-toc__nav-tree-node--selected', styles.root, classes?.node, props.className);
|
|
@@ -10480,7 +10480,7 @@ const useStyles$1 = makeStyles()(() => ({
|
|
|
10480
10480
|
|
|
10481
10481
|
const NavTree = (props) => {
|
|
10482
10482
|
const { elements, style, setSelectedValue, percentageRendered } = props;
|
|
10483
|
-
const { classes } =
|
|
10483
|
+
const { classes } = use(Context);
|
|
10484
10484
|
const { classes: styles } = useStyles$1();
|
|
10485
10485
|
const className = clsx('grep-toc__nav-tree', styles.root, classes?.tree, props.className);
|
|
10486
10486
|
return (React__default.createElement("ul", { className: className, style: style }, Object.values(elements).map((node) => (React__default.createElement(GrepTableOfContentNavTreeNode, { node: node, key: node.index, renderChilds: (children) => (React__default.createElement(NavTree, { elements: children, setSelectedValue: setSelectedValue, percentageRendered: percentageRendered })), setSelectedValue: setSelectedValue, percentageRendered: percentageRendered })))));
|
|
@@ -10530,7 +10530,7 @@ const buildTree = (elements, normalizer = normalize) => {
|
|
|
10530
10530
|
|
|
10531
10531
|
const GrepTableOfContentNav = (props) => {
|
|
10532
10532
|
const ref = useRef(null);
|
|
10533
|
-
const { elements, classes, selected, setSelected } =
|
|
10533
|
+
const { elements, classes, selected, setSelected } = use(Context);
|
|
10534
10534
|
const tree = useMemo(() => buildTree(Object.values(elements)), [elements]);
|
|
10535
10535
|
const focusSelected = useCallback(() => {
|
|
10536
10536
|
requestAnimationFrame(() => {
|