From 8e31ce0f5b61d7d2c34c3118ec982a1ac9180676 Mon Sep 17 00:00:00 2001
From: dsehnal <david.sehnal@gmail.com>
Date: Sun, 3 Apr 2022 11:15:47 +0200
Subject: [PATCH] react 18 support

---
 CHANGELOG.md                              |   3 +++
 package-lock.json                         | Bin 848305 -> 848438 bytes
 package.json                              |  12 +++++++-----
 src/apps/docking-viewer/index.ts          |   2 +-
 src/apps/viewer/app.ts                    |   2 +-
 src/examples/alpha-orbitals/index.ts      |   2 +-
 src/examples/basic-wrapper/index.ts       |   2 +-
 src/examples/lighting/index.ts            |   2 +-
 src/examples/proteopedia-wrapper/index.ts |   2 +-
 src/mol-plugin-ui/react18.ts              |  22 ++++++++++++++++++++++
 10 files changed, 38 insertions(+), 11 deletions(-)
 create mode 100644 src/mol-plugin-ui/react18.ts

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 67483da63..d54930a12 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -15,6 +15,9 @@ Note that since we don't clearly distinguish between a public and private interf
 - Add ``allowTransparentBackfaces`` parameter to support double-sided rendering of transparent geometries
 - Fix handling of case insensitive mmCIF enumeration fields (including entity.type)
 - Fix ``disable-wboit`` Viewer GET param
+- Add support for React 18.
+  - Used by importing ``createPluginUI`` from ``mol-plugin-ui/react18``;
+  - In Mol* 4.0, React 18 will become the default option.
 
 ## [v3.5.0] - 2022-03-25
 
diff --git a/package-lock.json b/package-lock.json
index 8bb1b81fd431e4ef202db81b29795362fd0536a0..529818656e642eccfafae36084ffcd5458763cd1 100644
GIT binary patch
delta 2033
zcmchW+m91v7{)W*o$d6%VOcpv4a+XDYbx7L&kNDmE$#F$(@qc5!>Ajk-A=dNw$qum
z+i8WMc(G9zh-u<WVkAJgka)9-FwqMI6EuMfF^0qo6WjnXa?lH7h;d`=?n3k*aIe1i
z%ljqIljnPWAK$iIx?@?mhQNmzY}18N)gLJQI*DnqN!&4J8naq}s~`jL+a!i=*gGYZ
zhxQE)t*&tR?sxS7e0v^Q2f|5Y<Ar^gOSN9gaoPInBj=c@^P}!rw0m|ZL3<mqbVS_%
z9Jzy{of%z5v$7aGbZD@1T{rgc?afCz<&h5AeHbo&j*P+O*N{Htg}0CwRlsago8k1!
z7zP*L>6$usPe05!BL*^5osxNz&5@C2=>}e+>TX-2;t1gQxGd2)CtAe<m*YbPA;P3x
zA+OP$&IPTZT2PQ;Y>OcRc6;9BrwrCirr4CNHo*+sdE_N1&m*UxzE1O4({l`Y8lF1a
zGtBr*7P;x6aUoTX@g++^$kfXbqj}2bwQ&<Z$;mNPvqi8i&K^!$ZG=ItPqoXU-8WOo
z=J>)y-4<Y+2NEqVSu$3VY^KP%D{WV2@#OwX#}Oj}R~v|Rjy{1X^a<6}emH|_Eb#L+
z)fV{VPt`C}<LtD#88EnAnS85d4SH)ef5sRHQKamh4SMmaJME68VosK7h-`(bNwVlS
zdu%njCB&<;Kr_aCf~DG$xm^tNc_-m#!&D8fG!T5Qb6ur$uJ`C~E+@ZN`RsJ>_M`B+
z)cd@0e+bQegE--hn#u<E|I%&f&WpXs9!54KNP9CAw+5mKy6o@}a%!4&Hl1WV8s=m=
z6&9yUL@N=KW=*vTyg1YH68V%IaFPjuj*_!<)NXY9S;AZ9+akl6L+KnPnLAgK`#>1g
zZ-uW9qbB%CR6Pf`?xQ=O7_dJ;w>~kD5>t*wyX+NARVJHDdfjyg!Si;1%TKkvOvMqQ
zSSce#ctWmoa*Fk5iAY-rRimWG!biwT%$jPGBu%j?b9_7=&Bi3IR>*c1V=D%R!2b~K
zNAM2Ln&H?(RHK^2A@Y9DsPg4QbkGV%L2rf2hxNU1enh_+`hV!z&ES&LA=~)&IF%A>
zO_$jdB?Xfw6Lv8U>w&7D37f`Ec|TW6$Hh`Y2;``2$-v^#yd&vr8^k)@C{D+W(}cf1
zJ|nZ?^hCnKbJ1=&9w+kA5$$HhG~9Qy17B_IF~i`eeZ4SwTE7iykNSq=t&pFqAK+{S
zPT&(lJ7#P|0-lm35KWT7AQ1>o+tXZO)<lp*tTA2n267JC63h5lr?FLZ`J$0#Fe<q0
zX;v)p#Z<DKXbXuLoJnhUb_Sp6pIcJ;lqE&&ISY&%8&Mb*+qITd_8(L`;0CEtgD{U|
zV51XL!`*pg&)Pu>?{aF#d&j$yE8=gzis^wJ(QkoQjw9d0RRSBC+i?(6b{y2)!qyDj
zU2``I8s$bod;7>TxP!{&U$h?xARN<ZVZox_0r!T`Jzy;B*TDl;r&SixI`r%lmi~8`
zq5Et0RhpN(3rkD7wF4Ozeb|clD#;M7W80Pazjb#<*N)xg&ip3;<%>~$vAL%3Zi9t$
M`t{1d8T~2xA4OrkcK`qY

delta 2188
zcmc(fU2Icj7{~K=Yj?KOAxp+K2!^o^m=rmupXU@<Oxv@bet)bx?OAc)S-(!Zwmbb;
zJDL!|kL<#XjTHC97&0*?My@a<94^qH7vcwrCZdT(B7P+X&4e2@i)5CWpy7%e;k|hC
zK3D($`#jJ8ci~6F+dml2eT+7il0v*Pu&;mMkdE3*?lm@wtKE&?+q#hfgb}R!{3l4I
zg3q#8Cv?7oHlE*ySry>krotQVcU(pK#sXe%bgTC~?@`MhHPRe~mtR2J;aUv)1&%#~
zy5$cJV(n=C3Gcpy2Ecj-(LhdMo8UbjX*jOLiwxmD;&p1H6j|_xXHtC87xT|>j6Tjg
zXUtsIp3B+IQa%t$+jwJ`<pWMSl^vZD$N)K#B%LM4tROKAZL1Y%ohP5Eo3pTeS+NT)
zmrxt5PGE6(t%kZ`Vjk^;<5tW9m*&yd#>oi{R~rdxZM0ag9x(?-nW`>i6XT(bV9c76
zf-&rH*(w$1xWs#cj@W25W2;UTilk#yG(<|S*(A^9%fYGI3?GS=A}mXJxJbaC=k5Oy
zKXn-E|3@5~M{3{)R6TJ0F!ni|T4~t=WE!>2tt=pUWkHeH4=)ZNJ^Y+$?}gGL(nRz#
zMq`ZC2jYG%U~w`M;m*-^lA1M39FZIwH5B3zi!Pk;7!o3D8H-j&BW3%vyQVYRr)Et|
zIyzNnt%jNqiv|n{N=g?c&PDK6IJwgD_#AUpAv0H7)L+~k))x8bnbytE0lBQ`YizM@
zkU!NZ`71EJqTCPW32XyYCKZ}gx*!HClqo|bibUN&n2Q7{l!Fw_kTWKWo-uiKQiAf)
zL2V*FWp>OES$EQF&O{;}y&)x4!dxs%N3tocma6eqn)AnVY$!fy9UdOo)6u_v2Bc)N
z)DY%(gQQXQF0J7>T>7@P2d>qXdN@Y6J^_Ihr3$i#ux&8DhSTudugWe&L2**CGgUT<
z7PF_~Ww=nTJmMF91)Wf$EBeV1L0crot(7b-1%nA!Hps9x#uf3GON>R}{n27s;*w@-
z-D7vLq+REX#k@stgepn_8~Y&czW%GF6Yw>>t5G_?sc{3}rO;7uJf_$sH{JFd;hi_y
z)IeHVhQL3h-V9xoVn<4!jHcMMwOEWg*kUE&%g4Q@y4~l|akMALSLtxb!KQOwgMFlu
zAO$AEMAJzJF+Oe2S91lEDQ~KWrwndFPl{tg*p>_jCd(lv^Z>0?`O%>KmPYkq1J2H>
z^gv!vwZfaSst-1?xQ2832+@&AkJ+3t(aV>`f~D*?P)?FIX~htmbUWPyPkAL<)azo1
z)MQ*Q#5rGz)8<&lLi4n)><MZmhhRyOOe}A&*(_{f(%QKFM?akV26fGe7ge%&v2Ema
z_<kSOEjI}<sCYOu`0g~WxkrP=hr)n+l5&#)ThaQL;XoNZ26q<F>f8+hlWz#^U$)(s
z`tkoK_08RwJCSXdPh>l8Ju9EQ*>QFnR!-wRcjFGtxc5QetBy{%eh}|~7wa89Se(F>
z@YK`I>(xQ!Sy+6stp_$v;Jf9e9m+nmUdzpTY5CD$0&WkfhyO)HbFX{hqdWNayKW9V
z0x;a?=N=S*oJX5w(;EKM&?6+leeTw~rTP=^h07Y%D%`r#-n(=YDP?K5dbs-VzyKkl
LeNcuo>gC|y!u8!_

diff --git a/package.json b/package.json
index 36fa245fe..cf81fdeab 100644
--- a/package.json
+++ b/package.json
@@ -101,6 +101,8 @@
     "@types/cors": "^2.8.12",
     "@types/gl": "^4.1.0",
     "@types/jest": "^27.4.1",
+    "@types/react": "^17.0.43",
+    "@types/react-dom": "^17.0.14",
     "@typescript-eslint/eslint-plugin": "^5.14.0",
     "@typescript-eslint/parser": "^5.14.0",
     "benchmark": "^2.1.4",
@@ -118,13 +120,15 @@
     "mini-css-extract-plugin": "^2.6.0",
     "path-browserify": "^1.0.1",
     "raw-loader": "^4.0.2",
+    "react": "^18.0.0",
+    "react-dom": "^18.0.0",
     "sass": "^1.49.9",
     "sass-loader": "^12.6.0",
     "simple-git": "^3.3.0",
     "stream-browserify": "^3.0.0",
     "style-loader": "^3.3.1",
     "ts-jest": "^27.1.3",
-    "typescript": "^4.6.2",
+    "typescript": "^4.6.3",
     "webpack": "^5.70.0",
     "webpack-cli": "^4.9.2"
   },
@@ -135,8 +139,6 @@
     "@types/express": "^4.17.13",
     "@types/node": "^16.11.26",
     "@types/node-fetch": "^2.6.1",
-    "@types/react": "^17.0.40",
-    "@types/react-dom": "^17.0.13",
     "@types/swagger-ui-dist": "3.30.1",
     "argparse": "^2.0.1",
     "body-parser": "^1.19.2",
@@ -154,7 +156,7 @@
     "xhr2": "^0.2.1"
   },
   "peerDependencies": {
-    "react": "^17.0.2 || ^16.14.0",
-    "react-dom": "^17.0.2 || ^16.14.0"
+    "react": "^18.0.0 || ^17.0.2 || ^16.14.0",
+    "react-dom": "^18.0.0 || ^17.0.2 || ^16.14.0"
   }
 }
diff --git a/src/apps/docking-viewer/index.ts b/src/apps/docking-viewer/index.ts
index 82e974586..8242e6203 100644
--- a/src/apps/docking-viewer/index.ts
+++ b/src/apps/docking-viewer/index.ts
@@ -8,7 +8,7 @@
 import { Structure } from '../../mol-model/structure';
 import { BuiltInTrajectoryFormat } from '../../mol-plugin-state/formats/trajectory';
 import { PluginStateObject as PSO, PluginStateTransform } from '../../mol-plugin-state/objects';
-import { createPluginUI } from '../../mol-plugin-ui';
+import { createPluginUI } from '../../mol-plugin-ui/react18';
 import { PluginUIContext } from '../../mol-plugin-ui/context';
 import { PluginLayoutControlsDisplay } from '../../mol-plugin/layout';
 import { DefaultPluginUISpec, PluginUISpec } from '../../mol-plugin-ui/spec';
diff --git a/src/apps/viewer/app.ts b/src/apps/viewer/app.ts
index 30b586aec..eee9375c9 100644
--- a/src/apps/viewer/app.ts
+++ b/src/apps/viewer/app.ts
@@ -32,7 +32,7 @@ import { createVolumeRepresentationParams } from '../../mol-plugin-state/helpers
 import { PluginStateObject } from '../../mol-plugin-state/objects';
 import { StateTransforms } from '../../mol-plugin-state/transforms';
 import { TrajectoryFromModelAndCoordinates } from '../../mol-plugin-state/transforms/model';
-import { createPluginUI } from '../../mol-plugin-ui';
+import { createPluginUI } from '../../mol-plugin-ui/react18';
 import { PluginUIContext } from '../../mol-plugin-ui/context';
 import { DefaultPluginUISpec, PluginUISpec } from '../../mol-plugin-ui/spec';
 import { PluginCommands } from '../../mol-plugin/commands';
diff --git a/src/examples/alpha-orbitals/index.ts b/src/examples/alpha-orbitals/index.ts
index 1322a5b0d..6b600e0bd 100644
--- a/src/examples/alpha-orbitals/index.ts
+++ b/src/examples/alpha-orbitals/index.ts
@@ -11,7 +11,7 @@ import { SphericalBasisOrder } from '../../extensions/alpha-orbitals/spherical-f
 import { BasisAndOrbitals, CreateOrbitalDensityVolume, CreateOrbitalRepresentation3D, CreateOrbitalVolume, StaticBasisAndOrbitals } from '../../extensions/alpha-orbitals/transforms';
 import { canComputeGrid3dOnGPU } from '../../mol-gl/compute/grid3d';
 import { PluginStateObject } from '../../mol-plugin-state/objects';
-import { createPluginUI } from '../../mol-plugin-ui';
+import { createPluginUI } from '../../mol-plugin-ui/react18';
 import { PluginUIContext } from '../../mol-plugin-ui/context';
 import { DefaultPluginUISpec } from '../../mol-plugin-ui/spec';
 import { PluginCommands } from '../../mol-plugin/commands';
diff --git a/src/examples/basic-wrapper/index.ts b/src/examples/basic-wrapper/index.ts
index f63563caa..27d660a29 100644
--- a/src/examples/basic-wrapper/index.ts
+++ b/src/examples/basic-wrapper/index.ts
@@ -9,7 +9,7 @@ import { EmptyLoci } from '../../mol-model/loci';
 import { StructureSelection } from '../../mol-model/structure';
 import { AnimateModelIndex } from '../../mol-plugin-state/animation/built-in/model-index';
 import { BuiltInTrajectoryFormat } from '../../mol-plugin-state/formats/trajectory';
-import { createPluginUI } from '../../mol-plugin-ui';
+import { createPluginUI } from '../../mol-plugin-ui/react18';
 import { PluginUIContext } from '../../mol-plugin-ui/context';
 import { DefaultPluginUISpec } from '../../mol-plugin-ui/spec';
 import { PluginCommands } from '../../mol-plugin/commands';
diff --git a/src/examples/lighting/index.ts b/src/examples/lighting/index.ts
index b81118dd7..23b254b5e 100644
--- a/src/examples/lighting/index.ts
+++ b/src/examples/lighting/index.ts
@@ -6,7 +6,7 @@
 
 import { Canvas3DProps } from '../../mol-canvas3d/canvas3d';
 import { BuiltInTrajectoryFormat } from '../../mol-plugin-state/formats/trajectory';
-import { createPluginUI } from '../../mol-plugin-ui';
+import { createPluginUI } from '../../mol-plugin-ui/react18';
 import { PluginUIContext } from '../../mol-plugin-ui/context';
 import { DefaultPluginUISpec } from '../../mol-plugin-ui/spec';
 import { PluginCommands } from '../../mol-plugin/commands';
diff --git a/src/examples/proteopedia-wrapper/index.ts b/src/examples/proteopedia-wrapper/index.ts
index f762038f4..f371c943f 100644
--- a/src/examples/proteopedia-wrapper/index.ts
+++ b/src/examples/proteopedia-wrapper/index.ts
@@ -10,7 +10,7 @@ import { AnimateModelIndex } from '../../mol-plugin-state/animation/built-in/mod
 import { createStructureRepresentationParams } from '../../mol-plugin-state/helpers/structure-representation-params';
 import { PluginStateObject, PluginStateObject as PSO } from '../../mol-plugin-state/objects';
 import { StateTransforms } from '../../mol-plugin-state/transforms';
-import { createPluginUI } from '../../mol-plugin-ui';
+import { createPluginUI } from '../../mol-plugin-ui/react18';
 import { PluginUIContext } from '../../mol-plugin-ui/context';
 import { DefaultPluginUISpec } from '../../mol-plugin-ui/spec';
 import { CreateVolumeStreamingInfo, InitVolumeStreaming } from '../../mol-plugin/behavior/dynamic/volume-streaming/transformers';
diff --git a/src/mol-plugin-ui/react18.ts b/src/mol-plugin-ui/react18.ts
new file mode 100644
index 000000000..6309eebc1
--- /dev/null
+++ b/src/mol-plugin-ui/react18.ts
@@ -0,0 +1,22 @@
+/**
+ * Copyright (c) 2018-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ *
+ * @author David Sehnal <david.sehnal@gmail.com>
+ * @author Alexander Rose <alexander.rose@weirdbyte.de>
+ */
+
+import { createElement } from 'react';
+import { createRoot } from 'react-dom/client';
+import { Plugin } from './plugin';
+import { PluginUIContext } from './context';
+import { DefaultPluginUISpec, PluginUISpec } from './spec';
+
+export async function createPluginUI(target: HTMLElement, spec?: PluginUISpec, options?: { onBeforeUIRender?: (ctx: PluginUIContext) => (Promise<void> | void) }) {
+    const ctx = new PluginUIContext(spec || DefaultPluginUISpec());
+    await ctx.init();
+    if (options?.onBeforeUIRender) {
+        await options.onBeforeUIRender(ctx);
+    }
+    createRoot(target).render(createElement(Plugin, { plugin: ctx }));
+    return ctx;
+}
\ No newline at end of file
-- 
GitLab