1
This commit is contained in:
+21
@@ -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
@@ -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
|
||||
|
||||
[](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 | - |
|
||||
Generated
Vendored
+4
@@ -0,0 +1,4 @@
|
||||
import React from 'react';
|
||||
import type { MutationObserverProps } from './interface';
|
||||
declare const MutateObserver: React.FC<MutationObserverProps>;
|
||||
export default MutateObserver;
|
||||
+39
@@ -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;
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
import MutateObserver from './MutateObserver';
|
||||
import useMutateObserver from './useMutateObserver';
|
||||
export { useMutateObserver };
|
||||
export default MutateObserver;
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
import MutateObserver from "./MutateObserver";
|
||||
import useMutateObserver from "./useMutateObserver";
|
||||
export { useMutateObserver };
|
||||
export default MutateObserver;
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
/// <reference types="react" />
|
||||
export interface MutationObserverProps {
|
||||
children: React.ReactNode;
|
||||
options?: MutationObserverInit;
|
||||
onMutate?: (mutations: MutationRecord[], observer: MutationObserver) => void;
|
||||
}
|
||||
+1
@@ -0,0 +1 @@
|
||||
export {};
|
||||
Generated
Vendored
+2
@@ -0,0 +1,2 @@
|
||||
declare const useMutateObserver: (nodeOrList: HTMLElement | HTMLElement[] | SVGElement | SVGElement[], callback: MutationCallback, options?: MutationObserverInit) => void;
|
||||
export default useMutateObserver;
|
||||
Generated
Vendored
+27
@@ -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;
|
||||
Generated
Vendored
+4
@@ -0,0 +1,4 @@
|
||||
import React from 'react';
|
||||
import type { MutationObserverProps } from './interface';
|
||||
declare const MutateObserver: React.FC<MutationObserverProps>;
|
||||
export default MutateObserver;
|
||||
+46
@@ -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;
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
import MutateObserver from './MutateObserver';
|
||||
import useMutateObserver from './useMutateObserver';
|
||||
export { useMutateObserver };
|
||||
export default MutateObserver;
|
||||
+16
@@ -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;
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
/// <reference types="react" />
|
||||
export interface MutationObserverProps {
|
||||
children: React.ReactNode;
|
||||
options?: MutationObserverInit;
|
||||
onMutate?: (mutations: MutationRecord[], observer: MutationObserver) => void;
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
Generated
Vendored
+2
@@ -0,0 +1,2 @@
|
||||
declare const useMutateObserver: (nodeOrList: HTMLElement | HTMLElement[] | SVGElement | SVGElement[], callback: MutationCallback, options?: MutationObserverInit) => void;
|
||||
export default useMutateObserver;
|
||||
Generated
Vendored
+34
@@ -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;
|
||||
+78
@@ -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"
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user