This commit is contained in:
2026-05-25 17:08:18 +08:00
parent df501f6151
commit f1259b71b5
9178 changed files with 1626125 additions and 0 deletions
+21
View File
@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2019-present react-component
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+73
View File
@@ -0,0 +1,73 @@
# @rc-component/mutate-observer
MutateObserver for React.
[![NPM version][npm-image]][npm-url]
[![npm download][download-image]][download-url]
[![build status][github-actions-image]][github-actions-url]
[![Codecov][codecov-image]][codecov-url]
[![bundle size][bundlephobia-image]][bundlephobia-url]
[![dumi][dumi-image]][dumi-url]
[npm-image]: https://img.shields.io/npm/v/@rc-component/mutate-observer.svg?style=flat-square
[npm-url]: http://npmjs.org/package/@rc-component/mutate-observer
[github-actions-image]: https://github.com/react-component/mutate-observer/actions/workflows/main.yml/badge.svg
[github-actions-url]: https://github.com/react-component/mutate-observer/actions/workflows/main.yml
[codecov-image]: https://img.shields.io/codecov/c/github/react-component/mutate-observer/master.svg?style=flat-square
[codecov-url]: https://app.codecov.io/gh/react-component/mutate-observer
[david-url]: https://david-dm.org/react-component/mutate-observer
[david-image]: https://david-dm.org/react-component/mutate-observer/status.svg?style=flat-square
[david-dev-url]: https://david-dm.org/react-component/mutate-observer?type=dev
[david-dev-image]: https://david-dm.org/react-component/mutate-observer/dev-status.svg?style=flat-square
[download-image]: https://img.shields.io/npm/dm/@rc-component/mutate-observer.svg?style=flat-square
[download-url]: https://npmjs.org/package/@rc-component/mutate-observer
[bundlephobia-url]: https://bundlephobia.com/package/@rc-component/mutate-observer
[bundlephobia-image]: https://badgen.net/bundlephobia/minzip/@rc-component/mutate-observer
[dumi-url]: https://github.com/umijs/dumi
[dumi-image]: https://img.shields.io/badge/docs%20by-dumi-blue?style=flat-square
## Development
```bash
npm install
npm run start
open http://localhost:8000
```
## Install
[![@rc-component/mutate-observer](https://nodei.co/npm/@rc-component/mutate-observer.png)](https://www.npmjs.com/package/@rc-component/mutate-observer)
## Usage
```tsx | pure
import React from 'react';
import MutateObserver from 'rc-component/mutate-observer';
const onMutate = (mutations: MutationRecord[], observer: MutationObserver) => {
console.log(mutation);
console.log(observer);
};
const Demo: React.FC = () => {
return (
<MutateObserver onMutate={onMutate}>
<div>test</div>
</MutateObserver>
);
};
export default Demo;
```
## 🔥 API
We use typescript to create the Type definition. You can view directly in IDE. But you can still check the type definition [here](https://github.com/react-component/mutate-observer/blob/master/src/interface.ts).
### mutate-observer
| Prop | Description | Type | Default |
| -------- | ---------------------------------------------------------------------------------------------------------------- | -------------------- | ------- |
| onMutate | A function which will be called on each DOM change that qualifies given the observed node or subtree and options | MutationCallback | - |
| options | An object providing options that describe which DOM mutations should be reported to mutationObserver's callback | MutationObserverInit | - |
@@ -0,0 +1,4 @@
import React from 'react';
import type { MutationObserverProps } from './interface';
declare const MutateObserver: React.FC<MutationObserverProps>;
export default MutateObserver;
@@ -0,0 +1,39 @@
import { getDOM } from "@rc-component/util/es/Dom/findDOMNode";
import useEvent from "@rc-component/util/es/hooks/useEvent";
import useLayoutEffect from "@rc-component/util/es/hooks/useLayoutEffect";
import { getNodeRef, supportNodeRef, useComposeRef } from "@rc-component/util/es/ref";
import React from 'react';
import useMutateObserver from "./useMutateObserver";
const MutateObserver = props => {
const {
children,
options,
onMutate = () => {}
} = props;
const callback = useEvent(onMutate);
const elementRef = React.useRef(null);
const canRef = supportNodeRef(children);
const mergedRef = useComposeRef(elementRef, getNodeRef(children));
const [target, setTarget] = React.useState(null);
useMutateObserver(target, callback, options);
// =========================== Effect ===========================
useLayoutEffect(() => {
// Set target based on the refs
if (canRef && elementRef.current) {
setTarget(getDOM(elementRef.current));
}
}, [canRef]);
// =========================== Render ===========================
if (!children) {
if (process.env.NODE_ENV !== 'production') {
console.error('MutationObserver need children props');
}
return null;
}
return canRef ? /*#__PURE__*/React.cloneElement(children, {
ref: mergedRef
}) : children;
};
export default MutateObserver;
@@ -0,0 +1,4 @@
import MutateObserver from './MutateObserver';
import useMutateObserver from './useMutateObserver';
export { useMutateObserver };
export default MutateObserver;
@@ -0,0 +1,4 @@
import MutateObserver from "./MutateObserver";
import useMutateObserver from "./useMutateObserver";
export { useMutateObserver };
export default MutateObserver;
@@ -0,0 +1,6 @@
/// <reference types="react" />
export interface MutationObserverProps {
children: React.ReactNode;
options?: MutationObserverInit;
onMutate?: (mutations: MutationRecord[], observer: MutationObserver) => void;
}
@@ -0,0 +1 @@
export {};
@@ -0,0 +1,2 @@
declare const useMutateObserver: (nodeOrList: HTMLElement | HTMLElement[] | SVGElement | SVGElement[], callback: MutationCallback, options?: MutationObserverInit) => void;
export default useMutateObserver;
@@ -0,0 +1,27 @@
import canUseDom from "@rc-component/util/es/Dom/canUseDom";
import React from 'react';
const defaultOptions = {
subtree: true,
childList: true,
attributeFilter: ['style', 'class']
};
const useMutateObserver = (nodeOrList, callback, options = defaultOptions) => {
React.useEffect(() => {
if (!canUseDom() || !nodeOrList) {
return;
}
let instance;
const nodeList = Array.isArray(nodeOrList) ? nodeOrList : [nodeOrList];
if ('MutationObserver' in window) {
instance = new MutationObserver(callback);
nodeList.forEach(element => {
instance.observe(element, options);
});
}
return () => {
instance?.takeRecords();
instance?.disconnect();
};
}, [options, nodeOrList]);
};
export default useMutateObserver;
@@ -0,0 +1,4 @@
import React from 'react';
import type { MutationObserverProps } from './interface';
declare const MutateObserver: React.FC<MutationObserverProps>;
export default MutateObserver;
@@ -0,0 +1,46 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _findDOMNode = require("@rc-component/util/lib/Dom/findDOMNode");
var _useEvent = _interopRequireDefault(require("@rc-component/util/lib/hooks/useEvent"));
var _useLayoutEffect = _interopRequireDefault(require("@rc-component/util/lib/hooks/useLayoutEffect"));
var _ref = require("@rc-component/util/lib/ref");
var _react = _interopRequireDefault(require("react"));
var _useMutateObserver = _interopRequireDefault(require("./useMutateObserver"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
const MutateObserver = props => {
const {
children,
options,
onMutate = () => {}
} = props;
const callback = (0, _useEvent.default)(onMutate);
const elementRef = _react.default.useRef(null);
const canRef = (0, _ref.supportNodeRef)(children);
const mergedRef = (0, _ref.useComposeRef)(elementRef, (0, _ref.getNodeRef)(children));
const [target, setTarget] = _react.default.useState(null);
(0, _useMutateObserver.default)(target, callback, options);
// =========================== Effect ===========================
(0, _useLayoutEffect.default)(() => {
// Set target based on the refs
if (canRef && elementRef.current) {
setTarget((0, _findDOMNode.getDOM)(elementRef.current));
}
}, [canRef]);
// =========================== Render ===========================
if (!children) {
if (process.env.NODE_ENV !== 'production') {
console.error('MutationObserver need children props');
}
return null;
}
return canRef ? /*#__PURE__*/_react.default.cloneElement(children, {
ref: mergedRef
}) : children;
};
var _default = exports.default = MutateObserver;
@@ -0,0 +1,4 @@
import MutateObserver from './MutateObserver';
import useMutateObserver from './useMutateObserver';
export { useMutateObserver };
export default MutateObserver;
@@ -0,0 +1,16 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
Object.defineProperty(exports, "useMutateObserver", {
enumerable: true,
get: function () {
return _useMutateObserver.default;
}
});
var _MutateObserver = _interopRequireDefault(require("./MutateObserver"));
var _useMutateObserver = _interopRequireDefault(require("./useMutateObserver"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
var _default = exports.default = _MutateObserver.default;
@@ -0,0 +1,6 @@
/// <reference types="react" />
export interface MutationObserverProps {
children: React.ReactNode;
options?: MutationObserverInit;
onMutate?: (mutations: MutationRecord[], observer: MutationObserver) => void;
}
@@ -0,0 +1,5 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
@@ -0,0 +1,2 @@
declare const useMutateObserver: (nodeOrList: HTMLElement | HTMLElement[] | SVGElement | SVGElement[], callback: MutationCallback, options?: MutationObserverInit) => void;
export default useMutateObserver;
@@ -0,0 +1,34 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _canUseDom = _interopRequireDefault(require("@rc-component/util/lib/Dom/canUseDom"));
var _react = _interopRequireDefault(require("react"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
const defaultOptions = {
subtree: true,
childList: true,
attributeFilter: ['style', 'class']
};
const useMutateObserver = (nodeOrList, callback, options = defaultOptions) => {
_react.default.useEffect(() => {
if (!(0, _canUseDom.default)() || !nodeOrList) {
return;
}
let instance;
const nodeList = Array.isArray(nodeOrList) ? nodeOrList : [nodeOrList];
if ('MutationObserver' in window) {
instance = new MutationObserver(callback);
nodeList.forEach(element => {
instance.observe(element, options);
});
}
return () => {
instance?.takeRecords();
instance?.disconnect();
};
}, [options, nodeOrList]);
};
var _default = exports.default = useMutateObserver;
@@ -0,0 +1,78 @@
{
"name": "@rc-component/mutate-observer",
"version": "2.0.1",
"description": "React MutateObserver Component",
"keywords": [
"react",
"react-component",
"mutate-observer"
],
"homepage": "https://github.com/react-component/mutate-observer",
"bugs": {
"url": "https://github.com/react-component/mutate-observer/issues"
},
"repository": {
"type": "git",
"url": "https://github.com/react-component/mutate-observer.git"
},
"license": "MIT",
"author": "574980606@qq.com",
"main": "./lib/index",
"module": "./es/index",
"typings": "es/index.d.ts",
"files": [
"lib",
"es",
"dist"
],
"scripts": {
"compile": "father build",
"deploy": "npm run docs:build && npm run docs:deploy",
"docs:build": "dumi build",
"docs:deploy": "gh-pages -d docs-dist",
"lint": "eslint src/ --ext .tsx,.ts",
"lint:tsc": "tsc -p tsconfig.json --noEmit",
"now-build": "npm run docs:build",
"prepare": "dumi setup",
"prepublishOnly": "npm run compile && rc-np",
"prettier": "prettier --write \"**/*.{js,jsx,tsx,ts,less,md,json}\"",
"start": "dumi dev",
"test": "umi-test",
"test:coverage": "npm run test --coverage",
"watch": "father dev"
},
"dependencies": {
"@rc-component/util": "^1.2.0"
},
"devDependencies": {
"@rc-component/father-plugin": "^2.0.2",
"@rc-component/np": "^1.0.3",
"@testing-library/jest-dom": "^5.16.4",
"@testing-library/react": "^13.0.0",
"@types/jest": "^26.0.20",
"@types/node": "^22.10.7",
"@types/react": "^19.0.7",
"@types/react-dom": "^19.0.3",
"@umijs/fabric": "^3.0.0",
"cheerio": "1.0.0-rc.12",
"dumi": "^2.0.0",
"eslint": "^8.54.0",
"eslint-plugin-jest": "^27.6.0",
"eslint-plugin-unicorn": "^49.0.0",
"father": "^4.0.0",
"gh-pages": "^3.1.0",
"glob": "^10.0.0",
"prettier": "^2.1.2",
"react": "^18.0.0",
"react-dom": "^18.0.0",
"typescript": "^5.0.0",
"umi-test": "^1.9.7"
},
"peerDependencies": {
"react": ">=16.9.0",
"react-dom": ">=16.9.0"
},
"engines": {
"node": ">=8.x"
}
}