feat: add support for React@18 in backward compatible way (#9435)
Any React version matching this semver is supported: >= 16.8 < 19 Refs #8126 Refs #8414
This commit is contained in:
26092
package-lock.json
generated
26092
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -90,10 +90,10 @@
|
|||||||
"prop-types": "^15.8.1",
|
"prop-types": "^15.8.1",
|
||||||
"randexp": "^0.5.3",
|
"randexp": "^0.5.3",
|
||||||
"randombytes": "^2.1.0",
|
"randombytes": "^2.1.0",
|
||||||
"react": "=17.0.2",
|
"react": ">=16.8.0 <19",
|
||||||
"react-copy-to-clipboard": "5.1.0",
|
"react-copy-to-clipboard": "5.1.0",
|
||||||
"react-debounce-input": "=3.3.0",
|
"react-debounce-input": "=3.3.0",
|
||||||
"react-dom": "=17.0.2",
|
"react-dom": ">=16.8.0 <19",
|
||||||
"react-immutable-proptypes": "2.2.0",
|
"react-immutable-proptypes": "2.2.0",
|
||||||
"react-immutable-pure-component": "^2.2.0",
|
"react-immutable-pure-component": "^2.2.0",
|
||||||
"react-inspector": "^6.0.1",
|
"react-inspector": "^6.0.1",
|
||||||
@@ -125,7 +125,7 @@
|
|||||||
"@pmmmwh/react-refresh-webpack-plugin": "^0.5.11",
|
"@pmmmwh/react-refresh-webpack-plugin": "^0.5.11",
|
||||||
"@release-it/conventional-changelog": "=5.1.0",
|
"@release-it/conventional-changelog": "=5.1.0",
|
||||||
"@svgr/webpack": "=8.1.0",
|
"@svgr/webpack": "=8.1.0",
|
||||||
"@wojtekmaj/enzyme-adapter-react-17": "=0.8.0",
|
"@cfaester/enzyme-adapter-react-18": "=0.7.1",
|
||||||
"autoprefixer": "^10.4.16",
|
"autoprefixer": "^10.4.16",
|
||||||
"babel-loader": "^9.1.3",
|
"babel-loader": "^9.1.3",
|
||||||
"babel-plugin-lodash": "=3.3.4",
|
"babel-plugin-lodash": "=3.3.4",
|
||||||
@@ -177,7 +177,7 @@
|
|||||||
"prettier": "^3.1.0",
|
"prettier": "^3.1.0",
|
||||||
"process": "^0.11.10",
|
"process": "^0.11.10",
|
||||||
"react-refresh": "^0.14.0",
|
"react-refresh": "^0.14.0",
|
||||||
"react-test-renderer": "=17.0.2",
|
"react-test-renderer": "^18.2.0",
|
||||||
"release-it": "=15.4.2",
|
"release-it": "=15.4.2",
|
||||||
"rimraf": "^5.0.5",
|
"rimraf": "^5.0.5",
|
||||||
"sass": "^1.69.5",
|
"sass": "^1.69.5",
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import SpecPlugin from "./plugins/spec"
|
|||||||
import SwaggerClientPlugin from "./plugins/swagger-client"
|
import SwaggerClientPlugin from "./plugins/swagger-client"
|
||||||
import UtilPlugin from "./plugins/util"
|
import UtilPlugin from "./plugins/util"
|
||||||
import ViewPlugin from "./plugins/view"
|
import ViewPlugin from "./plugins/view"
|
||||||
|
import ViewLegacyPlugin from "core/plugins/view-legacy"
|
||||||
import DownloadUrlPlugin from "./plugins/download-url"
|
import DownloadUrlPlugin from "./plugins/download-url"
|
||||||
import SafeRenderPlugin from "./plugins/safe-render"
|
import SafeRenderPlugin from "./plugins/safe-render"
|
||||||
|
|
||||||
@@ -268,6 +269,7 @@ SwaggerUI.plugins = {
|
|||||||
SwaggerClient: SwaggerClientPlugin,
|
SwaggerClient: SwaggerClientPlugin,
|
||||||
Util: UtilPlugin,
|
Util: UtilPlugin,
|
||||||
View: ViewPlugin,
|
View: ViewPlugin,
|
||||||
|
ViewLegacy: ViewLegacyPlugin,
|
||||||
DownloadUrl: DownloadUrlPlugin,
|
DownloadUrl: DownloadUrlPlugin,
|
||||||
SafeRender: SafeRenderPlugin,
|
SafeRender: SafeRenderPlugin,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,4 +30,4 @@ export default class ServersContainer extends React.Component {
|
|||||||
/>
|
/>
|
||||||
</div> ) : null
|
</div> ) : null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,176 +1,149 @@
|
|||||||
import React from "react"
|
/**
|
||||||
|
* @prettier
|
||||||
|
*/
|
||||||
|
import React, { useCallback, useEffect } from "react"
|
||||||
import { OrderedMap } from "immutable"
|
import { OrderedMap } from "immutable"
|
||||||
import PropTypes from "prop-types"
|
import PropTypes from "prop-types"
|
||||||
import ImPropTypes from "react-immutable-proptypes"
|
import ImPropTypes from "react-immutable-proptypes"
|
||||||
|
|
||||||
export default class Servers extends React.Component {
|
const Servers = ({
|
||||||
|
servers,
|
||||||
|
currentServer,
|
||||||
|
setSelectedServer,
|
||||||
|
setServerVariableValue,
|
||||||
|
getServerVariable,
|
||||||
|
getEffectiveServerValue,
|
||||||
|
}) => {
|
||||||
|
const currentServerDefinition =
|
||||||
|
servers.find((s) => s.get("url") === currentServer) || OrderedMap()
|
||||||
|
const currentServerVariableDefs =
|
||||||
|
currentServerDefinition.get("variables") || OrderedMap()
|
||||||
|
const shouldShowVariableUI = currentServerVariableDefs.size !== 0
|
||||||
|
|
||||||
static propTypes = {
|
useEffect(() => {
|
||||||
servers: ImPropTypes.list.isRequired,
|
if (currentServer) return
|
||||||
currentServer: PropTypes.string.isRequired,
|
|
||||||
setSelectedServer: PropTypes.func.isRequired,
|
|
||||||
setServerVariableValue: PropTypes.func.isRequired,
|
|
||||||
getServerVariable: PropTypes.func.isRequired,
|
|
||||||
getEffectiveServerValue: PropTypes.func.isRequired
|
|
||||||
}
|
|
||||||
|
|
||||||
componentDidMount() {
|
// fire 'change' event to set default 'value' of select
|
||||||
let { servers, currentServer } = this.props
|
setSelectedServer(servers.first()?.get("url"))
|
||||||
|
}, [])
|
||||||
|
|
||||||
if(currentServer) {
|
useEffect(() => {
|
||||||
|
// server has changed, we may need to set default values
|
||||||
|
const currentServerDefinition = servers.find(
|
||||||
|
(server) => server.get("url") === currentServer
|
||||||
|
)
|
||||||
|
if (!currentServerDefinition) {
|
||||||
|
setSelectedServer(servers.first().get("url"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// fire 'change' event to set default 'value' of select
|
const currentServerVariableDefs =
|
||||||
this.setServer(servers.first()?.get("url"))
|
currentServerDefinition.get("variables") || OrderedMap()
|
||||||
}
|
currentServerVariableDefs.map((val, key) => {
|
||||||
|
setServerVariableValue({
|
||||||
UNSAFE_componentWillReceiveProps(nextProps) {
|
server: currentServer,
|
||||||
let {
|
key,
|
||||||
servers,
|
val: val.get("default") || "",
|
||||||
setServerVariableValue,
|
|
||||||
getServerVariable
|
|
||||||
} = nextProps
|
|
||||||
if (this.props.currentServer !== nextProps.currentServer || this.props.servers !== nextProps.servers) {
|
|
||||||
// Server has changed, we may need to set default values
|
|
||||||
let currentServerDefinition = servers
|
|
||||||
.find(v => v.get("url") === nextProps.currentServer)
|
|
||||||
let prevServerDefinition = this.props.servers
|
|
||||||
.find(v => v.get("url") === this.props.currentServer) || OrderedMap()
|
|
||||||
|
|
||||||
if(!currentServerDefinition) {
|
|
||||||
return this.setServer(servers.first().get("url"))
|
|
||||||
}
|
|
||||||
|
|
||||||
let prevServerVariableDefs = prevServerDefinition.get("variables") || OrderedMap()
|
|
||||||
let prevServerVariableDefaultKey = prevServerVariableDefs.find(v => v.get("default")) || OrderedMap()
|
|
||||||
let prevServerVariableDefaultValue = prevServerVariableDefaultKey.get("default")
|
|
||||||
|
|
||||||
let currentServerVariableDefs = currentServerDefinition.get("variables") || OrderedMap()
|
|
||||||
let currentServerVariableDefaultKey = currentServerVariableDefs.find(v => v.get("default")) || OrderedMap()
|
|
||||||
let currentServerVariableDefaultValue = currentServerVariableDefaultKey.get("default")
|
|
||||||
|
|
||||||
currentServerVariableDefs.map((val, key) => {
|
|
||||||
let currentValue = getServerVariable(nextProps.currentServer, key)
|
|
||||||
|
|
||||||
// note: it is possible for both key/val to be the same across definitions,
|
|
||||||
// but we will try to detect a change in default values between definitions
|
|
||||||
// only set the default value if the user hasn't set one yet
|
|
||||||
// or if the definition appears to have changed
|
|
||||||
if (!currentValue || prevServerVariableDefaultValue !== currentServerVariableDefaultValue) {
|
|
||||||
setServerVariableValue({
|
|
||||||
server: nextProps.currentServer,
|
|
||||||
key,
|
|
||||||
val: val.get("default") || ""
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
}
|
})
|
||||||
}
|
}, [currentServer, servers])
|
||||||
|
|
||||||
onServerChange =( e ) => {
|
const handleServerChange = useCallback(
|
||||||
this.setServer( e.target.value )
|
(e) => {
|
||||||
|
setSelectedServer(e.target.value)
|
||||||
|
},
|
||||||
|
[setSelectedServer]
|
||||||
|
)
|
||||||
|
|
||||||
// set default variable values
|
const handleServerVariableChange = useCallback(
|
||||||
}
|
(e) => {
|
||||||
|
const variableName = e.target.getAttribute("data-variable")
|
||||||
|
const newVariableValue = e.target.value
|
||||||
|
|
||||||
onServerVariableValueChange = ( e ) => {
|
|
||||||
let {
|
|
||||||
setServerVariableValue,
|
|
||||||
currentServer
|
|
||||||
} = this.props
|
|
||||||
|
|
||||||
let variableName = e.target.getAttribute("data-variable")
|
|
||||||
let newVariableValue = e.target.value
|
|
||||||
|
|
||||||
if(typeof setServerVariableValue === "function") {
|
|
||||||
setServerVariableValue({
|
setServerVariableValue({
|
||||||
server: currentServer,
|
server: currentServer,
|
||||||
key: variableName,
|
key: variableName,
|
||||||
val: newVariableValue
|
val: newVariableValue,
|
||||||
})
|
})
|
||||||
}
|
},
|
||||||
}
|
[setServerVariableValue, currentServer]
|
||||||
|
)
|
||||||
|
|
||||||
setServer = ( value ) => {
|
return (
|
||||||
let { setSelectedServer } = this.props
|
<div className="servers">
|
||||||
|
<label htmlFor="servers">
|
||||||
setSelectedServer(value)
|
<select onChange={handleServerChange} value={currentServer}>
|
||||||
}
|
{servers
|
||||||
|
.valueSeq()
|
||||||
render() {
|
.map((server) => (
|
||||||
let { servers,
|
<option value={server.get("url")} key={server.get("url")}>
|
||||||
currentServer,
|
{server.get("url")}
|
||||||
getServerVariable,
|
{server.get("description") && ` - ${server.get("description")}`}
|
||||||
getEffectiveServerValue
|
|
||||||
} = this.props
|
|
||||||
|
|
||||||
|
|
||||||
let currentServerDefinition = servers.find(s => s.get("url") === currentServer) || OrderedMap()
|
|
||||||
|
|
||||||
let currentServerVariableDefs = currentServerDefinition.get("variables") || OrderedMap()
|
|
||||||
|
|
||||||
let shouldShowVariableUI = currentServerVariableDefs.size !== 0
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="servers">
|
|
||||||
<label htmlFor="servers">
|
|
||||||
<select onChange={ this.onServerChange } value={currentServer}>
|
|
||||||
{ servers.valueSeq().map(
|
|
||||||
( server ) =>
|
|
||||||
<option
|
|
||||||
value={ server.get("url") }
|
|
||||||
key={ server.get("url") }>
|
|
||||||
{ server.get("url") }
|
|
||||||
{ server.get("description") && ` - ${server.get("description")}` }
|
|
||||||
</option>
|
</option>
|
||||||
).toArray()}
|
))
|
||||||
</select>
|
.toArray()}
|
||||||
</label>
|
</select>
|
||||||
{ shouldShowVariableUI ?
|
</label>
|
||||||
<div>
|
{shouldShowVariableUI && (
|
||||||
|
<div>
|
||||||
<div className={"computed-url"}>
|
<div className={"computed-url"}>
|
||||||
Computed URL:
|
Computed URL:
|
||||||
<code>
|
<code>{getEffectiveServerValue(currentServer)}</code>
|
||||||
{getEffectiveServerValue(currentServer)}
|
</div>
|
||||||
</code>
|
<h4>Server variables</h4>
|
||||||
</div>
|
<table>
|
||||||
<h4>Server variables</h4>
|
<tbody>
|
||||||
<table>
|
{currentServerVariableDefs.entrySeq().map(([name, val]) => {
|
||||||
<tbody>
|
return (
|
||||||
{
|
<tr key={name}>
|
||||||
currentServerVariableDefs.entrySeq().map(([name, val]) => {
|
<td>{name}</td>
|
||||||
return <tr key={name}>
|
<td>
|
||||||
<td>{name}</td>
|
{val.get("enum") ? (
|
||||||
<td>
|
<select
|
||||||
{ val.get("enum") ?
|
data-variable={name}
|
||||||
<select data-variable={name} onChange={this.onServerVariableValueChange}>
|
onChange={handleServerVariableChange}
|
||||||
{val.get("enum").map(enumValue => {
|
>
|
||||||
return <option
|
{val.get("enum").map((enumValue) => {
|
||||||
selected={enumValue === getServerVariable(currentServer, name)}
|
return (
|
||||||
|
<option
|
||||||
|
selected={
|
||||||
|
enumValue ===
|
||||||
|
getServerVariable(currentServer, name)
|
||||||
|
}
|
||||||
key={enumValue}
|
key={enumValue}
|
||||||
value={enumValue}>
|
value={enumValue}
|
||||||
|
>
|
||||||
{enumValue}
|
{enumValue}
|
||||||
</option>
|
</option>
|
||||||
})}
|
)
|
||||||
</select> :
|
})}
|
||||||
<input
|
</select>
|
||||||
type={"text"}
|
) : (
|
||||||
value={getServerVariable(currentServer, name) || ""}
|
<input
|
||||||
onChange={this.onServerVariableValueChange}
|
type={"text"}
|
||||||
data-variable={name}
|
value={getServerVariable(currentServer, name) || ""}
|
||||||
></input>
|
onChange={handleServerVariableChange}
|
||||||
}
|
data-variable={name}
|
||||||
</td>
|
></input>
|
||||||
</tr>
|
)}
|
||||||
})
|
</td>
|
||||||
}
|
</tr>
|
||||||
</tbody>
|
)
|
||||||
</table>
|
})}
|
||||||
</div>: null
|
</tbody>
|
||||||
}
|
</table>
|
||||||
</div>
|
</div>
|
||||||
)
|
)}
|
||||||
}
|
</div>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
Servers.propTypes = {
|
||||||
|
servers: ImPropTypes.list.isRequired,
|
||||||
|
currentServer: PropTypes.string.isRequired,
|
||||||
|
setSelectedServer: PropTypes.func.isRequired,
|
||||||
|
setServerVariableValue: PropTypes.func.isRequired,
|
||||||
|
getServerVariable: PropTypes.func.isRequired,
|
||||||
|
getEffectiveServerValue: PropTypes.func.isRequired,
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Servers
|
||||||
|
|||||||
25
src/core/plugins/view-legacy/index.js
Normal file
25
src/core/plugins/view-legacy/index.js
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
/**
|
||||||
|
* @prettier
|
||||||
|
*/
|
||||||
|
import { getComponent } from "core/plugins/view/root-injects"
|
||||||
|
import { render } from "./root-injects"
|
||||||
|
|
||||||
|
const ViewLegacyPlugin = ({ React, getSystem, getStore, getComponents }) => {
|
||||||
|
const rootInjects = {}
|
||||||
|
const reactMajorVersion = parseInt(React?.version, 10)
|
||||||
|
|
||||||
|
if (reactMajorVersion >= 16 && reactMajorVersion < 18) {
|
||||||
|
rootInjects.render = render(
|
||||||
|
getSystem,
|
||||||
|
getStore,
|
||||||
|
getComponent,
|
||||||
|
getComponents
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
rootInjects,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ViewLegacyPlugin
|
||||||
12
src/core/plugins/view-legacy/root-injects.jsx
Normal file
12
src/core/plugins/view-legacy/root-injects.jsx
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
/**
|
||||||
|
* @prettier
|
||||||
|
*/
|
||||||
|
import React from "react"
|
||||||
|
import ReactDOM from "react-dom"
|
||||||
|
|
||||||
|
export const render =
|
||||||
|
(getSystem, getStore, getComponent, getComponents) => (domNode) => {
|
||||||
|
const App = getComponent(getSystem, getStore, getComponents)("App", "root")
|
||||||
|
|
||||||
|
ReactDOM.render(<App />, domNode)
|
||||||
|
}
|
||||||
@@ -82,7 +82,10 @@ export const withMappedContainer = (getSystem, getStore, memGetComponent) => (co
|
|||||||
|
|
||||||
export const render = (getSystem, getStore, getComponent, getComponents) => (domNode) => {
|
export const render = (getSystem, getStore, getComponent, getComponents) => (domNode) => {
|
||||||
const App = getComponent(getSystem, getStore, getComponents)("App", "root")
|
const App = getComponent(getSystem, getStore, getComponents)("App", "root")
|
||||||
ReactDOM.render(<App/>, domNode)
|
const { createRoot } = ReactDOM
|
||||||
|
const root = createRoot(domNode)
|
||||||
|
|
||||||
|
root.render(<App/>)
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getComponent = (getSystem, getStore, getComponents) => (componentName, container, config = {}) => {
|
export const getComponent = (getSystem, getStore, getComponents) => (componentName, container, config = {}) => {
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import SpecPlugin from "core/plugins/spec"
|
|||||||
import SwaggerClientPlugin from "core/plugins/swagger-client"
|
import SwaggerClientPlugin from "core/plugins/swagger-client"
|
||||||
import UtilPlugin from "core/plugins/util"
|
import UtilPlugin from "core/plugins/util"
|
||||||
import ViewPlugin from "core/plugins/view"
|
import ViewPlugin from "core/plugins/view"
|
||||||
|
import ViewLegacyPlugin from "core/plugins/view-legacy"
|
||||||
import DownloadUrlPlugin from "core/plugins/download-url"
|
import DownloadUrlPlugin from "core/plugins/download-url"
|
||||||
import SafeRenderPlugin from "core/plugins/safe-render"
|
import SafeRenderPlugin from "core/plugins/safe-render"
|
||||||
// ad-hoc plugins
|
// ad-hoc plugins
|
||||||
@@ -28,6 +29,7 @@ const BasePreset = () => [
|
|||||||
UtilPlugin,
|
UtilPlugin,
|
||||||
LogsPlugin,
|
LogsPlugin,
|
||||||
ViewPlugin,
|
ViewPlugin,
|
||||||
|
ViewLegacyPlugin,
|
||||||
SpecPlugin,
|
SpecPlugin,
|
||||||
ErrPlugin,
|
ErrPlugin,
|
||||||
IconsPlugin,
|
IconsPlugin,
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
const { JSDOM } = require("jsdom")
|
const { JSDOM } = require("jsdom")
|
||||||
const Enzyme = require("enzyme")
|
const Enzyme = require("enzyme")
|
||||||
const Adapter = require("@wojtekmaj/enzyme-adapter-react-17")
|
const { default: Adapter } = require("@cfaester/enzyme-adapter-react-18")
|
||||||
|
|
||||||
const win = require("../../src/core/window")
|
const win = require("../../src/core/window")
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { JSDOM } from "jsdom"
|
import { JSDOM } from "jsdom"
|
||||||
import Enzyme from "enzyme"
|
import Enzyme from "enzyme"
|
||||||
import Adapter from "@wojtekmaj/enzyme-adapter-react-17"
|
const { default: Adapter } = require("@cfaester/enzyme-adapter-react-18")
|
||||||
|
|
||||||
import win from "../../src/core/window"
|
import win from "../../src/core/window"
|
||||||
|
|
||||||
@@ -29,7 +29,7 @@ function setUpDomEnvironment() {
|
|||||||
}
|
}
|
||||||
copyProps(win, window) // use UI's built-in window wrapper
|
copyProps(win, window) // use UI's built-in window wrapper
|
||||||
copyProps(window, global)
|
copyProps(window, global)
|
||||||
|
|
||||||
// https://github.com/jsdom/jsdom/issues/1721
|
// https://github.com/jsdom/jsdom/issues/1721
|
||||||
if (typeof global.window.URL.createObjectURL === "undefined") {
|
if (typeof global.window.URL.createObjectURL === "undefined") {
|
||||||
Object.defineProperty(global.window.URL, "createObjectURL", { value: () => "data:text/plain;base64,SGVsbG8sIFdvcmxkIQ==" })
|
Object.defineProperty(global.window.URL, "createObjectURL", { value: () => "data:text/plain;base64,SGVsbG8sIFdvcmxkIQ==" })
|
||||||
|
|||||||
Reference in New Issue
Block a user