fix: 修复关闭SSH终端标签页时会话状态未更新的问题

This commit is contained in:
2026-04-18 02:35:38 +08:00
commit 6e2e2f9387
43467 changed files with 5489040 additions and 0 deletions
+22
View File
@@ -0,0 +1,22 @@
language: node_js
os:
- linux
cache:
yarn: true
directories:
- ~/.npm
notifications:
email: false
node_js:
- '8'
script:
- npm run test
- npm run build
matrix:
allow_failures: []
fast_finish: true
after_success:
- npm run semantic-release
branches:
except:
- /^v\d+\.\d+\.\d+$/
+24
View File
@@ -0,0 +1,24 @@
This is free and unencumbered software released into the public domain.
Anyone is free to copy, modify, publish, use, compile, sell, or
distribute this software, either in source code form or as a compiled
binary, for any purpose, commercial or non-commercial, and by any
means.
In jurisdictions that recognize copyright laws, the author or authors
of this software dedicate any and all copyright interest in the
software to the public domain. We make this dedication for the benefit
of the public at large and to the detriment of our heirs and
successors. We intend this dedication to be an overt act of
relinquishment in perpetuity of all present and future rights to this
software under copyright law.
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 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.
For more information, please refer to <https://unlicense.org>
+169
View File
@@ -0,0 +1,169 @@
# react-universal-interface
Easily create a component which is render-prop, Function-as-a-child and component-prop.
```js
import {render} from 'react-universal-interface';
class MyData extends React.Component {
render () {
return render(this.props, this.state);
}
}
```
Now you can use it:
```jsx
<MyData render={(state) =>
<MyChild {...state} />
} />
<MyData>{(state) =>
<MyChild {...state} />
}</MyData>
<MyData comp={MyChild} />
<MyData component={MyChild} />
```
---
[![][npm-badge]][npm-url] [![][travis-badge]][travis-url] [![React Universal Interface](https://img.shields.io/badge/React-Universal%20Interface-green.svg)](https://github.com/streamich/react-universal-interface)
Use this badge if you support universal interface:
<div align="center">
<a href="https://github.com/streamich/react-universal-interface">
<img src="https://img.shields.io/badge/React-Universal%20Interface-green.svg" />
</a>
</div>
```
[![React Universal Interface](https://img.shields.io/badge/React-Universal%20Interface-green.svg)](https://github.com/streamich/react-universal-interface)
```
---
Given a `<MyData>` component, it is said to follow **universal component interface** if, and only if, it supports
all the below usage patterns:
```jsx
// Function as a Child Component (FaCC)
<MyData>{
(data) => <Child {...data} />
}</MyData>
// Render prop
<MyData render={
(data) => <Child {...data} />
} />
// Component prop
<MyData component={Child} />
<MyData comp={Child} />
// Prop injection
<MyData>
<Child />
</MyData>
// Higher Order Component (HOC)
const ChildWithData = withData(Child);
// Decorator
@withData
class ChildWithData extends {
render () {
return <Child {...this.props.data} />;
}
}
```
This library allows you to create universal interface components using these two functions:
- `render(props, data)`
- `createEnhancer(Comp, propName)`
First, in your render method use `render()`:
```js
class MyData extends Component {
render () {
return render(this.props, data);
}
}
```
Second, create enhancer out of your component:
```js
const withData = createEnhancer(MyData, 'data');
```
Done!
## Installation
<pre>
npm i <a href="https://www.npmjs.com/package/react-universal-interface">react-universal-interface</a> --save
</pre>
## Usage
```js
import {render, createEnhancer} from 'react-universal-interface';
```
## Reference
### `render(props, data)`
- `props` &mdash; props of your component.
- `data` &mdash; data you want to provide to your users, usually this will be `this.state`.
### `createEnhancer(Facc, propName)`
- `Facc` &mdash; FaCC component to use when creating enhancer.
- `propName` &mdash; prop name to use when injecting FaCC data into a component.
Returns a component enhancer `enhancer(Comp, propName, faccProps)` that receives three arguments.
- `Comp` &mdash; required, component to be enhanced.
- `propName` &mdash; optional, string, name of the injected prop.
- `faccProps` &mdash; optional, props to provide to the FaCC component.
## TypeScript
TypeScript users can add typings to their render-prop components.
```ts
import {UniversalProps} from 'react-universal-interface';
interface Props extends UniversalProps<State> {
}
interface State {
}
class MyData extends React.Component<Props, State> {
}
```
## License
[Unlicense](./LICENSE) &mdash; public domain.
[npm-url]: https://www.npmjs.com/package/react-universal-interface
[npm-badge]: https://img.shields.io/npm/v/react-universal-interface.svg
[travis-url]: https://travis-ci.org/streamich/react-universal-interface
[travis-badge]: https://travis-ci.org/streamich/react-universal-interface.svg?branch=master
@@ -0,0 +1,2 @@
declare const addClassDecoratorSupport: (Comp: any) => any;
export default addClassDecoratorSupport;
@@ -0,0 +1,10 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var tslib_1 = require("tslib");
var wrapInStatefulComponent_1 = tslib_1.__importDefault(require("./wrapInStatefulComponent"));
var addClassDecoratorSupport = function (Comp) {
var isSFC = !Comp.prototype;
return !isSFC ? Comp : wrapInStatefulComponent_1.default(Comp);
};
exports.default = addClassDecoratorSupport;
//# sourceMappingURL=addClassDecoratorSupport.js.map
@@ -0,0 +1 @@
{"version":3,"file":"addClassDecoratorSupport.js","sourceRoot":"","sources":["../src/addClassDecoratorSupport.ts"],"names":[],"mappings":";;;AAAA,8FAAgE;AAEhE,IAAM,wBAAwB,GAAG,UAAC,IAAI;IAClC,IAAM,KAAK,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC;IAC9B,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,iCAAuB,CAAC,IAAI,CAAC,CAAC;AACzD,CAAC,CAAC;AAEF,kBAAe,wBAAwB,CAAC"}
+4
View File
@@ -0,0 +1,4 @@
import * as React from 'react';
export declare const divWrapper: (Comp: any, propName: any, props: any, state: any) => any;
declare const createEnhancer: (Facc: any, prop?: string, wrapper?: (Comp: any, propName: any, props: any, state: any) => React.CElement<any, React.Component<any, any, any>>) => (Comp: any, propName?: any, faccProps?: object) => any;
export default createEnhancer;
+35
View File
@@ -0,0 +1,35 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.divWrapper = void 0;
var tslib_1 = require("tslib");
var React = tslib_1.__importStar(require("react"));
var addClassDecoratorSupport_1 = tslib_1.__importDefault(require("./addClassDecoratorSupport"));
var h = React.createElement;
var noWrap = function (Comp, propName, props, state) {
var _a;
return h(Comp, propName ? tslib_1.__assign((_a = {}, _a[propName] = state, _a), props) : tslib_1.__assign(tslib_1.__assign({}, state), props));
};
exports.divWrapper = function (Comp, propName, props, state) {
return h('div', null, noWrap(Comp, propName, props, state));
};
var createEnhancer = function (Facc, prop, wrapper) {
if (wrapper === void 0) { wrapper = noWrap; }
var enhancer = function (Comp, propName, faccProps) {
if (propName === void 0) { propName = prop; }
if (faccProps === void 0) { faccProps = null; }
var isClassDecoratorMethodCall = typeof Comp === 'string';
if (isClassDecoratorMethodCall) {
return function (Klass) { return enhancer(Klass, Comp || prop, propName); };
}
var Enhanced = function (props) {
return h(Facc, faccProps, function (state) { return wrapper(Comp, propName, props, state); });
};
if (process.env.NODE_ENV !== 'production') {
Enhanced.displayName = (Facc.displayName || Facc.name) + "(" + (Comp.displayName || Comp.name) + ")";
}
return isClassDecoratorMethodCall ? addClassDecoratorSupport_1.default(Enhanced) : Enhanced;
};
return enhancer;
};
exports.default = createEnhancer;
//# sourceMappingURL=createEnhancer.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"createEnhancer.js","sourceRoot":"","sources":["../src/createEnhancer.ts"],"names":[],"mappings":";;;;AAAA,mDAA+B;AAC/B,gGAAkE;AAElE,IAAM,CAAC,GAAG,KAAK,CAAC,aAAa,CAAC;AAE9B,IAAM,MAAM,GAAG,UAAC,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,KAAK;;IAAK,OAAA,CAAC,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,+BAC/D,QAAQ,IAAG,KAAK,OAAK,KAAK,EAAE,CAAC,uCAC3B,KAAK,GAAK,KAAK,CAAC,CACrB;AAHgD,CAGhD,CAAC;AAEW,QAAA,UAAU,GAAG,UAAC,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,KAAK;IACrD,OAAA,CAAC,CAAC,KAAK,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,KAAK,CAAC,CAAQ;AAA3D,CAA2D,CAAC;AAE9D,IAAM,cAAc,GAAG,UAAC,IAAI,EAAE,IAAa,EAAE,OAAgB;IAAhB,wBAAA,EAAA,gBAAgB;IACzD,IAAM,QAAQ,GAAG,UAAC,IAAI,EAAE,QAAoB,EAAE,SAAwB;QAA9C,yBAAA,EAAA,eAAoB;QAAE,0BAAA,EAAA,gBAAwB;QAClE,IAAM,0BAA0B,GAAG,OAAO,IAAI,KAAK,QAAQ,CAAC;QAE5D,IAAI,0BAA0B,EAAE;YAC5B,OAAO,UAAC,KAAK,IAAK,OAAA,QAAQ,CAAC,KAAK,EAAE,IAAW,IAAI,IAAI,EAAE,QAAe,CAAC,EAArD,CAAqD,CAAC;SAC3E;QAED,IAAM,QAAQ,GAAG,UAAC,KAAK;YACnB,OAAA,CAAC,CAAC,IAAI,EAAE,SAAS,EAAE,UAAC,KAAK,IAAK,OAAA,OAAO,CAAC,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,KAAK,CAAC,EAArC,CAAqC,CAAC;QAApE,CAAoE,CAAC;QAEzE,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,YAAY,EAAE;YACtC,QAAgB,CAAC,WAAW,GAAG,CAAG,IAAI,CAAC,WAAW,IAAI,IAAI,CAAC,IAAI,WAAI,IAAI,CAAC,WAAW,IAAI,IAAI,CAAC,IAAI,OAAG,CAAC;SACxG;QAED,OAAO,0BAA0B,CAAC,CAAC,CAAC,kCAAwB,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;IACtF,CAAC,CAAC;IAEF,OAAO,QAAQ,CAAC;AACpB,CAAC,CAAA;AAED,kBAAe,cAAc,CAAC"}
+5
View File
@@ -0,0 +1,5 @@
import { FC } from 'react';
export declare type MapPropsToArgs<Props extends {}, Args extends any[]> = (props: Props) => Args;
export declare type CreateRenderProp = <Props extends {}, Args extends any[], State extends any>(hook: (...args: Args) => State, mapPropsToArgs?: MapPropsToArgs<Props, Args>) => FC<Props>;
declare const hookToRenderProp: CreateRenderProp;
export default hookToRenderProp;
+11
View File
@@ -0,0 +1,11 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var tslib_1 = require("tslib");
var render_1 = tslib_1.__importDefault(require("./render"));
var defaultMapPropsToArgs = function (props) { return [props]; };
var hookToRenderProp = function (hook, mapPropsToArgs) {
if (mapPropsToArgs === void 0) { mapPropsToArgs = defaultMapPropsToArgs; }
return function (props) { return render_1.default(props, hook.apply(void 0, mapPropsToArgs(props))); };
};
exports.default = hookToRenderProp;
//# sourceMappingURL=hookToRenderProp.js.map
@@ -0,0 +1 @@
{"version":3,"file":"hookToRenderProp.js","sourceRoot":"","sources":["../src/hookToRenderProp.ts"],"names":[],"mappings":";;;AACA,4DAA8B;AAK9B,IAAM,qBAAqB,GAAG,UAAA,KAAK,IAAI,OAAA,CAAC,KAAK,CAAC,EAAP,CAAO,CAAC;AAE/C,IAAM,gBAAgB,GAAqB,UAAC,IAAI,EAAE,cAA6C;IAA7C,+BAAA,EAAA,iBAAiB,qBAA4B;IAC3F,OAAA,UAAA,KAAK,IAAI,OAAA,gBAAM,CAAC,KAAK,EAAE,IAAI,eAAI,cAAc,CAAC,KAAK,CAAC,EAAE,EAA7C,CAA6C;AAAtD,CAAsD,CAAC;AAE3D,kBAAe,gBAAgB,CAAC"}
+11
View File
@@ -0,0 +1,11 @@
/// <reference types="react" />
import render from './render';
import createEnhancer from './createEnhancer';
import hookToRenderProp from './hookToRenderProp';
export interface UniversalProps<Data> {
children?: ((data: Data) => React.ReactNode) | React.ReactNode;
render?: (data: Data) => React.ReactNode;
comp?: React.ComponentType<Data & any>;
component?: React.ComponentType<Data & any>;
}
export { render, createEnhancer, hookToRenderProp, };
+11
View File
@@ -0,0 +1,11 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.hookToRenderProp = exports.createEnhancer = exports.render = void 0;
var tslib_1 = require("tslib");
var render_1 = tslib_1.__importDefault(require("./render"));
exports.render = render_1.default;
var createEnhancer_1 = tslib_1.__importDefault(require("./createEnhancer"));
exports.createEnhancer = createEnhancer_1.default;
var hookToRenderProp_1 = tslib_1.__importDefault(require("./hookToRenderProp"));
exports.hookToRenderProp = hookToRenderProp_1.default;
//# sourceMappingURL=index.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;AAAA,4DAA8B;AAY1B,iBAZG,gBAAM,CAYH;AAXV,4EAA8C;AAY1C,yBAZG,wBAAc,CAYH;AAXlB,gFAAkD;AAY9C,2BAZG,0BAAgB,CAYH"}
+2
View File
@@ -0,0 +1,2 @@
declare const render: (props: any, data: any, ...more: any[]) => any;
export default render;
+56
View File
@@ -0,0 +1,56 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var tslib_1 = require("tslib");
var react_1 = require("react");
var isReact16Plus = parseInt(react_1.version.substr(0, react_1.version.indexOf('.'))) > 15;
var isFn = function (fn) { return typeof fn === 'function'; };
var render = function (props, data) {
var more = [];
for (var _i = 2; _i < arguments.length; _i++) {
more[_i - 2] = arguments[_i];
}
if (process.env.NODE_ENV !== 'production') {
if (typeof props !== 'object') {
throw new TypeError('renderChildren(props, data) first argument must be a props object.');
}
var children_1 = props.children, render_1 = props.render;
if (isFn(children_1) && isFn(render_1)) {
console.warn('Both "render" and "children" are specified for in a universal interface component. ' +
'Children will be used.');
console.trace();
}
if (typeof data !== 'object') {
console.warn('Universal component interface normally expects data to be an object, ' +
("\"" + typeof data + "\" received."));
console.trace();
}
}
var render = props.render, _a = props.children, children = _a === void 0 ? render : _a, component = props.component, _b = props.comp, comp = _b === void 0 ? component : _b;
if (isFn(children))
return children.apply(void 0, tslib_1.__spreadArrays([data], more));
if (comp) {
return react_1.createElement(comp, data);
}
if (children instanceof Array)
return isReact16Plus ? children : react_1.createElement.apply(void 0, tslib_1.__spreadArrays(['div', null], children));
if (children && (children instanceof Object)) {
if (process.env.NODE_ENV !== 'production') {
if (!children.type || ((typeof children.type !== 'string') && (typeof children.type !== 'function') && (typeof children.type !== 'symbol'))) {
console.warn('Universal component interface received object as children, ' +
'expected React element, but received unexpected React "type".');
console.trace();
}
if (typeof children.type === 'string')
return children;
return react_1.cloneElement(children, Object.assign({}, children.props, data));
}
else {
if (typeof children.type === 'string')
return children;
return react_1.cloneElement(children, Object.assign({}, children.props, data));
}
}
return children || null;
};
exports.default = render;
//# sourceMappingURL=render.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"render.js","sourceRoot":"","sources":["../src/render.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,55 @@
import * as React from 'react';
declare const wrapInStatefulComponent: (Comp: any) => {
new (props: Readonly<any>): {
render(): any;
context: any;
setState<K extends string | number | symbol>(state: any, callback?: () => void): void;
forceUpdate(callback?: () => void): void;
readonly props: Readonly<any> & Readonly<{
children?: React.ReactNode;
}>;
state: Readonly<any>;
refs: {
[key: string]: React.ReactInstance;
};
componentDidMount?(): void;
shouldComponentUpdate?(nextProps: Readonly<any>, nextState: Readonly<any>, nextContext: any): boolean;
componentWillUnmount?(): void;
componentDidCatch?(error: Error, errorInfo: React.ErrorInfo): void;
getSnapshotBeforeUpdate?(prevProps: Readonly<any>, prevState: Readonly<any>): any;
componentDidUpdate?(prevProps: Readonly<any>, prevState: Readonly<any>, snapshot?: any): void;
componentWillMount?(): void;
UNSAFE_componentWillMount?(): void;
componentWillReceiveProps?(nextProps: Readonly<any>, nextContext: any): void;
UNSAFE_componentWillReceiveProps?(nextProps: Readonly<any>, nextContext: any): void;
componentWillUpdate?(nextProps: Readonly<any>, nextState: Readonly<any>, nextContext: any): void;
UNSAFE_componentWillUpdate?(nextProps: Readonly<any>, nextState: Readonly<any>, nextContext: any): void;
};
new (props: any, context?: any): {
render(): any;
context: any;
setState<K extends string | number | symbol>(state: any, callback?: () => void): void;
forceUpdate(callback?: () => void): void;
readonly props: Readonly<any> & Readonly<{
children?: React.ReactNode;
}>;
state: Readonly<any>;
refs: {
[key: string]: React.ReactInstance;
};
componentDidMount?(): void;
shouldComponentUpdate?(nextProps: Readonly<any>, nextState: Readonly<any>, nextContext: any): boolean;
componentWillUnmount?(): void;
componentDidCatch?(error: Error, errorInfo: React.ErrorInfo): void;
getSnapshotBeforeUpdate?(prevProps: Readonly<any>, prevState: Readonly<any>): any;
componentDidUpdate?(prevProps: Readonly<any>, prevState: Readonly<any>, snapshot?: any): void;
componentWillMount?(): void;
UNSAFE_componentWillMount?(): void;
componentWillReceiveProps?(nextProps: Readonly<any>, nextContext: any): void;
UNSAFE_componentWillReceiveProps?(nextProps: Readonly<any>, nextContext: any): void;
componentWillUpdate?(nextProps: Readonly<any>, nextState: Readonly<any>, nextContext: any): void;
UNSAFE_componentWillUpdate?(nextProps: Readonly<any>, nextState: Readonly<any>, nextContext: any): void;
};
contextType?: React.Context<any>;
};
export default wrapInStatefulComponent;
@@ -0,0 +1,22 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var tslib_1 = require("tslib");
var React = tslib_1.__importStar(require("react"));
var wrapInStatefulComponent = function (Comp) {
var Decorated = (function (_super) {
tslib_1.__extends(class_1, _super);
function class_1() {
return _super !== null && _super.apply(this, arguments) || this;
}
class_1.prototype.render = function () {
return Comp(this.props, this.context);
};
return class_1;
}(React.Component));
if (process.env.NODE_ENV !== 'production') {
Decorated.displayName = "Decorated(" + (Comp.displayName || Comp.name) + ")";
}
return Decorated;
};
exports.default = wrapInStatefulComponent;
//# sourceMappingURL=wrapInStatefulComponent.js.map
@@ -0,0 +1 @@
{"version":3,"file":"wrapInStatefulComponent.js","sourceRoot":"","sources":["../src/wrapInStatefulComponent.ts"],"names":[],"mappings":";;;AAAA,mDAA+B;AAE/B,IAAM,uBAAuB,GAAG,UAAC,IAAI;IACjC,IAAM,SAAS;QAAiB,mCAAyB;QAAvC;;QAIlB,CAAC;QAHG,wBAAM,GAAN;YACI,OAAO,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;QAC1C,CAAC;QACL,cAAC;IAAD,CAAC,AAJiB,CAAc,KAAK,CAAC,SAAS,EAI9C,CAAC;IAEF,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,YAAY,EAAE;QACtC,SAAiB,CAAC,WAAW,GAAG,gBAAa,IAAI,CAAC,WAAW,IAAI,IAAI,CAAC,IAAI,OAAG,CAAC;KAClF;IAED,OAAO,SAAS,CAAC;AACrB,CAAC,CAAC;AAEF,kBAAe,uBAAuB,CAAC"}
+91
View File
@@ -0,0 +1,91 @@
{
"name": "react-universal-interface",
"version": "0.6.2",
"description": "Universal Children Definition for React Components",
"main": "lib/index.js",
"types": "lib/index.d.ts",
"typings": "lib/index.d.ts",
"repository": {
"type": "git",
"url": "https://github.com/streamich/react-universal-interface.git"
},
"scripts": {
"build": "npm run clean && tsc",
"clean": "rimraf lib",
"test": "npm run test:server && npm run test:client",
"test:server": "mocha -r ts-node/register src/**/*.test-server.ts*",
"test:client": "jest",
"semantic-release": "semantic-release"
},
"peerDependencies": {
"react": "*",
"tslib": "*"
},
"devDependencies": {
"@types/chai": "^4.1.7",
"@types/jest": "^24.0.11",
"@types/node": "^11.13.0",
"@types/react": "^16.8.13",
"@types/react-dom": "^16.8.3",
"chai": "^4.2.0",
"enzyme": "^3.9.0",
"enzyme-adapter-react-16": "^1.12.1",
"enzyme-to-json": "^3.3.5",
"jest": "^24.7.1",
"jest-environment-jsdom": "^24.7.1",
"jest-environment-jsdom-global": "^1.2.0",
"jest-tap-reporter": "^1.9.0",
"mocha": "^6.1.1",
"mol-conventional-changelog": "^1.4.0",
"react": "^16.8.6",
"react-dom": "^16.8.6",
"react-test-renderer": "^16.8.6",
"rimraf": "^2.6.3",
"semantic-release": "^15.13.3",
"ts-jest": "^24.0.2",
"ts-node": "^8.0.3",
"tslib": "^2.0.0",
"typescript": "^3.4.2"
},
"config": {
"commitizen": {
"path": "./node_modules/mol-conventional-changelog"
}
},
"jest": {
"moduleFileExtensions": [
"ts",
"tsx",
"js",
"jsx"
],
"transform": {
"^.+\\.tsx?$": "ts-jest"
},
"transformIgnorePatterns": [],
"testRegex": ".*/__tests__/.*\\.(test|spec)\\.(jsx?|tsx?)$",
"setupFiles": [
"./src/__tests__/setup.js"
],
"reporters": [
"jest-tap-reporter"
],
"testEnvironment": "jest-environment-jsdom-global",
"testURL": "http://localhost"
},
"keywords": [
"react",
"universal",
"interface",
"children",
"definition",
"ucd",
"universal-children",
"facc",
"render",
"prop",
"function",
"child",
"component"
]
}
@@ -0,0 +1,22 @@
import * as React from 'react';
import {renderToString} from 'react-dom/server';
import {expect} from 'chai';
import render from '../render';
import createEnhancer from '../createEnhancer';
const Parent = (props) => render(props, {foo: 'bar'});
const withParent = createEnhancer(Parent, 'parent');
describe('createEnhancer() SSR', () => {
it('exists and does not crash', () => {
expect(typeof createEnhancer).to.equal('function');
});
it('renders as expected', () => {
const Comp = (props) => <div>{props.parent.foo}</div>;
const CompEnhanced = withParent(Comp);
const html = renderToString(<CompEnhanced />);
expect(html).to.equal('<div data-reactroot="">bar</div>');
});
});
@@ -0,0 +1,22 @@
import * as React from 'react';
import {renderToString} from 'react-dom/server';
import {expect} from 'chai';
import render from '../render';
const Parent = (props) => render(props, {foo: 'bar'});
describe('render() SSR', () => {
it('exists and does not crash', () => {
expect(typeof render).to.equal('function');
});
it('renders as expected', () => {
const html = renderToString(
<Parent>
<div>foobar</div>
</Parent>
);
expect(html).to.equal('<div data-reactroot="">foobar</div>');
});
});
+8
View File
@@ -0,0 +1,8 @@
const {configure} = require('enzyme');
const Adapter = require('enzyme-adapter-react-16');
configure({
adapter: new Adapter()
});
global.requestAnimationFrame = window.requestAnimationFrame = (callback) => setTimeout(callback, 17);
@@ -0,0 +1,8 @@
import wrapInStatefulComponent from './wrapInStatefulComponent';
const addClassDecoratorSupport = (Comp) => {
const isSFC = !Comp.prototype;
return !isSFC ? Comp : wrapInStatefulComponent(Comp);
};
export default addClassDecoratorSupport;
+35
View File
@@ -0,0 +1,35 @@
import * as React from 'react';
import addClassDecoratorSupport from './addClassDecoratorSupport';
const h = React.createElement;
const noWrap = (Comp, propName, props, state) => h(Comp, propName ?
{[propName]: state, ...props} :
{...state, ...props}
);
export const divWrapper = (Comp, propName, props, state) =>
h('div', null, noWrap(Comp, propName, props, state)) as any;
const createEnhancer = (Facc, prop?: string, wrapper = noWrap) => {
const enhancer = (Comp, propName: any = prop, faccProps: object = null) => {
const isClassDecoratorMethodCall = typeof Comp === 'string';
if (isClassDecoratorMethodCall) {
return (Klass) => enhancer(Klass, Comp as any || prop, propName as any);
}
const Enhanced = (props) =>
h(Facc, faccProps, (state) => wrapper(Comp, propName, props, state));
if (process.env.NODE_ENV !== 'production') {
(Enhanced as any).displayName = `${Facc.displayName || Facc.name}(${Comp.displayName || Comp.name})`;
}
return isClassDecoratorMethodCall ? addClassDecoratorSupport(Enhanced) : Enhanced;
};
return enhancer;
}
export default createEnhancer;
+12
View File
@@ -0,0 +1,12 @@
import {FC} from 'react';
import render from './render';
export type MapPropsToArgs<Props extends {}, Args extends any[]> = (props: Props) => Args;
export type CreateRenderProp = <Props extends {}, Args extends any[], State extends any>(hook: (...args: Args) => State, mapPropsToArgs?: MapPropsToArgs<Props, Args>) => FC<Props>;
const defaultMapPropsToArgs = props => [props];
const hookToRenderProp: CreateRenderProp = (hook, mapPropsToArgs = defaultMapPropsToArgs as any) =>
props => render(props, hook(...mapPropsToArgs(props)));
export default hookToRenderProp;
+16
View File
@@ -0,0 +1,16 @@
import render from './render';
import createEnhancer from './createEnhancer';
import hookToRenderProp from './hookToRenderProp';
export interface UniversalProps<Data> {
children?: ((data: Data) => React.ReactNode) | React.ReactNode;
render?: (data: Data) => React.ReactNode;
comp?: React.ComponentType<Data & any>;
component?: React.ComponentType<Data & any>;
}
export {
render,
createEnhancer,
hookToRenderProp,
};
+67
View File
@@ -0,0 +1,67 @@
import {createElement as h, cloneElement, version} from 'react';
const isReact16Plus = parseInt(version.substr(0, version.indexOf('.'))) > 15;
const isFn = fn => typeof fn === 'function';
const render = (props, data, ...more) => {
if (process.env.NODE_ENV !== 'production') {
if (typeof props !== 'object') {
throw new TypeError('renderChildren(props, data) first argument must be a props object.');
}
const {children, render} = props;
if (isFn(children) && isFn(render)) {
console.warn(
'Both "render" and "children" are specified for in a universal interface component. ' +
'Children will be used.'
);
console.trace();
}
if (typeof data !== 'object') {
console.warn(
'Universal component interface normally expects data to be an object, ' +
`"${typeof data}" received.`
);
console.trace();
}
}
const {render, children = render, component, comp = component} = props;
if (isFn(children)) return children(data, ...more);
if (comp) {
return h(comp, data);
}
if (children instanceof Array)
return isReact16Plus ? children : h('div', null, ...children);
if (children && (children instanceof Object)) {
if (process.env.NODE_ENV !== 'production') {
if (!children.type || ((typeof children.type !== 'string') && (typeof children.type !== 'function') && (typeof children.type !== 'symbol'))) {
console.warn(
'Universal component interface received object as children, ' +
'expected React element, but received unexpected React "type".'
);
console.trace();
}
if (typeof children.type === 'string')
return children;
return cloneElement(children, Object.assign({}, children.props, data));
} else {
if (typeof children.type === 'string')
return children;
return cloneElement(children, Object.assign({}, children.props, data));
}
}
return children || null;
};
export default render;
@@ -0,0 +1,17 @@
import * as React from 'react';
const wrapInStatefulComponent = (Comp) => {
const Decorated = class extends React.Component<any, any> {
render () {
return Comp(this.props, this.context);
}
};
if (process.env.NODE_ENV !== 'production') {
(Decorated as any).displayName = `Decorated(${Comp.displayName || Comp.name})`;
}
return Decorated;
};
export default wrapInStatefulComponent;
+34
View File
@@ -0,0 +1,34 @@
{
"compilerOptions": {
"target": "es5",
"module": "commonjs",
"moduleResolution": "Node",
"removeComments": true,
"noImplicitAny": false,
"outDir": "./lib",
"allowJs": false,
"allowSyntheticDefaultImports": true,
"jsx": "react",
"skipDefaultLibCheck": true,
"skipLibCheck": true,
"experimentalDecorators": true,
"importHelpers": true,
"pretty": true,
"sourceMap": true,
"esModuleInterop": true,
"noEmitHelpers": true,
"noErrorTruncation": true,
"noFallthroughCasesInSwitch": true,
"noImplicitReturns": true,
"declaration": true,
"lib": ["dom", "es5", "es6", "es7", "es2015", "es2017", "scripthost", "dom.iterable"]
},
"include": ["typing.d.ts", "src"],
"exclude": [
"node_modules",
"lib",
"**/__tests__/**/*",
"*.test.ts",
"*.test.tsx"
]
}