@ ariakit/ utils (英语)
重要内容: 这个软件包是Ariakit的内部依赖性,不遵循语义化的版本,意思是断裂变化可能发生在补丁和小版本中.
Ariakit软件包使用的共享框架不可知公用事业.
目录
安装
npm i @ariakit/utils
使用量
从包根导入助手 :
import { invariant } from "@ariakit/utils";
这一一揽子方案只采用无害环境管理,并暴露出单一的公众切入点.
API 参考
- 阵列公用事业
- DOM 公用事业
canUseDOMgetDocumentgetWindowGetActiveElementOptionsgetActiveElementcontainsisElementisNodeisFrameisButtonisVisibleisTextFieldisTextboxgetTextboxValuegetTextboxSelectiongetPopupRolegetItemRoleByPopupRolegetPopupItemRolescrollIntoViewIfNeededGetScrollingElementOptionsgetScrollingElementisPartiallyHiddensetSelectionRangesortBasedOnDOMPosition
- 二. 活动公用事业
- 二. 重点公用事业
isFocusableisTabbablegetAllFocusableIngetAllFocusablegetFirstFocusableIngetFirstFocusablegetAllTabbableIngetAllTabbablegetFirstTabbableIngetFirstTabbablegetLastTabbableIngetLastTabbablegetNextTabbableIngetNextTabbablegetPreviousTabbableIngetPreviousTabbablegetClosestFocusablehasFocushasFocusWithinfocusIfNeededdisableFocusdisableFocusInrestoreFocusInfocusIntoView
- 一般公用事业
- 平台公用事业
- 公用事业类型
- 撤消公用事业
阵列公用事业
Ariakit 软件包使用的串行帮助器 .
toArray
function toArray<T>(arg: T): T extends readonly any[] ? T : T[];
变换 arg 如果还没有进入数组.
示例
toArray("a"); // ["a"]
toArray(["a"]); // ["a"]
addItemToArray
function addItemToArray<T extends any[]>(
array: T,
item: T[number],
index = -1,
): T;
当然,在一个阵列中添加一个项.
返回:通过数组索引中包含项目的新数组.
示例
addItemToArray(["a", "b", "d"], "c", 2); // ["a", "b", "c", "d"]
flatten2DArray
function flatten2DArray<T>(array: T[][]): T[];
将2D阵列平整为一维阵列.
返回:一个一维阵列.
示例
flatten2DArray([["a"], ["b"], ["c"]]); // ["a", "b", "c"]
reverseArray
function reverseArray<T>(array: T[]): T[];
自动反转数组 .
返回:倒数组.
示例
reverseArray(["a", "b", "c"]); // ["c", "b", "a"]
DOM 公用事业
DOM帮助浏览器,iframe,文本输入,弹出和滚动行为.
canUseDOM
const canUseDOM: boolean;
这是 true 如果它在浏览器环境中运行或 false 如果不是的话.
示例
const title = canUseDOM ? document.title : "";
getDocument
function getDocument(node?: Window | Document | Node | null): Document;
返回文档 node 属于,或当它没有时属于当前.
getWindow
function getWindow(
node?: Window | Document | Node | null,
): Window & typeof globalThis;
返回窗口 node 属于,或当它没有时属于当前.
GetActiveElementOptions
interface GetActiveElementOptions {
/**
* Whether to resolve focus that lives inside a frame into that frame's own
* document. Pass `false` to decide ownership in `node`'s document, where
* focus inside a frame is represented by the frame element.
* @default true
*/
frame?: boolean;
/**
* Whether to resolve the element referenced by the focused element's
* `aria-activedescendant` attribute.
* @default false
*/
activeDescendant?: boolean;
}
getActiveElement
function getActiveElement(
node?: Node | null,
{ frame = true, activeDescendant = false }: GetActiveElementOptions = {},
): HTMLElement | null;
返回焦点元素 node'文件,溶入焦点框架自己的文件,除非 frame 实值 false。 。 。 .
示例
// Focus inside a frame, as the frame element rather than the inner element.
getActiveElement(document.getElementById("dialog"), { frame: false });
contains
function contains(parent: Node, child: Node): boolean;
类似 Element.prototype.contains不过要快一点 element 与 child。 。 。 .
示例
contains(document.getElementById("parent"), document.getElementById("child"));
isElement
function isElement(target: EventTarget | null | undefined): target is Element;
检查指定事件目标是否为元素 .
event.target 财务报告和审定财务报表 event.relatedTarget 为: EventTargets,这些不一定是元素——例如: window 或一个 XMLHttpRequest 当一个事件被按程序发送时。 通话 Element- 仅限方法,例如 hasAttribute 在投出之前 注意这个 然后再把它们当作元素 当你只需要一个 Node ——例如打电话 contains ——使用 isNode 换句话说.
测试 nodeType 而不是说 instanceof Element 使来自同源儿童框架的元素 addGlobalEventListener 也听了),没有被错误地拒绝,因为属于不同的领域.
示例
if (isElement(event.target)) {
event.target.hasAttribute("data-active");
}
isNode
function isNode(target: EventTarget | null | undefined): target is Node;
检查指定事件目标是否为节点 .
喜欢 isElement,但只要求目标是一个 Node 而不是一个因素——在召唤之前有用 contains,它接受任何节点。 它仍然拒绝非节点 EventTargets(例如: window 或一个 XMLHttpRequest) 将产生 contains 掷出.
示例
if (isNode(event.target)) {
contains(element, event.target);
}
isFrame
function isFrame(element: Element): element is HTMLIFrameElement;
检查是否 element 是一个框架元素.
isButton
function isButton(element: { tagName: string; type?: string }): boolean;
检查是否 element 是本地 HTML 按钮元素.
示例
isButton(document.querySelector("button")); // true
isButton(document.querySelector("input[type='button']")); // true
isButton(document.querySelector("div")); // false
isButton(document.querySelector("input[type='text']")); // false
isButton(document.querySelector("div[role='button']")); // false
isVisible
function isVisible(element: Element): boolean;
检查元素是否可见 .
isTextField
function isTextField(
element: Element,
): element is HTMLInputElement | HTMLTextAreaElement;
检查给定元素是否是一个文本字段,其中文本字段由输入内选择的能力所定义.
示例
isTextField(document.querySelector("div")); // false
isTextField(document.querySelector("input")); // true
isTextField(document.querySelector("input[type='button']")); // false
isTextField(document.querySelector("textarea")); // true
isTextbox
function isTextbox(element: HTMLElement): boolean;
检查给定元素是文本字段还是内容可编辑元素 .
getTextboxValue
function getTextboxValue(element: HTMLElement): string;
返回文本字段或内容可编辑元素作为字符串的值.
getTextboxSelection
function getTextboxSelection(element: HTMLElement): {
start: number;
end: number;
};
返回元素中选择的起始和结尾相抵.
getPopupRole
function getPopupRole(
element?: Element | null,
fallback?: AriaHasPopup,
): AriaHasPopup;
返回元素角色属性中的弹出角色, 如果它有的话 .
getItemRoleByPopupRole
function getItemRoleByPopupRole(popupRole?: string | null): string | undefined;
返回基于弹出角色的项目角色 .
getPopupItemRole
function getPopupItemRole(
element?: Element | null,
fallback?: AriaRole,
): string | undefined;
返回基于弹出式角色的项目角色属性 .
scrollIntoViewIfNeeded
function scrollIntoViewIfNeeded(
element: Element,
arg?: boolean | ScrollIntoViewOptions,
): void;
电话 element.scrollIntoView() 如果该元素被隐藏或部分隐藏在取景口.
GetScrollingElementOptions
interface GetScrollingElementOptions {
/**
* The axis to check. By default, either axis can establish a scroll
* container.
*/
axis?: "x" | "y";
/**
* Returns this ancestor without testing its overflow or walking beyond it.
*/
stopAt?: Element;
}
getScrollingElement
function getScrollingElement(
element?: Element | null,
options: GetScrollingElementOptions = {},
): HTMLElement | Element | null;
返回给定元素的滚动容器元素.
isPartiallyHidden
function isPartiallyHidden(element: Element): boolean;
确定元素是隐藏还是部分隐藏在视图端口.
setSelectionRange
function setSelectionRange(
element: HTMLInputElement | HTMLTextAreaElement,
...args: Parameters<typeof HTMLInputElement.prototype.setSelectionRange>
): void;
SelectRange只工作于几类输入. 通话 setSelectionRange 在不支持的输入类型上,可能会对某些浏览器出错。 为避免出现这种情况,我们先检查其类型是否支持选择区域. 在找到工作之前,它不会成为非支持类型.
sortBasedOnDOMPosition
function sortBasedOnDOMPosition<T>(
items: T[],
getElement: (item: T) => Element | null | undefined,
): T[];
根据其 DOM 位置排序项目 .
二. 活动公用事业
用于发送和解释浏览器事件的事件助手.
isPortalEvent
function isPortalEvent(event: Pick<Event, "currentTarget" | "target">): boolean;
回返 true 若为 event 已经在一个反应门户元素内发射.
isSelfTarget
function isSelfTarget(event: Pick<Event, "target" | "currentTarget">): boolean;
回返 true 若为 event.target 财务报告和审定财务报表 event.currentTarget 都一样.
isOpeningInNewTab
function isOpeningInNewTab(
event: Pick<MouseEvent, "currentTarget" | "metaKey" | "ctrlKey">,
): boolean;
检查用户事件是否在新标签中触发页面导航 .
isDownloading
function isDownloading(
event: Pick<MouseEvent, "altKey" | "currentTarget">,
): boolean;
检查用户事件是否触发下载 .
fireEvent
function fireEvent(
element: Element,
type: string,
eventInit?: EventInit,
): boolean;
创建和发送一个事件.
示例
fireEvent(document.getElementById("id"), "blur", {
bubbles: true,
cancelable: true,
});
fireBlurEvent
function fireBlurEvent(element: Element, eventInit?: FocusEventInit): boolean;
创建并发送模糊事件 .
示例
fireBlurEvent(document.getElementById("id"));
fireFocusEvent
function fireFocusEvent(element: Element, eventInit?: FocusEventInit): boolean;
创建和发送焦点活动.
示例
fireFocusEvent(document.getElementById("id"));
fireKeyboardEvent
function fireKeyboardEvent(
element: Element,
type: string,
eventInit?: KeyboardEventInit,
): boolean;
创建并发送键盘事件.
示例
fireKeyboardEvent(document.getElementById("id"), "keydown", {
key: "ArrowDown",
shiftKey: true,
});
fireClickEvent
function fireClickEvent(
element: Element,
eventInit?: PointerEventInit | null,
): boolean;
创建并发送点击事件.
这个事件是 PointerEvent 由拥有元素的窗口所建, 浏览器发送的方式, 返回到一个 MouseEvent 在窗口没有 PointerEvent。 。 view 那扇窗是真实的 Window,或 null 否则,它就由它组成。 它报告点击后没有指针,除非呼叫者通过一个指针,并报告其他每个指针属性的默认值,即点击总是这样.
示例
fireClickEvent(document.getElementById("id"));
isFocusEventOutside
function isFocusEventOutside(
event: Pick<FocusEvent, "currentTarget" | "relatedTarget">,
container?: Element | null,
): boolean;
检查焦点/ blur 事件是否从容器元素的外出/ 从外出 .
示例
const element = document.getElementById("id");
element.addEventListener("blur", (event) => {
if (isFocusEventOutside(event)) {
// ...
}
});
getInputType
function getInputType(
event: Event | { nativeEvent: Event },
): string | undefined;
返回 inputType (a) 活动财产,如果有的话.
isInputEvent
function isInputEvent(event: Event): event is InputEvent;
检查事件是否为输入事件 .
queueBeforeEvent
function queueBeforeEvent(
element: Element,
type: string,
callback: () => void,
timeout?: number,
): () => void;
在下一个动画框上运行回调,但在某个事件之前运行.
addGlobalEventListener
function addGlobalEventListener<K extends keyof DocumentEventMap>(
type: K,
listener: (event: DocumentEventMap[K]) => any,
options?: boolean | AddEventListenerOptions,
scope?: Window,
): () => void;
function addGlobalEventListener(
type: string,
listener: EventListenerOrEventListenerObject,
options?: boolean | AddEventListenerOptions,
scope?: Window,
): () => void;
添加一个全局活动收听器,包括儿童帧.
二. 重点公用事业
可聚焦和可制表元素的焦点管理助手.
isFocusable
function isFocusable(element: Element): boolean;
检查是否 element 可聚焦与否.
示例
isFocusable(document.querySelector("input")); // true
isFocusable(document.querySelector("input[tabindex='-1']")); // true
isFocusable(document.querySelector("input[hidden]")); // false
isFocusable(document.querySelector("input:disabled")); // false
isTabbable
function isTabbable(
element: Element | HTMLElement | HTMLInputElement,
): element is HTMLElement;
检查是否 element 是否可制表.
示例
isTabbable(document.querySelector("input")); // true
isTabbable(document.querySelector("input[tabindex='-1']")); // false
isTabbable(document.querySelector("input[hidden]")); // false
isTabbable(document.querySelector("input:disabled")); // false
getAllFocusableIn
function getAllFocusableIn(
container: HTMLElement,
includeContainer?: boolean,
): HTMLElement[];
返回所有可聚焦元素 container。 。 。 .
getAllFocusable
function getAllFocusable(includeBody?: boolean): HTMLElement[];
返回文档中的所有可聚焦元素.
getFirstFocusableIn
function getFirstFocusableIn(
container: HTMLElement,
includeContainer?: boolean,
): HTMLElement | null;
返回第一个可聚焦元素 container。 。 。 .
getFirstFocusable
function getFirstFocusable(includeBody?: boolean): HTMLElement | null;
返回文档中的第一个可聚焦元素.
getAllTabbableIn
function getAllTabbableIn(
container: HTMLElement,
includeContainer?: boolean,
fallbackToFocusable?: boolean,
): HTMLElement[];
返回所有可制表元素 container包括集装箱本身.
getAllTabbable
function getAllTabbable(fallbackToFocusable?: boolean): HTMLElement[];
返回文档中的所有可制表元素.
getFirstTabbableIn
function getFirstTabbableIn(
container: HTMLElement,
includeContainer?: boolean,
fallbackToFocusable?: boolean,
): HTMLElement | null;
返回第一个可制表元素 container包括容器本身,如果它是可标签的.
getFirstTabbable
function getFirstTabbable(fallbackToFocusable?: boolean): HTMLElement | null;
返回文档中的第一个可制表元素.
getLastTabbableIn
function getLastTabbableIn(
container: HTMLElement,
includeContainer?: boolean,
fallbackToFocusable?: boolean,
): HTMLElement | null;
返回最后一个可制表元素 container包括容器本身,如果它是可标签的.
getLastTabbable
function getLastTabbable(fallbackToFocusable?: boolean): HTMLElement | null;
返回文档中最后一个可制表元素.
getNextTabbableIn
function getNextTabbableIn(
container: HTMLElement,
includeContainer?: boolean,
fallbackToFirst?: boolean,
fallbackToFocusable?: boolean,
): HTMLElement | null;
返回下一个可制表元素 container。 。 。 .
getNextTabbable
function getNextTabbable(
fallbackToFirst?: boolean,
fallbackToFocusable?: boolean,
): HTMLElement | null;
返回文档中的下一个可制表元素.
getPreviousTabbableIn
function getPreviousTabbableIn(
container: HTMLElement,
includeContainer?: boolean,
fallbackToLast?: boolean,
fallbackToFocusable?: boolean,
): HTMLElement | null;
返回上一个可制表元素 container。 。 。 .
getPreviousTabbable
function getPreviousTabbable(
fallbackToLast?: boolean,
fallbackToFocusable?: boolean,
): HTMLElement | null;
返回文档中先前的可制表元素.
getClosestFocusable
function getClosestFocusable(element?: HTMLElement | null): HTMLElement | null;
返回最接近的可聚焦元素 .
hasFocus
function hasFocus(element: Element): boolean;
检查是否 element 有焦点。 参考的要点 aria-activedescendant 还将考虑.
示例
hasFocus(document.getElementById("id"));
hasFocusWithin
function hasFocusWithin(element: Node | Element): boolean;
检查是否 element 专注在内部。 参考的要点 aria-activedescendant 还将考虑.
示例
hasFocusWithin(document.getElementById("id"));
focusIfNeeded
function focusIfNeeded(element: HTMLElement): void;
只有当元素还没有被聚焦时,才关注元素.
disableFocus
function disableFocus(element: HTMLElement): void;
禁用焦点 element。 。 。 .
disableFocusIn
function disableFocusIn(
container: HTMLElement,
includeContainer?: boolean,
): void;
使容器内的元素不具有可标签性.
restoreFocusIn
function restoreFocusIn(container: HTMLElement): void;
恢复容器内受禁用FocusIn影响的可标签元素.
focusIntoView
function focusIntoView(
element: HTMLElement,
options?: ScrollIntoViewOptions,
): void;
注重元素并滚动到视图中.
一般公用事业
通用辅助器用于状态,对象,字符串,调度,以及断言.
noop
function noop(..._: any[]): any;
空函数 .
shallowEqual
function shallowEqual(a?: AnyObject, b?: AnyObject): boolean;
比较两个对象.
示例
shallowEqual({ a: "a" }, {}); // false
shallowEqual({ a: "a" }, { b: "b" }); // false
shallowEqual({ a: "a" }, { a: "a" }); // true
shallowEqual({ a: "a" }, { a: "a", b: "b" }); // false
applyState
function applyState<T>(
argument: SetStateAction<T>,
currentValue: T | (() => T),
): T;
接收 a setState 参数和调用 currentValue 如果这是一个函数。 否则, 将参数作为新值返回 .
示例
applyState((value) => value + 1, 1); // 2
applyState(2, 1); // 2
isObject
function isObject(arg: any): arg is Record<any, unknown>;
检查是否 arg 是否为对象.
isEmpty
function isEmpty(arg: any): boolean;
检查是否 arg 是否为空.
示例
isEmpty([]); // true
isEmpty(["a"]); // false
isEmpty({}); // true
isEmpty({ a: "a" }); // false
isEmpty(); // true
isEmpty(null); // true
isEmpty(undefined); // true
isEmpty(""); // true
isInteger
function isInteger(arg: any): boolean;
检查是否 arg 是否为整数.
示例
isInteger(1); // true
isInteger(1.5); // false
isInteger("1"); // true
isInteger("1.5"); // false
hasOwnProperty
function hasOwnProperty<T extends AnyObject>(
object: T,
prop: keyof any,
): prop is keyof T;
检查是否 prop 属于 obj 或无.
chain
function chain<T>(
...fns: T[]
): (...args: T extends AnyFunction ? Parameters<T> : never) => void;
接收函数作为参数并返回调用全部的新函数.
cx
function cx(
...args: Array<string | null | false | 0 | undefined>
): string | undefined;
返回带有以下真值的字符串: args 以空间分隔 .
normalizeString
function normalizeString(str: string): string;
从字符串中去除二甲酸盐.
omit
function omit<T extends AnyObject, K extends keyof T>(
object: T,
keys: ReadonlyArray<K> | K[],
): Omit<T, K>;
关闭对象的特定密钥.
示例
omit({ a: "a", b: "b" }, ["a"]); // { b: "b" }
pick
function pick<T extends AnyObject, K extends keyof T>(
object: T,
paths: ReadonlyArray<K> | K[],
): Pick<T, K>;
从对象中选择特定的密钥.
示例
pick({ a: "a", b: "b" }, ["a"]); // { a: "a" }
identity
function identity<T>(value: T): T;
返回相同的参数.
beforePaint
function beforePaint(cb: () => void = noop): () => void;
在下一个油漆之前就跑.
afterPaint
function afterPaint(cb: () => void = noop): () => void;
下作相后行行相.
warnOnce
function warnOnce(message: string, key?: object): void;
每个消息和密钥只记录一次警告.
示例
if (process.env.NODE_ENV !== "production") {
warnOnce("Warning");
}
invariant
function invariant(
condition: any,
message?: string | boolean,
): asserts condition;
确认一个条件是真实的,否则会丢出一个错误.
示例
invariant(
condition,
process.env.NODE_ENV !== "production" && "Invariant failed",
);
getKeys
function getKeys<T extends object>(obj: T): (keyof T)[];
类似 Object.keys 但返回一个类型安全的密钥数组.
isFalsyBooleanCallback
function isFalsyBooleanCallback<T extends unknown[]>(
booleanOrCallback?: boolean | ((...args: T) => boolean),
...args: T
): boolean;
检查布尔事件道具(例如隐藏 OnInteract Outside)是否被故意设定为虚假, 或带有布尔值, 或带有返回错误的回调 .
disabledFromProps
function disabledFromProps(props: {
disabled?: boolean;
"aria-disabled"?: boolean | "true" | "false";
}): boolean;
检查某物是否基于道具被禁用.
disabledFromElement
function disabledFromElement(element: Element): boolean;
检查某物是否基于其 DOM 属性被禁用 .
removeUndefinedValues
function removeUndefinedValues<T extends AnyObject>(obj: T): T;
从对象中删除未定义的值。 只有自己的地产被复制,所以继承的可支配地产永远不会成为结果的地产. A 类 __proto__ 键被丢弃,因为它将取代结果的原型,而不是在结果中添加一个属性.
defaultValue
type DefaultValue<T extends readonly any[], Other = never> = T extends [
infer Head,
...infer Rest,
]
? Rest extends []
? T[number] | Other
: undefined extends Head
? DefaultValue<Rest, Exclude<Other | Head, undefined>>
: Exclude<T[number], undefined>
: never;
function defaultValue<T extends readonly any[]>(...values: T): DefaultValue<T>;
返回第一个不是的值 undefined。 。 。 .
平台公用事业
浏览器和平台检测帮助器.
isTouchDevice
function isTouchDevice(): boolean;
检测设备是否有触摸能力.
isApple
function isApple(): boolean;
探测苹果设备.
isSafari
function isSafari(): boolean;
探测到Safari浏览器.
isFirefox
function isFirefox(): boolean;
检测 Firefox 浏览器 .
isMac
function isMac(): boolean;
检测Mac电脑.
公用事业类型
阿里阿基特套件使用的共享型公用事业.
AnyObject
type AnyObject = Record<string, any>;
任何物体.
EmptyObject
type EmptyObject = Record<keyof any, never>;
空对象.
AnyFunction
type AnyFunction = (...args: any) => any;
任何职能.
BivariantCallback
type BivariantCallback<T extends AnyFunction> = {
bivarianceHack(...args: Parameters<T>): ReturnType<T>;
}["bivarianceHack"];
解决差异问题.
SetStateAction
type SetStateAction<T> = T | BivariantCallback<(prevState: T) => T>;
SetState
type SetState<T> = BivariantCallback<(value: SetStateAction<T>) => void>;
类型 setState 函数在 [state, setState] = useState()。 。 。 .
BooleanOrCallback
type BooleanOrCallback<T> = boolean | BivariantCallback<(arg: T) => boolean>;
布尔值或返回布尔值的回调值.
StringWithValue
type StringWithValue<T extends string> = T | (string & Record<never, never>);
为特定字符串提供自动补全的字符串 .
ToPrimitive
type ToPrimitive<T> = T extends string
? string
: T extends number
? number
: T extends boolean
? boolean
: T extends AnyFunction
? (...args: Parameters<T>) => ReturnType<T>
: T;
将一个类型转换为原始类型.
示例
// string
ToPrimitive<"a">;
// number
ToPrimitive<1>;
PickByValue
type PickByValue<T, Value> = {
[
K in keyof T as [Value] extends [T[K]]
? T[K] extends Value | undefined
? K
: never
: never
]: T[K];
};
只从具有特定值的类型中选择属性.
PickRequired
type PickRequired<T, P extends keyof T> = T &
{
[K in keyof T]: Pick<Required<T>, K>;
}[P];
仅从类型中选择所需的属性.
AriaHasPopup
type AriaHasPopup =
| boolean
| "false"
| "true"
| "menu"
| "listbox"
| "tree"
| "grid"
| "dialog"
| undefined;
表示一个元素可以触发的互动弹出元素的可用性和类型,如菜单或对话框等.
AriaRole
type AriaRole =
| "alert"
| "alertdialog"
| "application"
| "article"
| "banner"
| "button"
| "cell"
| "checkbox"
| "columnheader"
| "combobox"
| "complementary"
| "contentinfo"
| "definition"
// ... 53 more lines
| "tree"
| "treegrid"
| "treeitem"
| (string & {});
WAI-ARIA 1.1 所有角色属性值来自 https://www.w3.org/TR/wai-aria-1.1/#作用 定义
撤消公用事业
撤消和重做管理工具 .
UndoManager
type Callback = void | (() => Callback | Promise<Callback>);
const UndoManager: { canUndo: () => boolean; canRedo: () => boolean; undo: () => Promise<void>; redo: () => Promise<void>; execute: (callback: Callback, group?: string) => Promise<void>; };
共享取消管理器实例 .
createUndoManager
type Callback = void | (() => Callback | Promise<Callback>);
interface CreateUndoManagerOptions {
limit?: number;
}
function createUndoManager({ limit = 100 }: CreateUndoManagerOptions = {}): {
canUndo: () => boolean;
canRedo: () => boolean;
undo: () => Promise<void>;
redo: () => Promise<void>;
execute: (callback: Callback, group?: string) => Promise<void>;
};
创建带有撤销和重做堆栈的撤销管理器.