diff --git a/packages/plugin/package.json b/packages/plugin/package.json index 249539b..f3dcd68 100644 --- a/packages/plugin/package.json +++ b/packages/plugin/package.json @@ -26,7 +26,6 @@ "@arco-design/web-react": ">=2.60.3" }, "dependencies": { - "ahooks": "3.3.13", "react-live-runtime": "0.0.3", "embed-drawio": "0.0.18", "lodash-es": "4.17.21", diff --git a/packages/plugin/src/float-toolbar/index.tsx b/packages/plugin/src/float-toolbar/index.tsx index 600be7d..1cd052c 100644 --- a/packages/plugin/src/float-toolbar/index.tsx +++ b/packages/plugin/src/float-toolbar/index.tsx @@ -1,19 +1,19 @@ import "./styles/index.scss"; import { Menu } from "@arco-design/web-react"; -import { useMemoizedFn } from "ahooks"; import type { EditorKit } from "doc-editor-core"; import type { TextElement } from "doc-editor-delta"; import { Editor } from "doc-editor-delta"; import { ReactEditor } from "doc-editor-delta"; import { EVENT_ENUM } from "doc-editor-utils"; -import { omit } from "doc-editor-utils"; +import { Collection } from "doc-editor-utils"; import type { FC } from "react"; import React, { useEffect, useMemo, useRef, useState } from "react"; import { FONT_BASE_KEY } from "../font-base/types"; import { HYPER_LINK_KEY } from "../hyper-link/types"; import { LINE_HEIGHT_KEY } from "../line-height/types"; +import { useMemoFn } from "../shared/hooks/preset"; import { MenuItems } from "./components/menu"; import { execSelectMarks, getSelectionRect, maskMenuToolBar, Portal } from "./utils/selection"; @@ -32,11 +32,13 @@ export const MenuToolBar: FC<{ const toolbarRef = useRef(null); const [selectedMarks, setSelectedMarks] = useState([]); - const wakeUpToolbar = useMemoizedFn((wakeUp: boolean) => { + const wakeUpToolbar = useMemoFn((wakeUp: boolean) => { const toolbar = toolbarRef.current; if (!toolbar) return void 0; if (ReactEditor.isFocused(editor.raw) && wakeUp) { - setSelectedMarks(omit(Object.keys(Editor.marks(editor.raw) || []), NOT_INIT_SELECT)); + setSelectedMarks( + Collection.omit(Object.keys(Editor.marks(editor.raw) || []), NOT_INIT_SELECT) + ); const rect = getSelectionRect(); if (rect) { toolbar.style.top = `${rect.top + window.pageYOffset - TOOLBAR_OFFSET_HEIGHT - 10}px`; @@ -74,29 +76,27 @@ export const MenuToolBar: FC<{ }; }, [editor, wakeUpToolbar, props.readonly]); - const exec = useMemoizedFn( - (param: string, event: React.MouseEvent) => { - const [key, extraKey] = param.split("."); - const marks = Editor.marks(editor.raw); - const position = { left: 0, top: 0 }; - const toolbar = toolbarRef.current; - setSelectedMarks(execSelectMarks(key, selectedMarks, MUTEX_SELECT)); - if (toolbar) { - position.top = toolbar.offsetTop + toolbar.offsetHeight / 2; - position.left = toolbar.offsetLeft + toolbar.offsetWidth / 2; - } - const result = props.editor.command.exec(key, { - extraKey, - event, - position, - marks: marks as TextElement, - }); - if (result) { - keepStatus.current = true; - result.then(() => (keepStatus.current = false)); - } + const exec = useMemoFn((param: string, event: React.MouseEvent) => { + const [key, extraKey] = param.split("."); + const marks = Editor.marks(editor.raw); + const position = { left: 0, top: 0 }; + const toolbar = toolbarRef.current; + setSelectedMarks(execSelectMarks(key, selectedMarks, MUTEX_SELECT)); + if (toolbar) { + position.top = toolbar.offsetTop + toolbar.offsetHeight / 2; + position.left = toolbar.offsetLeft + toolbar.offsetWidth / 2; } - ); + const result = props.editor.command.exec(key, { + extraKey, + event, + position, + marks: marks as TextElement, + }); + if (result) { + keepStatus.current = true; + result.then(() => (keepStatus.current = false)); + } + }); const HoverMenu = useMemo( () => ( diff --git a/packages/plugin/src/float-toolbar/utils/selection.ts b/packages/plugin/src/float-toolbar/utils/selection.ts index 4c6205a..faab564 100644 --- a/packages/plugin/src/float-toolbar/utils/selection.ts +++ b/packages/plugin/src/float-toolbar/utils/selection.ts @@ -1,4 +1,4 @@ -import { omit } from "doc-editor-utils"; +import { Collection } from "doc-editor-utils"; import ReactDOM from "react-dom"; export const maskMenuToolBar = (element: HTMLDivElement) => { @@ -24,8 +24,8 @@ export const execSelectMarks = (key: string, marks: string[], mutexKeys: string[ const isKeyInMarks = marks.indexOf(key) > -1; const isKeyInMutexKeys = mutexKeys.indexOf(key) > -1; return isKeyInMarks - ? omit(marks, [key]) + ? Collection.omit(marks, [key]) : isKeyInMutexKeys - ? [...omit(marks, mutexKeys), key] + ? [...Collection.omit(marks, mutexKeys), key] : [...marks, key]; }; diff --git a/packages/plugin/src/font-base/components/menu.tsx b/packages/plugin/src/font-base/components/menu.tsx index fa75a03..4dffcee 100644 --- a/packages/plugin/src/font-base/components/menu.tsx +++ b/packages/plugin/src/font-base/components/menu.tsx @@ -1,8 +1,8 @@ import { Button, InputNumber } from "@arco-design/web-react"; -import { useMemoizedFn } from "ahooks"; import type { FC } from "react"; import { useMemo } from "react"; +import { useMemoFn } from "../../shared/hooks/preset"; import type { FontBaseConfig } from "../types"; interface Props { @@ -29,14 +29,12 @@ export const FontBaseMenu: FC = props => { const left = props.left - 180; let changedConfig: FontBaseConfig = props.config; - const onChange = useMemoizedFn( - (key: keyof FontBaseConfig, value: string | number | undefined) => { - changedConfig = { ...changedConfig, [key]: value }; - props.onChange(changedConfig); - } - ); + const onChange = useMemoFn((key: keyof FontBaseConfig, value: string | number | undefined) => { + changedConfig = { ...changedConfig, [key]: value }; + props.onChange(changedConfig); + }); - const resetDefault = useMemoizedFn(() => { + const resetDefault = useMemoFn(() => { props.onChange({}); changedConfig = {}; }); diff --git a/packages/plugin/src/highlight-block/components/wrapper.tsx b/packages/plugin/src/highlight-block/components/wrapper.tsx index 356ecc6..f54b9c6 100644 --- a/packages/plugin/src/highlight-block/components/wrapper.tsx +++ b/packages/plugin/src/highlight-block/components/wrapper.tsx @@ -1,6 +1,5 @@ import { Button, Trigger } from "@arco-design/web-react"; import { IconPalette } from "@arco-design/web-react/icon"; -import { useMemoizedFn } from "ahooks"; import type { EditorKit } from "doc-editor-core"; import type { BlockElement } from "doc-editor-delta"; import { ReactEditor } from "doc-editor-delta"; @@ -9,6 +8,7 @@ import { setBlockNode } from "doc-editor-utils"; import type { FC } from "react"; import { useMemo } from "react"; +import { useMemoFn } from "../../shared/hooks/preset"; import { HIGHLIGHT_BLOCK_KEY } from "../types"; import { COLOR_MAP } from "../types"; @@ -20,7 +20,7 @@ export const HighlightBlockWrapper: FC<{ }> = props => { const { editor, element, config, readonly } = props; - const switchAction = useMemoizedFn((index: number) => { + const switchAction = useMemoFn((index: number) => { const path = ReactEditor.findPath(editor.raw, element); setBlockNode( editor.raw, diff --git a/packages/plugin/src/react-live/components/viewer.tsx b/packages/plugin/src/react-live/components/viewer.tsx index 43d1460..83355f9 100644 --- a/packages/plugin/src/react-live/components/viewer.tsx +++ b/packages/plugin/src/react-live/components/viewer.tsx @@ -1,8 +1,8 @@ import { Button, Space, Spin } from "@arco-design/web-react"; -import { useDebounceEffect } from "ahooks"; import type { EditorKit } from "doc-editor-core"; import { Void } from "doc-editor-core"; import type { BlockElement } from "doc-editor-delta"; +import { debounce } from "doc-editor-utils"; import { isText } from "doc-editor-utils"; import type { FC } from "react"; import React, { useEffect, useMemo, useRef, useState } from "react"; @@ -26,31 +26,33 @@ export const ReactLiveView: FC<{ .join("\n"); }, [props.element]); - useDebounceEffect( - () => { - const el = ref.current; - if (!el) return; - try { - const sandbox = withSandbox({ React, Button, console, Space }); - // JS Plain Object -> ({...}) - // React.FC -> React.Fragment / div - const compiledCode = compileWithSucrase("
" + code + "
"); - const Component = renderWithDependency(compiledCode, sandbox) as JSX.Element; - const App = () => { - useEffect(() => { - setLoading(false); - }, []); - return Component; - }; - ReactDOM.render(, el); - } catch (error) { - console.log("Render Component Error", error); - } - }, - [code], - { wait: 300 } + const onParseCode = useMemo( + () => + debounce((code: string) => { + const el = ref.current; + if (!el) return; + try { + const sandbox = withSandbox({ React, Button, console, Space }); + // JS Plain Object -> ({...}) + // React.FC -> React.Fragment / div + const compiledCode = compileWithSucrase("
" + code + "
"); + const Component = renderWithDependency(compiledCode, sandbox) as JSX.Element; + const App = () => { + useEffect(() => { + setLoading(false); + }, []); + return Component; + }; + ReactDOM.render(, el); + } catch (error) { + console.log("Render Component Error", error); + } + }, 300), + [] ); + useEffect(() => onParseCode(code), [code, onParseCode]); + return (
diff --git a/packages/plugin/src/table/components/cell.tsx b/packages/plugin/src/table/components/cell.tsx index 38e814b..7b7724f 100644 --- a/packages/plugin/src/table/components/cell.tsx +++ b/packages/plugin/src/table/components/cell.tsx @@ -3,7 +3,7 @@ import { EDITOR_STATE } from "doc-editor-core"; import type { SetNodeOperation } from "doc-editor-delta"; import { HistoryEditor, Transforms } from "doc-editor-delta"; import { cs, EVENT_ENUM, findNodePath, getNodeTupleByDepth, isNil } from "doc-editor-utils"; -import throttle from "lodash-es/throttle"; +import { throttle } from "doc-editor-utils"; import type { FC } from "react"; import { useMemo } from "react"; diff --git a/packages/plugin/src/table/components/table.tsx b/packages/plugin/src/table/components/table.tsx index 46b3bbe..4eaefaf 100644 --- a/packages/plugin/src/table/components/table.tsx +++ b/packages/plugin/src/table/components/table.tsx @@ -1,10 +1,10 @@ -import { useMemoizedFn } from "ahooks"; import type { BlockContext, EditorKit } from "doc-editor-core"; import { Transforms, useSelected } from "doc-editor-delta"; import { EVENT_ENUM } from "doc-editor-utils"; import type { FC } from "react"; import React, { useEffect, useMemo, useRef, useState } from "react"; +import { useMemoFn } from "../../shared/hooks/preset"; import type { SelectChangeEvent } from "../../shared/types/event"; import { createResizeObserver } from "../../shared/utils/resize"; import { useCompose } from "../hooks/use-compose"; @@ -85,7 +85,7 @@ export const Table: FC<{ }; }, [provider.ref, props.readonly]); - const onEditorSelectionChange = useMemoizedFn((e: SelectChangeEvent) => { + const onEditorSelectionChange = useMemoFn((e: SelectChangeEvent) => { const { previous, current } = e; if (!previous && current && sel) { setSel(null); diff --git a/packages/react/package.json b/packages/react/package.json index b3df50c..4e4ca95 100644 --- a/packages/react/package.json +++ b/packages/react/package.json @@ -25,7 +25,6 @@ "dependencies": { "@arco-design/web-react": "2.60.3", "react": "17.0.2", - "ahooks": "^3.3.13", "lodash-es": "4.17.21", "react-dom": "17.0.2", "doc-editor-core": "workspace: *", diff --git a/packages/utils/src/collection.ts b/packages/utils/src/collection.ts new file mode 100644 index 0000000..369bb2f --- /dev/null +++ b/packages/utils/src/collection.ts @@ -0,0 +1,84 @@ +import type { Array } from "laser-utils"; +import type { Object } from "laser-utils"; +import { isArray, isObject } from "laser-utils"; + +export class Collection { + /** + * Pick + * @param target Object.Any + * @param keys keyof Object.Any + */ + public static pick( + target: T, + keys: K | K[] + ): Pick { + const set: Set = new Set(isArray(keys) ? keys : [keys]); + const next = {} as T; + for (const key in target) { + if (!set.has(key)) continue; + next[key] = target[key]; + } + return next; + } + + /** + * Omit + * @param target Array.Any | Object.Any + * @param keys keys: Array.Any + */ + public static omit(target: T, keys: T): T; + public static omit(target: T, keys: K | K[]): Omit; + public static omit(target: T, keys: Array.Any): T | Object.Any { + const set = new Set(isArray(keys) ? keys : [keys]); + if (isObject(target)) { + const next = {} as Object.Unknown; + for (const key in target) { + if (set.has(key)) continue; + next[key] = target[key]; + } + return next; + } + return target.filter(item => !set.has(item)); + } + + /** + * Patch + * @param a Set | T[] + * @param b Set | T[] + */ + public static patch(a: Set | T[], b: Set | T[]) { + const prev = a instanceof Set ? a : new Set(a); + const next = b instanceof Set ? b : new Set(b); + const effects: T[] = []; + const added: T[] = []; + const removed: T[] = []; + for (const id of next) { + if (!prev.has(id)) added.push(id); + } + for (const id of prev) { + if (!next.has(id)) removed.push(id); + } + effects.push(...added, ...removed); + return { effects, added, removed }; + } + + /** + * Union + * @param a Set | T[] + * @param b Set | T[] + */ + public static union(a: Set | T[], b: Set | T[]) { + return [...a, ...b]; + } + + /** + * Intersection + * @param a Set | T[] + * @param b Set | T[] + */ + public static intersection(a: Set | T[], b: Set | T[]) { + const prev = [...a]; + const next = b instanceof Set ? b : new Set(b); + return new Set([...prev].filter(id => next.has(id))); + } +} diff --git a/packages/utils/src/decorator.ts b/packages/utils/src/decorator.ts new file mode 100644 index 0000000..659d4d1 --- /dev/null +++ b/packages/utils/src/decorator.ts @@ -0,0 +1,31 @@ +import { isFunction } from "laser-utils"; + +// ExperimentalDecorators +// https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-0.html + +/** + * Bind 装饰器 + * @param _ + * @param key + * @param descriptor + */ +export function Bind(_: T, key: string, descriptor: PropertyDescriptor): PropertyDescriptor { + const originalMethod = descriptor.value; + if (!isFunction(originalMethod)) { + throw new TypeError(`${originalMethod} is not a function`); + } + + return { + configurable: true, + get() { + const boundFunction = originalMethod.bind(this); + Object.defineProperty(this, key, { + value: boundFunction, + configurable: true, + writable: true, + enumerable: false, + }); + return boundFunction; + }, + }; +} diff --git a/packages/utils/src/filter.ts b/packages/utils/src/filter.ts deleted file mode 100644 index 888af17..0000000 --- a/packages/utils/src/filter.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { isObject } from "laser-utils"; - -type RecordObject = Record; - -export function omit>(target: T, keys: T): T; -export function omit(target: T, keys: K[]): Omit; -export function omit | RecordObject>( - target: T, - keys: unknown[] -): T | RecordObject { - const keySet = new Set(keys); - return isObject(target) - ? Object.keys(target).reduce( - (pre, cur) => (keySet.has(cur) ? pre : { ...pre, [cur]: target[cur] }), - {} - ) - : target.filter(item => !keySet.has(item)); -} - -export function pick(target: T, keys: K[]): Pick { - const keySet: Set = new Set(keys); - const a = Object.keys(target); - return a.reduce( - (pre, cur) => (keySet.has(cur) ? { ...pre, [cur]: target[cur] } : pre), - {} as Pick - ); -} diff --git a/packages/utils/src/index.ts b/packages/utils/src/index.ts index 0d027af..b8b8f9b 100644 --- a/packages/utils/src/index.ts +++ b/packages/utils/src/index.ts @@ -1,8 +1,9 @@ +export { Collection } from "./collection"; export type { AssertT } from "./common"; export { assertValue } from "./common"; export { DEFAULT_PRIORITY, EVENT_ENUM, KEYBOARD } from "./constant"; export { debounce } from "./debounce"; -export { omit, pick } from "./filter"; +export { Bind } from "./decorator"; export { findNodePath, getBlockNode, @@ -43,6 +44,7 @@ export { setUnWrapNodesExactly, setWrapNodes, } from "./set"; +export { throttle } from "./throttle"; export type { Func, Reflex } from "laser-utils"; export { Clipboard, diff --git a/packages/utils/src/throttle.ts b/packages/utils/src/throttle.ts new file mode 100644 index 0000000..712dbbd --- /dev/null +++ b/packages/utils/src/throttle.ts @@ -0,0 +1,82 @@ +/* eslint-disable @typescript-eslint/no-this-alias */ +/* eslint-disable @typescript-eslint/no-explicit-any */ + +import type { Func } from "laser-utils"; +import { isNil, isNumber } from "laser-utils"; + +type Fn = Func.Any; +type ThrottledFn = T & { + flush: () => void; + cancel: () => void; +}; + +type Options = { + wait: number; + leading?: boolean; + trailing?: boolean; +}; + +const DEFAULT_OPTIONS: Required = { + wait: 100, + leading: true, + trailing: true, +}; + +export const throttle = (fn: T, options: Options | number): ThrottledFn => { + let lastThis: any; + let lastArgs: any[] = []; + let lastInvokeTime = 0; + let timer: ReturnType | null = null; + const config = Object.assign( + { ...DEFAULT_OPTIONS }, + isNumber(options) ? { wait: options } : options + ); + const wait = config.wait; + const leading = config.leading; + const trailing = config.trailing; + + const clear = () => { + timer && clearTimeout(timer); + timer = null; + }; + + const invoke = () => { + lastInvokeTime = Date.now(); + fn.apply(lastThis, lastArgs); + clear(); + }; + + const flush = () => { + invoke(); + if (leading && !trailing) { + timer = setTimeout(clear, wait); + } + }; + + function throttled(this: unknown, ...args: any[]) { + lastThis = this; + lastArgs = args; + const now = Date.now(); + if (leading && trailing && isNil(timer)) { + // 此处没有处理多次调用才会触发`trailing`的情况 + // 即单次调用也会同时触发`leading`和`trailing` + // 如果必须要的话就将后续的`timer`赋值写入`else` + now - lastInvokeTime > wait && invoke(); + timer = setTimeout(invoke, wait); + return void 0; + } + if (!leading && trailing && isNil(timer)) { + timer = setTimeout(invoke, wait); + return void 0; + } + if (leading && !trailing && isNil(timer)) { + invoke(); + timer = setTimeout(clear, wait); + return void 0; + } + } + + throttled.flush = flush; + throttled.cancel = clear; + return throttled as ThrottledFn; +}; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 397d4f9..e6f5151 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -145,9 +145,6 @@ importers: '@arco-design/web-react': specifier: '>=2.60.3' version: 2.60.3(@types/react@17.0.2)(react-dom@17.0.1)(react@17.0.2) - ahooks: - specifier: 3.3.13 - version: 3.3.13(react@17.0.2) doc-editor-core: specifier: 'workspace: *' version: link:../core @@ -251,9 +248,6 @@ importers: '@arco-design/web-react': specifier: 2.60.3 version: 2.60.3(@types/react@17.0.2)(react-dom@17.0.2)(react@17.0.2) - ahooks: - specifier: ^3.3.13 - version: 3.7.10(react@17.0.2) doc-editor-core: specifier: 'workspace: *' version: link:../core @@ -3059,10 +3053,6 @@ packages: pretty-format: 29.7.0 dev: true - /@types/js-cookie@2.2.7: - resolution: {integrity: sha512-aLkWa0C0vO5b4Sr798E26QgOkss68Un0bLjs7u9qxzPT5CG+8DuNTffWES58YzJs3hrVAOs1wonycqEBqNJubA==} - dev: false - /@types/json-schema@7.0.15: resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} dev: true @@ -3822,44 +3812,6 @@ packages: indent-string: 4.0.0 dev: true - /ahooks-v3-count@1.0.0: - resolution: {integrity: sha512-V7uUvAwnimu6eh/PED4mCDjE7tokeZQLKlxg9lCTMPhN+NjsSbtdacByVlR1oluXQzD3MOw55wylDmQo4+S9ZQ==} - dev: false - - /ahooks@3.3.13(react@17.0.2): - resolution: {integrity: sha512-/1+KeZHvhEs7IGn2YX4DE8UY7wV7YM7iziFBvSFnYw95z9oNvasuSTu4BwLxCqdIdWEFLFwuLE3naRL3B8xZyQ==} - engines: {node: '>=8.0.0'} - peerDependencies: - react: ^16.8.0 || ^17.0.0 || ^18.0.0 - dependencies: - '@types/js-cookie': 2.2.7 - ahooks-v3-count: 1.0.0 - dayjs: 1.11.10 - intersection-observer: 0.12.2 - js-cookie: 2.2.1 - lodash: 4.17.21 - react: 17.0.2 - resize-observer-polyfill: 1.5.1 - screenfull: 5.2.0 - dev: false - - /ahooks@3.7.10(react@17.0.2): - resolution: {integrity: sha512-/HLYif7sFA/5qSuWKrwvjDbf3bq+sdaMrUWS7XGCDRWdC2FrG/i+u5LZdakMYc6UIgJTMQ7tGiJCV7sdU4kSIw==} - engines: {node: '>=8.0.0'} - peerDependencies: - react: ^16.8.0 || ^17.0.0 || ^18.0.0 - dependencies: - '@babel/runtime': 7.24.0 - dayjs: 1.11.10 - intersection-observer: 0.12.2 - js-cookie: 2.2.1 - lodash: 4.17.21 - react: 17.0.2 - resize-observer-polyfill: 1.5.1 - screenfull: 5.2.0 - tslib: 2.6.2 - dev: false - /ajv-errors@1.0.1(ajv@6.12.6): resolution: {integrity: sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ==} peerDependencies: @@ -8379,10 +8331,6 @@ packages: side-channel: 1.0.6 dev: true - /intersection-observer@0.12.2: - resolution: {integrity: sha512-7m1vEcPCxXYI8HqnL8CKI6siDyD+eIWSwgB3DZA+ZTogxk9I4CDnj4wilt9x/+/QbHI4YG5YZNmC6458/e9Ktg==} - dev: false - /ip-regex@2.1.0: resolution: {integrity: sha512-58yWmlHpp7VYfcdTwMTvwMmqx/Elfxjd9RXTDyMsbL7lLWmhMylLEqiYVLKuLzOZqVgiWXD9MfR62Vv89VRxkw==} engines: {node: '>=4'} @@ -9865,10 +9813,6 @@ packages: - ts-node dev: true - /js-cookie@2.2.1: - resolution: {integrity: sha512-HvdH2LzI/EAZcUwA8+0nKNtWHqS+ZmijLA30RwZA0bo7ToCckjK5MkGhjED9KoRcXO6BaGI3I9UIzSA1FKFPOQ==} - dev: false - /js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} @@ -13735,11 +13679,6 @@ packages: ajv-keywords: 3.5.2(ajv@6.12.6) dev: true - /screenfull@5.2.0: - resolution: {integrity: sha512-9BakfsO2aUQN2K9Fdbj87RJIEZ82Q9IGim7FqM5OsebfoFC6ZHXgDq/KvniuLTPdeM8wY2o6Dj3WQ7KeQCj3cA==} - engines: {node: '>=0.10.0'} - dev: false - /scroll-into-view-if-needed@2.2.20: resolution: {integrity: sha512-P9kYMrhi9f6dvWwTGpO5I3HgjSU/8Mts7xL3lkoH5xlewK7O9Obdc5WmMCzppln7bCVGNmf3qfoZXrpCeyNJXw==} dependencies: @@ -15087,10 +15026,6 @@ packages: /tslib@2.4.0: resolution: {integrity: sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==} - /tslib@2.6.2: - resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==} - dev: false - /tsutils@3.21.0(typescript@5.3.2): resolution: {integrity: sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==} engines: {node: '>= 6'}