@rc-component/util 1.11.1 → 1.12.0

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/README.md CHANGED
@@ -1,303 +1,92 @@
1
- # rc-util
1
+ <div align="center">
2
+ <h1>@rc-component/util</h1>
3
+ <p><sub><a href="https://ant.design"><img alt="Ant Design" height="14" src="https://gw.alipayobjects.com/zos/rmsportal/KDpgvguMpGfqaHPjicRK.svg" style="vertical-align: -0.125em;" /></a> Part of the Ant Design ecosystem.</sub></p>
4
+ <p>🛠️ Shared React utilities for rc-component packages.</p>
2
5
 
3
- Common Utils For React Component.
6
+ <p>
7
+ <a href="https://npmjs.org/package/@rc-component/util"><img alt="NPM version" src="https://img.shields.io/npm/v/@rc-component/util.svg?style=flat-square"></a>
8
+ <a href="https://npmjs.org/package/@rc-component/util"><img alt="npm downloads" src="https://img.shields.io/npm/dm/@rc-component/util.svg?style=flat-square"></a>
9
+ <a href="https://github.com/react-component/util/actions/workflows/react-component-ci.yml"><img alt="build status" src="https://github.com/react-component/util/actions/workflows/react-component-ci.yml/badge.svg"></a>
10
+ <a href="https://app.codecov.io/gh/react-component/util"><img alt="Codecov" src="https://img.shields.io/codecov/c/github/react-component/util/master.svg?style=flat-square"></a>
11
+ <a href="https://bundlephobia.com/package/@rc-component/util"><img alt="bundle size" src="https://img.shields.io/bundlephobia/minzip/@rc-component/util?style=flat-square"></a>
12
+ <a href="https://github.com/umijs/dumi"><img alt="dumi" src="https://img.shields.io/badge/docs%20by-dumi-blue?style=flat-square"></a>
13
+ </p>
14
+ </div>
4
15
 
5
- [![NPM version][npm-image]][npm-url]
6
- [![npm download][download-image]][download-url]
7
- [![build status][github-actions-image]][github-actions-url]
8
- [![Codecov][codecov-image]][codecov-url]
9
- [![bundle size][bundlephobia-image]][bundlephobia-url]
10
- [![dumi][dumi-image]][dumi-url]
16
+ <p align="center">English | <a href="./README.zh-CN.md">简体中文</a></p>
11
17
 
12
- [npm-image]: http://img.shields.io/npm/v/rc-util.svg?style=flat-square
13
- [npm-url]: http://npmjs.org/package/rc-util
14
- [travis-image]: https://img.shields.io/travis/react-component/util/master?style=flat-square
15
- [travis-url]: https://travis-ci.com/react-component/util
16
- [github-actions-image]: https://github.com/react-component/util/actions/workflows/react-component-ci.yml/badge.svg
17
- [github-actions-url]: https://github.com/react-component/util/actions/workflows/react-component-ci.yml
18
- [codecov-image]: https://img.shields.io/codecov/c/github/react-component/util/master.svg?style=flat-square
19
- [codecov-url]: https://app.codecov.io/gh/react-component/util
20
- [david-url]: https://david-dm.org/react-component/util
21
- [david-image]: https://david-dm.org/react-component/util/status.svg?style=flat-square
22
- [david-dev-url]: https://david-dm.org/react-component/util?type=dev
23
- [david-dev-image]: https://david-dm.org/react-component/util/dev-status.svg?style=flat-square
24
- [download-image]: https://img.shields.io/npm/dm/rc-util.svg?style=flat-square
25
- [download-url]: https://npmjs.org/package/rc-util
26
- [bundlephobia-url]: https://bundlephobia.com/package/rc-util
27
- [bundlephobia-image]: https://badgen.net/bundlephobia/minzip/rc-util
28
- [dumi-url]: https://github.com/umijs/dumi
29
- [dumi-image]: https://img.shields.io/badge/docs%20by-dumi-blue?style=flat-square
18
+ ## Highlights
30
19
 
31
- ## Install
32
-
33
- [![rc-util](https://nodei.co/npm/rc-util.png)](https://npmjs.org/package/rc-util)
34
-
35
- ## API
36
-
37
- ### createChainedFunction
38
-
39
- > (...functions): Function
40
-
41
- Create a function which will call all the functions with it's arguments from left to right.
42
-
43
- ```jsx|pure
44
- import createChainedFunction from 'rc-util/lib/createChainedFunction';
45
- ```
46
-
47
- ### deprecated
48
-
49
- > (prop: string, instead: string, component: string): void
50
-
51
- Log an error message to warn developers that `prop` is deprecated.
52
-
53
- ```jsx|pure
54
- import deprecated from 'rc-util/lib/deprecated';
55
- ```
56
-
57
- ### getContainerRenderMixin
58
-
59
- > (config: Object): Object
60
-
61
- To generate a mixin which will render specific component into specific container automatically.
62
-
63
- ```jsx|pure
64
- import getContainerRenderMixin from 'rc-util/lib/getContainerRenderMixin';
65
- ```
66
-
67
- Fields in `config` and their meanings.
68
-
69
- | Field | Type | Description | Default |
70
- | ------------- | ---------------------------- | -------------------------------------------------------------------------- | ------- |
71
- | autoMount | boolean | Whether to render component into container automatically | true |
72
- | autoDestroy | boolean | Whether to remove container automatically while the component is unmounted | true |
73
- | isVisible | (instance): boolean | A function to get current visibility of the component | - |
74
- | isForceRender | (instance): boolean | A function to determine whether to render popup even it's not visible | - |
75
- | getComponent | (instance, extra): ReactNode | A function to get the component which will be rendered into container | - |
76
- | getContainer | (instance): HTMLElement | A function to get the container | |
77
-
78
- ### Portal
79
-
80
- Render children to the specific container;
81
-
82
- ```jsx|pure
83
- import Portal from 'rc-util/lib/Portal';
84
- ```
85
-
86
- Props:
87
-
88
- | Prop | Type | Description | Default |
89
- | ------------ | --------------- | ------------------------------- | ------- |
90
- | children | ReactChildren | Content render to the container | - |
91
- | getContainer | (): HTMLElement | A function to get the container | - |
92
-
93
- ### getScrollBarSize
94
-
95
- > (fresh?: boolean): number
96
-
97
- Get the width of scrollbar.
98
-
99
- ```jsx|pure
100
- import getScrollBarSize from 'rc-util/lib/getScrollBarSize';
101
- ```
102
-
103
- ### guid
104
-
105
- > (): string
106
-
107
- To generate a global unique id across current application.
108
-
109
- ```jsx|pure
110
- import guid from 'rc-util/lib/guid';
111
- ```
112
-
113
- ### pickAttrs
114
-
115
- > (props: Object): Object
116
-
117
- Pick valid HTML attributes and events from props.
118
-
119
- ```jsx|pure
120
- import pickAttrs from 'rc-util/lib/pickAttrs';
121
- ```
122
-
123
- ### warn
124
-
125
- > (msg: string): void
126
-
127
- A shallow wrapper of `console.warn`.
128
-
129
- ```jsx|pure
130
- import warn from 'rc-util/lib/warn';
131
- ```
132
-
133
- ### warning
134
-
135
- > (valid: boolean, msg: string): void
136
-
137
- A shallow wrapper of [warning](https://github.com/BerkeleyTrue/warning), but only warning once for the same message.
138
-
139
- ```jsx|pure
140
- import warning, { noteOnce } from 'rc-util/lib/warning';
20
+ - Built for React and maintained by the rc-component team.
21
+ - Used by Ant Design and other React component libraries.
22
+ - Ships TypeScript declarations with both ES module and CommonJS outputs.
23
+ - Keeps examples, tests, and preview builds aligned with the package source.
141
24
 
142
- warning(false, '[antd Component] test hello world');
25
+ > This package was historically published as `rc-util`. Prefer the scoped package for new code.
143
26
 
144
- // Low level note
145
- noteOnce(false, '[antd Component] test hello world');
146
- ```
147
-
148
- ### Children
149
-
150
- A collection of functions to operate React elements' children.
151
-
152
- #### Children/mapSelf
153
-
154
- > (children): children
155
-
156
- Return a shallow copy of children.
157
-
158
- ```jsx|pure
159
- import mapSelf from 'rc-util/lib/Children/mapSelf';
160
- ```
161
-
162
- #### Children/toArray
163
-
164
- > (children: ReactNode[]): ReactNode[]
165
-
166
- Convert children into an array.
167
-
168
- ```jsx|pure
169
- import toArray from 'rc-util/lib/Children/toArray';
170
- ```
171
-
172
- ### Dom
173
-
174
- A collection of functions to operate DOM elements.
175
-
176
- #### Dom/addEventlistener
177
-
178
- > (target: ReactNode, eventType: string, listener: Function): { remove: Function }
179
-
180
- A shallow wrapper of [add-dom-event-listener](https://github.com/yiminghe/add-dom-event-listener).
181
-
182
- ```jsx|pure
183
- import addEventlistener from 'rc-util/lib/Dom/addEventlistener';
184
- ```
185
-
186
- #### Dom/canUseDom
187
-
188
- > (): boolean
189
-
190
- Check if DOM is available.
191
-
192
- ```jsx|pure
193
- import canUseDom from 'rc-util/lib/Dom/canUseDom';
194
- ```
195
-
196
- #### Dom/class
197
-
198
- A collection of functions to operate DOM nodes' class name.
199
-
200
- - `hasClass(node: HTMLElement, className: string): boolean`
201
- - `addClass(node: HTMLElement, className: string): void`
202
- - `removeClass(node: HTMLElement, className: string): void`
27
+ ## Install
203
28
 
204
- ```jsx|pure
205
- import cssClass from 'rc-util/lib/Dom/class;
29
+ ```bash
30
+ npm install @rc-component/util
206
31
  ```
207
32
 
208
- #### Dom/contains
33
+ ## Usage
209
34
 
210
- > (root: HTMLElement, node: HTMLElement): boolean
211
-
212
- Check if node is equal to root or in the subtree of root.
213
-
214
- ```jsx|pure
215
- import contains from 'rc-util/lib/Dom/contains';
35
+ ```tsx | pure
36
+ import {
37
+ Portal,
38
+ raf,
39
+ useEvent,
40
+ useLayoutEffect,
41
+ warning,
42
+ } from '@rc-component/util';
216
43
  ```
217
44
 
218
- #### Dom/css
219
-
220
- A collection of functions to get or set css styles.
45
+ ## Examples
221
46
 
222
- - `get(node: HTMLElement, name?: string): any`
223
- - `set(node: HTMLElement, name?: string, value: any) | set(node, object)`
224
- - `getOuterWidth(el: HTMLElement): number`
225
- - `getOuterHeight(el: HTMLElement): number`
226
- - `getDocSize(): { width: number, height: number }`
227
- - `getClientSize(): { width: number, height: number }`
228
- - `getScroll(): { scrollLeft: number, scrollTop: number }`
229
- - `getOffset(node: HTMLElement): { left: number, top: number }`
47
+ Run the local dumi site:
230
48
 
231
- ```jsx|pure
232
- import css from 'rc-util/lib/Dom/css';
49
+ ```bash
50
+ npm install
51
+ npm start
233
52
  ```
234
53
 
235
- #### Dom/focus
54
+ Then open `http://localhost:8000`.
236
55
 
237
- A collection of functions to operate focus status of DOM node.
238
-
239
- - `saveLastFocusNode(): void`
240
- - `clearLastFocusNode(): void`
241
- - `backLastFocusNode(): void`
242
- - `getFocusNodeList(node: HTMLElement): HTMLElement[]` get a list of focusable nodes from the subtree of node.
243
- - `limitTabRange(node: HTMLElement, e: Event): void`
56
+ ## API
244
57
 
245
- ```jsx|pure
246
- import focus from 'rc-util/lib/Dom/focus';
247
- ```
58
+ The package exposes small, focused helpers used across rc-component and Ant Design packages. Import the public entry when possible, and use subpath imports for specialized DOM, React, or test helpers.
248
59
 
249
- #### Dom/support
60
+ | Area | Examples |
61
+ | --------------- | ---------------------------------------------------------------------------------- |
62
+ | React hooks | `useEvent`, `useLayoutEffect`, `useMergedState`, `useState` helpers |
63
+ | React utilities | `Children/toArray`, `composeRef`, `pickAttrs`, `Portal` |
64
+ | DOM utilities | `Dom/canUseDom`, `Dom/contains`, `Dom/dynamicCSS`, `Dom/focus`, `getScrollBarSize` |
65
+ | Async helpers | `raf`, `raf.cancel` |
66
+ | Warnings | `warning`, `noteOnce`, `resetWarned` |
67
+ | Tests | `test/domHook` for DOM prototype spies |
250
68
 
251
- > { animation: boolean | Object, transition: boolean | Object }
69
+ Examples in `docs/examples` cover the commonly used subpath helpers.
252
70
 
253
- A flag to tell whether current environment supports `animationend` or `transitionend`.
71
+ ## Development
254
72
 
255
- ```jsx|pure
256
- import support from 'rc-util/lib/Dom/support';
73
+ ```bash
74
+ npm install
75
+ npm start
76
+ npm test
77
+ npm run build
257
78
  ```
258
79
 
259
- ### KeyCode
80
+ The dumi site runs at `http://localhost:8000` by default.
260
81
 
261
- > Enum
82
+ ## Release
262
83
 
263
- Enum of KeyCode, please check the [definition](https://github.com/react-component/util/blob/master/src/KeyCode.ts) of it.
264
-
265
- ```jsx|pure
266
- import KeyCode from 'rc-util/lib/KeyCode';
84
+ ```bash
85
+ npm run prepublishOnly
267
86
  ```
268
87
 
269
- #### KeyCode.isTextModifyingKeyEvent
270
-
271
- > (e: Event): boolean
272
-
273
- Whether text and modified key is entered at the same time.
274
-
275
- #### KeyCode.isCharacterKey
276
-
277
- > (keyCode: KeyCode): boolean
278
-
279
- Whether character is entered.
280
-
281
- ### ScrollLocker
282
-
283
- > ScrollLocker<{lock: (options: {container: HTMLElement}) => void, unLock: () => void}>
284
-
285
- improve shake when page scroll bar hidden.
286
-
287
- `ScrollLocker` change body style, and add a class `ant-scrolling-effect` when called, so if you page look abnormal, please check this;
288
-
289
- ```js
290
- import ScrollLocker from 'rc-util/lib/Dom/scrollLocker';
291
-
292
- const scrollLocker = new ScrollLocker();
293
-
294
- // lock
295
- scrollLocker.lock()
296
-
297
- // unLock
298
- scrollLocker.unLock()
299
- ```
88
+ The release flow is handled by `@rc-component/np` through the `rc-np` command after the package build.
300
89
 
301
90
  ## License
302
91
 
303
- [MIT](/LICENSE)
92
+ @rc-component/util is released under the [MIT](./LICENSE) license.
@@ -0,0 +1,92 @@
1
+ <div align="center">
2
+ <h1>@rc-component/util</h1>
3
+ <p><sub><a href="https://ant.design"><img alt="Ant Design" height="14" src="https://gw.alipayobjects.com/zos/rmsportal/KDpgvguMpGfqaHPjicRK.svg" style="vertical-align: -0.125em;" /></a> Ant Design 生态的一部分。</sub></p>
4
+ <p>🛠️ rc-component 共享工具集合,包含 DOM、React 和测试辅助能力。</p>
5
+
6
+ <p>
7
+ <a href="https://npmjs.org/package/@rc-component/util"><img alt="NPM version" src="https://img.shields.io/npm/v/@rc-component/util.svg?style=flat-square"></a>
8
+ <a href="https://npmjs.org/package/@rc-component/util"><img alt="npm downloads" src="https://img.shields.io/npm/dm/@rc-component/util.svg?style=flat-square"></a>
9
+ <a href="https://github.com/react-component/util/actions/workflows/react-component-ci.yml"><img alt="build status" src="https://github.com/react-component/util/actions/workflows/react-component-ci.yml/badge.svg"></a>
10
+ <a href="https://app.codecov.io/gh/react-component/util"><img alt="Codecov" src="https://img.shields.io/codecov/c/github/react-component/util/master.svg?style=flat-square"></a>
11
+ <a href="https://bundlephobia.com/package/@rc-component/util"><img alt="bundle size" src="https://img.shields.io/bundlephobia/minzip/@rc-component/util?style=flat-square"></a>
12
+ <a href="https://github.com/umijs/dumi"><img alt="dumi" src="https://img.shields.io/badge/docs%20by-dumi-blue?style=flat-square"></a>
13
+ </p>
14
+ </div>
15
+
16
+ <p align="center"><a href="./README.md">English</a> | 简体中文</p>
17
+
18
+ ## 特性
19
+
20
+ - 面向 React 构建,并由 rc-component 团队维护。
21
+ - 被 Ant Design 使用和其他 React 组件库使用。
22
+ - 提供 TypeScript 类型声明,同时输出 ES module 和 CommonJS 产物。
23
+ - 示例、测试和预览构建与包源码保持一致。
24
+
25
+ > 该包历史上曾以 `rc-util` 发布。新代码推荐使用带 scope 的包名。
26
+
27
+ ## 安装
28
+
29
+ ```bash
30
+ npm install @rc-component/util
31
+ ```
32
+
33
+ ## 使用
34
+
35
+ ```tsx | pure
36
+ import {
37
+ Portal,
38
+ raf,
39
+ useEvent,
40
+ useLayoutEffect,
41
+ warning,
42
+ } from '@rc-component/util';
43
+ ```
44
+
45
+ ## 示例
46
+
47
+ 运行本地 dumi 站点:
48
+
49
+ ```bash
50
+ npm install
51
+ npm start
52
+ ```
53
+
54
+ 然后打开 `http://localhost:8000`。
55
+
56
+ ## API
57
+
58
+ 该包提供在 rc-component 和 Ant Design 包中复用的小型聚焦工具。优先导入公开入口;针对 DOM、React 或测试辅助能力,可使用子路径导入。
59
+
60
+ | 范围 | 示例 |
61
+ | ------------ | ---------------------------------------------------------------------------------- |
62
+ | React hooks | `useEvent`, `useLayoutEffect`, `useMergedState`, `useState` 辅助方法 |
63
+ | React 工具 | `Children/toArray`, `composeRef`, `pickAttrs`, `Portal` |
64
+ | DOM 工具 | `Dom/canUseDom`, `Dom/contains`, `Dom/dynamicCSS`, `Dom/focus`, `getScrollBarSize` |
65
+ | 异步辅助方法 | `raf`, `raf.cancel` |
66
+ | 警告工具 | `warning`, `noteOnce`, `resetWarned` |
67
+ | 测试工具 | `test/domHook` 用于 DOM 原型 spy |
68
+
69
+ `docs/examples` 中的示例覆盖了常用的子路径辅助工具。
70
+
71
+ ## 本地开发
72
+
73
+ ```bash
74
+ npm install
75
+ npm start
76
+ npm test
77
+ npm run build
78
+ ```
79
+
80
+ dumi 站点默认运行在 `http://localhost:8000`。
81
+
82
+ ## 发布
83
+
84
+ ```bash
85
+ npm run prepublishOnly
86
+ ```
87
+
88
+ 包构建完成后,发布流程由 `@rc-component/np` 通过 `rc-np` 命令处理。
89
+
90
+ ## 许可证
91
+
92
+ @rc-component/util 基于 [MIT](./LICENSE) 许可证发布。
@@ -1,5 +1,7 @@
1
- export default function getScrollBarSize(fresh?: boolean): number;
2
- export declare function getTargetScrollBarSize(target: HTMLElement): {
1
+ type ScrollBarSize = {
3
2
  width: number;
4
3
  height: number;
5
4
  };
5
+ export default function getScrollBarSize(fresh?: boolean): number;
6
+ export declare function getTargetScrollBarSize(target: HTMLElement): ScrollBarSize;
7
+ export {};
@@ -0,0 +1,16 @@
1
+ import * as React from 'react';
2
+ export type DelayConfig = {
3
+ frame: number;
4
+ ms?: never;
5
+ } | {
6
+ frame?: never;
7
+ ms: number;
8
+ };
9
+ export type SetDelayState<T> = (nextValue: React.SetStateAction<T>,
10
+ /** `true` updates immediately. `false` delays the update by one frame. */
11
+ immediatelyOrDelay?: boolean | DelayConfig) => void;
12
+ /**
13
+ * Similar to `useState`, but updates on the next frame by default.
14
+ * Pending updates are always replaced by the latest one.
15
+ */
16
+ export default function useDelayState<T>(defaultValue: T | (() => T)): [T, SetDelayState<T>];
@@ -0,0 +1,36 @@
1
+ import * as React from 'react';
2
+ import raf from "../raf";
3
+ import useEvent from "./useEvent";
4
+ /**
5
+ * Similar to `useState`, but updates on the next frame by default.
6
+ * Pending updates are always replaced by the latest one.
7
+ */
8
+ export default function useDelayState(defaultValue) {
9
+ const [value, setValue] = React.useState(defaultValue);
10
+ const delayRef = React.useRef(null);
11
+ const cancelPending = useEvent(() => {
12
+ if (delayRef.current) {
13
+ const [isRaf, delay] = delayRef.current;
14
+ if (isRaf) {
15
+ raf.cancel(delay);
16
+ } else {
17
+ clearTimeout(delay);
18
+ }
19
+ delayRef.current = null;
20
+ }
21
+ });
22
+ const setDelayValue = useEvent((nextValue, immediatelyOrDelay) => {
23
+ const delayConfig = immediatelyOrDelay || {
24
+ frame: 1
25
+ };
26
+ cancelPending();
27
+ if (delayConfig === true) {
28
+ setValue(nextValue);
29
+ } else if ('ms' in delayConfig) {
30
+ delayRef.current = [false, setTimeout(() => setValue(nextValue), delayConfig.ms)];
31
+ } else {
32
+ delayRef.current = [true, raf(() => setValue(nextValue), delayConfig.frame)];
33
+ }
34
+ });
35
+ return [value, setDelayValue];
36
+ }
package/es/index.d.ts CHANGED
@@ -1,6 +1,8 @@
1
1
  export { default as useEvent } from './hooks/useEvent';
2
2
  export { default as useMergedState } from './hooks/useMergedState';
3
3
  export { default as useControlledState } from './hooks/useControlledState';
4
+ export { default as useDelayState } from './hooks/useDelayState';
5
+ export type { DelayConfig, SetDelayState } from './hooks/useDelayState';
4
6
  export { default as useId, getId } from './hooks/useId';
5
7
  export { default as useLayoutEffect, useLayoutUpdateEffect, } from './hooks/useLayoutEffect';
6
8
  export { default as useMemo } from './hooks/useMemo';
package/es/index.js CHANGED
@@ -1,6 +1,7 @@
1
1
  export { default as useEvent } from "./hooks/useEvent";
2
2
  export { default as useMergedState } from "./hooks/useMergedState";
3
3
  export { default as useControlledState } from "./hooks/useControlledState";
4
+ export { default as useDelayState } from "./hooks/useDelayState";
4
5
  export { default as useId, getId } from "./hooks/useId";
5
6
  export { default as useLayoutEffect, useLayoutUpdateEffect } from "./hooks/useLayoutEffect";
6
7
  export { default as useMemo } from "./hooks/useMemo";
package/es/pickAttrs.js CHANGED
@@ -16,7 +16,12 @@ const eventsName = `onCopy onCut onPaste onCompositionEnd onCompositionStart onC
16
16
  onMouseEnter onMouseLeave onMouseMove onMouseOut onMouseOver onMouseUp onSelect onTouchCancel
17
17
  onTouchEnd onTouchMove onTouchStart onScroll onWheel onAbort onCanPlay onCanPlayThrough
18
18
  onDurationChange onEmptied onEncrypted onEnded onError onLoadedData onLoadedMetadata
19
- onLoadStart onPause onPlay onPlaying onProgress onRateChange onSeeked onSeeking onStalled onSuspend onTimeUpdate onVolumeChange onWaiting onLoad onError`;
19
+ onLoadStart onPause onPlay onPlaying onProgress onRateChange onSeeked onSeeking onStalled onSuspend onTimeUpdate onVolumeChange onWaiting onLoad
20
+ onPointerDown onPointerMove onPointerUp onPointerCancel onPointerEnter onPointerLeave onPointerOver onPointerOut onGotPointerCapture onLostPointerCapture
21
+ onAnimationStart onAnimationEnd onAnimationIteration
22
+ onTransitionEnd onTransitionRun onTransitionStart onTransitionCancel
23
+ onBeforeInput onReset onInvalid
24
+ onAuxClick onToggle onBeforeToggle onCancel onClose onResize onScrollEnd`;
20
25
  const propList = `${attributes} ${eventsName}`.split(/[\s\n]+/);
21
26
 
22
27
  /* eslint-enable max-len */
@@ -1,4 +1,3 @@
1
- /* eslint-disable @typescript-eslint/ban-types */
2
1
  /* eslint-disable no-param-reassign */
3
2
  const NO_EXIST = {
4
3
  __NOT_EXIST: true
@@ -1,5 +1,7 @@
1
- export default function getScrollBarSize(fresh?: boolean): number;
2
- export declare function getTargetScrollBarSize(target: HTMLElement): {
1
+ type ScrollBarSize = {
3
2
  width: number;
4
3
  height: number;
5
4
  };
5
+ export default function getScrollBarSize(fresh?: boolean): number;
6
+ export declare function getTargetScrollBarSize(target: HTMLElement): ScrollBarSize;
7
+ export {};
@@ -0,0 +1,16 @@
1
+ import * as React from 'react';
2
+ export type DelayConfig = {
3
+ frame: number;
4
+ ms?: never;
5
+ } | {
6
+ frame?: never;
7
+ ms: number;
8
+ };
9
+ export type SetDelayState<T> = (nextValue: React.SetStateAction<T>,
10
+ /** `true` updates immediately. `false` delays the update by one frame. */
11
+ immediatelyOrDelay?: boolean | DelayConfig) => void;
12
+ /**
13
+ * Similar to `useState`, but updates on the next frame by default.
14
+ * Pending updates are always replaced by the latest one.
15
+ */
16
+ export default function useDelayState<T>(defaultValue: T | (() => T)): [T, SetDelayState<T>];
@@ -0,0 +1,45 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = useDelayState;
7
+ var React = _interopRequireWildcard(require("react"));
8
+ var _raf = _interopRequireDefault(require("../raf"));
9
+ var _useEvent = _interopRequireDefault(require("./useEvent"));
10
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
11
+ 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); }
12
+ 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; }
13
+ /**
14
+ * Similar to `useState`, but updates on the next frame by default.
15
+ * Pending updates are always replaced by the latest one.
16
+ */
17
+ function useDelayState(defaultValue) {
18
+ const [value, setValue] = React.useState(defaultValue);
19
+ const delayRef = React.useRef(null);
20
+ const cancelPending = (0, _useEvent.default)(() => {
21
+ if (delayRef.current) {
22
+ const [isRaf, delay] = delayRef.current;
23
+ if (isRaf) {
24
+ _raf.default.cancel(delay);
25
+ } else {
26
+ clearTimeout(delay);
27
+ }
28
+ delayRef.current = null;
29
+ }
30
+ });
31
+ const setDelayValue = (0, _useEvent.default)((nextValue, immediatelyOrDelay) => {
32
+ const delayConfig = immediatelyOrDelay || {
33
+ frame: 1
34
+ };
35
+ cancelPending();
36
+ if (delayConfig === true) {
37
+ setValue(nextValue);
38
+ } else if ('ms' in delayConfig) {
39
+ delayRef.current = [false, setTimeout(() => setValue(nextValue), delayConfig.ms)];
40
+ } else {
41
+ delayRef.current = [true, (0, _raf.default)(() => setValue(nextValue), delayConfig.frame)];
42
+ }
43
+ });
44
+ return [value, setDelayValue];
45
+ }
package/lib/index.d.ts CHANGED
@@ -1,6 +1,8 @@
1
1
  export { default as useEvent } from './hooks/useEvent';
2
2
  export { default as useMergedState } from './hooks/useMergedState';
3
3
  export { default as useControlledState } from './hooks/useControlledState';
4
+ export { default as useDelayState } from './hooks/useDelayState';
5
+ export type { DelayConfig, SetDelayState } from './hooks/useDelayState';
4
6
  export { default as useId, getId } from './hooks/useId';
5
7
  export { default as useLayoutEffect, useLayoutUpdateEffect, } from './hooks/useLayoutEffect';
6
8
  export { default as useMemo } from './hooks/useMemo';
package/lib/index.js CHANGED
@@ -261,6 +261,12 @@ Object.defineProperty(exports, "useControlledState", {
261
261
  return _useControlledState.default;
262
262
  }
263
263
  });
264
+ Object.defineProperty(exports, "useDelayState", {
265
+ enumerable: true,
266
+ get: function () {
267
+ return _useDelayState.default;
268
+ }
269
+ });
264
270
  Object.defineProperty(exports, "useEvent", {
265
271
  enumerable: true,
266
272
  get: function () {
@@ -324,6 +330,7 @@ Object.defineProperty(exports, "warning", {
324
330
  var _useEvent = _interopRequireDefault(require("./hooks/useEvent"));
325
331
  var _useMergedState = _interopRequireDefault(require("./hooks/useMergedState"));
326
332
  var _useControlledState = _interopRequireDefault(require("./hooks/useControlledState"));
333
+ var _useDelayState = _interopRequireDefault(require("./hooks/useDelayState"));
327
334
  var _useId = _interopRequireWildcard(require("./hooks/useId"));
328
335
  var _useLayoutEffect = _interopRequireWildcard(require("./hooks/useLayoutEffect"));
329
336
  var _useMemo = _interopRequireDefault(require("./hooks/useMemo"));
package/lib/pickAttrs.js CHANGED
@@ -22,7 +22,12 @@ const eventsName = `onCopy onCut onPaste onCompositionEnd onCompositionStart onC
22
22
  onMouseEnter onMouseLeave onMouseMove onMouseOut onMouseOver onMouseUp onSelect onTouchCancel
23
23
  onTouchEnd onTouchMove onTouchStart onScroll onWheel onAbort onCanPlay onCanPlayThrough
24
24
  onDurationChange onEmptied onEncrypted onEnded onError onLoadedData onLoadedMetadata
25
- onLoadStart onPause onPlay onPlaying onProgress onRateChange onSeeked onSeeking onStalled onSuspend onTimeUpdate onVolumeChange onWaiting onLoad onError`;
25
+ onLoadStart onPause onPlay onPlaying onProgress onRateChange onSeeked onSeeking onStalled onSuspend onTimeUpdate onVolumeChange onWaiting onLoad
26
+ onPointerDown onPointerMove onPointerUp onPointerCancel onPointerEnter onPointerLeave onPointerOver onPointerOut onGotPointerCapture onLostPointerCapture
27
+ onAnimationStart onAnimationEnd onAnimationIteration
28
+ onTransitionEnd onTransitionRun onTransitionStart onTransitionCancel
29
+ onBeforeInput onReset onInvalid
30
+ onAuxClick onToggle onBeforeToggle onCancel onClose onResize onScrollEnd`;
26
31
  const propList = `${attributes} ${eventsName}`.split(/[\s\n]+/);
27
32
 
28
33
  /* eslint-enable max-len */
@@ -5,7 +5,6 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports.spyElementPrototype = spyElementPrototype;
7
7
  exports.spyElementPrototypes = spyElementPrototypes;
8
- /* eslint-disable @typescript-eslint/ban-types */
9
8
  /* eslint-disable no-param-reassign */
10
9
  const NO_EXIST = {
11
10
  __NOT_EXIST: true
package/package.json CHANGED
@@ -1,18 +1,18 @@
1
1
  {
2
2
  "name": "@rc-component/util",
3
- "version": "1.11.1",
4
- "description": "Common Utils For React Component",
3
+ "version": "1.12.0",
4
+ "description": "Shared React utilities for rc-component packages.",
5
5
  "keywords": [
6
6
  "react",
7
7
  "util"
8
8
  ],
9
- "homepage": "http://github.com/react-component/util",
9
+ "homepage": "https://react-component.github.io/util",
10
10
  "bugs": {
11
- "url": "http://github.com/react-component/util/issues"
11
+ "url": "https://github.com/react-component/util/issues"
12
12
  },
13
13
  "repository": {
14
14
  "type": "git",
15
- "url": "git@github.com:react-component/util.git"
15
+ "url": "https://github.com/react-component/util.git"
16
16
  },
17
17
  "license": "MIT",
18
18
  "main": "./lib/index",
@@ -22,56 +22,71 @@
22
22
  "es"
23
23
  ],
24
24
  "scripts": {
25
- "build": "dumi build",
25
+ "build": "npm run compile && npm run docs:build",
26
26
  "compile": "father build",
27
- "coverage": "npm test -- --coverage",
28
- "lint": "eslint src/ --ext .tsx,.ts & eslint tests/ --ext .tsx,.ts",
29
- "prepare": "husky install",
27
+ "coverage": "rc-test --coverage",
28
+ "docs:build": "dumi build",
29
+ "docs:deploy": "gh-pages -d docs-dist",
30
+ "deploy": "npm run gh-pages",
31
+ "gh-pages": "npm run compile && cross-env GH_PAGES=1 npm run docs:build && npm run docs:deploy",
32
+ "lint": "eslint src/ tests/ docs/examples/ --ext .tsx,.ts,.jsx,.js",
30
33
  "prepublishOnly": "npm run compile && rc-np",
34
+ "prettier": "prettier --write --ignore-unknown .",
31
35
  "start": "dumi dev",
32
- "test": "rc-test"
36
+ "test": "rc-test",
37
+ "tsc": "tsc --noEmit",
38
+ "prepare": "husky"
33
39
  },
34
40
  "lint-staged": {
35
- "**/*.{js,jsx,tsx,ts,md,json}": [
36
- "prettier --write",
37
- "git add"
38
- ]
41
+ "*": "prettier --write --ignore-unknown"
39
42
  },
40
43
  "dependencies": {
41
44
  "is-mobile": "^5.0.0",
42
- "react-is": "^18.2.0"
45
+ "react-is": "^19.2.7"
43
46
  },
44
47
  "devDependencies": {
48
+ "@eslint/js": "^10.0.1",
49
+ "@eslint/compat": "^2.1.0",
45
50
  "@rc-component/father-plugin": "^2.2.0",
46
- "@rc-component/np": "^1.0.3",
47
- "@testing-library/react": "^16.0.0",
51
+ "@rc-component/np": "^1.0.4",
52
+ "@testing-library/dom": "^10.4.1",
53
+ "@testing-library/jest-dom": "^6.9.1",
54
+ "@testing-library/react": "^16.3.2",
48
55
  "@types/jest": "^30.0.0",
49
- "@types/node": "^25.0.3",
50
- "@types/react": "^19.2.7",
51
- "@types/react-dom": "^19.2.2",
52
- "@types/react-is": "^19.0.0",
53
- "@types/responselike": "^1.0.0",
54
- "@types/warning": "^3.0.0",
55
- "@umijs/fabric": "^3.0.0",
56
+ "@types/node": "^26.0.1",
57
+ "@types/react": "^19.2.17",
58
+ "@types/react-dom": "^19.2.3",
59
+ "@types/react-is": "^19.2.0",
60
+ "@types/responselike": "^1.0.3",
61
+ "@types/warning": "^3.0.4",
56
62
  "cross-env": "^10.1.0",
57
- "dumi": "^2.1.3",
58
- "eslint": "^8.54.0",
59
- "eslint-plugin-jest": "^29.0.1",
60
- "eslint-plugin-unicorn": "^56.0.1",
61
- "father": "^4.1.3",
62
- "glob": "^13.0.0",
63
- "husky": "^9.1.6",
64
- "lint-staged": "^17.0.3",
65
- "prettier": "^3.3.2",
66
- "rc-test": "^7.0.14",
67
- "react": "^18.0.0",
63
+ "dumi": "^2.4.38",
64
+ "eslint": "^10.6.0",
65
+ "eslint-config-prettier": "^10.1.8",
66
+ "eslint-plugin-jest": "^29.15.4",
67
+ "eslint-plugin-react": "^7.37.5",
68
+ "eslint-plugin-react-hooks": "^7.1.1",
69
+ "father": "^4.6.24",
70
+ "gh-pages": "^6.3.0",
71
+ "glob": "^13.0.6",
72
+ "globals": "^17.7.0",
73
+ "husky": "^9.1.7",
74
+ "lint-staged": "^17.0.8",
75
+ "prettier": "^3.9.4",
76
+ "rc-test": "^7.1.3",
77
+ "react": "^19.2.7",
68
78
  "react-19": "npm:react@19.0.0",
69
- "react-dom": "^18.0.0",
79
+ "react-dom": "^19.2.7",
70
80
  "react-dom-19": "npm:react-dom@19.0.0",
71
- "typescript": "^5.3.2"
81
+ "typescript": "^6.0.3",
82
+ "typescript-eslint": "^8.62.1"
72
83
  },
73
84
  "peerDependencies": {
74
85
  "react": ">=18.0.0",
75
86
  "react-dom": ">=18.0.0"
76
- }
87
+ },
88
+ "publishConfig": {
89
+ "access": "public"
90
+ },
91
+ "types": "./es/index.d.ts"
77
92
  }