@@ -203,6 +203,9 @@ def get_uid_str(uid):
203203 const remountOnUidChange = view.model.get('remount_on_uid_change');
204204 const storeUrls = view.model.get('store_urls');
205205
206+ const pageMode = view.model.get('page_mode');
207+ const pageEsm = view.model.get('page_esm');
208+
206209 const pkgName = (jsDevMode ? "@vitessce/dev" : "vitessce");
207210
208211 importMap.imports["vitessce"] = (customJsUrl.length > 0
@@ -216,14 +219,17 @@ def get_uid_str(uid):
216219 PluginViewType,
217220 PluginCoordinationType,
218221 PluginJointFileType,
222+ PluginAsyncFunction,
219223 z,
220224 useCoordination,
225+ usePageModeView,
221226 } = await importWithMap("vitessce", importMap);
222227
223228 let pluginViewTypes = [];
224229 let pluginCoordinationTypes = [];
225230 let pluginFileTypes = [];
226231 let pluginJointFileTypes = [];
232+ let pluginAsyncFunctions = [];
227233
228234 const stores = Object.fromEntries(
229235 storeUrls.map(storeUrl => ([
@@ -248,16 +254,18 @@ def get_uid_str(uid):
248254 const pluginModule = (await import(pluginEsmUrl)).default;
249255 URL.revokeObjectURL(pluginEsmUrl);
250256
251- const pluginsObj = await pluginModule.createPlugins( {
257+ const pluginDeps = {
252258 React,
253259 PluginFileType,
254260 PluginViewType,
255261 PluginCoordinationType,
256262 PluginJointFileType,
263+ PluginAsyncFunction,
257264 z,
258265 useCoordination,
259266 invokeCommand: invokePluginCommand,
260- });
267+ };
268+ const pluginsObj = await pluginModule.createPlugins(pluginDeps);
261269 if(Array.isArray(pluginsObj.pluginViewTypes)) {
262270 pluginViewTypes = [...pluginViewTypes, ...pluginsObj.pluginViewTypes];
263271 }
@@ -270,11 +278,30 @@ def get_uid_str(uid):
270278 if(Array.isArray(pluginsObj.pluginJointFileTypes)) {
271279 pluginJointFileTypes = [...pluginJointFileTypes, ...pluginsObj.pluginJointFileTypes];
272280 }
281+ if(Array.isArray(pluginsObj.pluginAsyncFunctions)) {
282+ pluginAsyncFunctions = [...pluginAsyncFunctions, ...pluginsObj.pluginAsyncFunctions];
283+ }
273284 } catch(e) {
285+ console.error("Error loading plugin ESM or executing createPlugins function.");
274286 console.error(e);
275287 }
276288 }
277289
290+ let PageComponent;
291+ try {
292+ const pageEsmUrl = URL.createObjectURL(new Blob([pageEsm], { type: "text/javascript" }));
293+ const pageModule = (await import(pageEsmUrl)).default;
294+ URL.revokeObjectURL(pageEsmUrl);
295+
296+ const pageDeps = {
297+ usePageModeView,
298+ };
299+ PageComponent = await pageModule.createPage(pageDeps);
300+ } catch(e) {
301+ console.error("Error loading page ESM or executing createPage function.")
302+ console.error(e);
303+ }
304+
278305 function VitessceWidget(props) {
279306 const { model } = props;
280307
@@ -338,14 +365,17 @@ def get_uid_str(uid):
338365
339366 const vitessceProps = {
340367 height, theme, config, onConfigChange, validateConfig,
341- pluginViewTypes, pluginCoordinationTypes, pluginFileTypes, pluginJointFileTypes,
342- remountOnUidChange, stores,
368+ pluginViewTypes, pluginCoordinationTypes,
369+ pluginFileTypes,pluginJointFileTypes, pluginAsyncFunctions,
370+ remountOnUidChange, stores, pageMode,
343371 };
344372
345373 return e('div', { ref: divRef, style: { height: height + 'px' } },
346374 e(React.Suspense, { fallback: e('div', {}, 'Loading...') },
347375 e(React.StrictMode, {},
348- e(Vitessce, vitessceProps)
376+ e(Vitessce, vitessceProps,
377+ (pageMode ? e(PageComponent, {}) : null)
378+ ),
349379 ),
350380 ),
351381 );
@@ -379,6 +409,7 @@ def get_uid_str(uid):
379409 PluginViewType,
380410 PluginCoordinationType,
381411 PluginJointFileType,
412+ PluginAsyncFunction,
382413 z,
383414 useCoordination,
384415 invokeCommand,
@@ -388,11 +419,32 @@ def get_uid_str(uid):
388419 pluginFileTypes: undefined,
389420 pluginCoordinationTypes: undefined,
390421 pluginJointFileTypes: undefined,
422+ pluginAsyncFunctions: undefined,
391423 };
392424}
393425export default { createPlugins };
394426"""
395427
428+ DEFAULT_PAGE_ESM = """
429+ function createPage(utilsForPage) {
430+ const {
431+ usePageModeView,
432+ } = utilsForPage;
433+
434+ function PageComponent(props) {
435+ const BiomarkerSelect = usePageModeView('biomarker-select');
436+
437+ return (
438+ <div>
439+ <BiomarkerSelect />
440+ </div>
441+ );
442+ }
443+ return PageComponent;
444+ }
445+ export default { createPage };
446+ """
447+
396448
397449class VitesscePlugin :
398450 """
@@ -437,10 +489,13 @@ class VitessceWidget(anywidget.AnyWidget):
437489 custom_js_url = Unicode ('' ).tag (sync = True )
438490 plugin_esm = List (trait = Unicode ('' ), default_value = []).tag (sync = True )
439491 remount_on_uid_change = Bool (True ).tag (sync = True )
492+ page_mode = Bool (False ).tag (sync = True )
493+ page_esm = Unicode ('' ).tag (sync = True )
494+
440495
441496 store_urls = List (trait = Unicode ('' ), default_value = []).tag (sync = True )
442497
443- def __init__ (self , config , height = 600 , theme = 'auto' , uid = None , port = None , proxy = False , js_package_version = '3.3.12' , js_dev_mode = False , custom_js_url = '' , plugins = None , remount_on_uid_change = True ):
498+ def __init__ (self , config , height = 600 , theme = 'auto' , uid = None , port = None , proxy = False , js_package_version = '3.3.12' , js_dev_mode = False , custom_js_url = '' , plugins = None , remount_on_uid_change = True , page_mode = False , page_esm = None ):
444499 """
445500 Construct a new Vitessce widget.
446501
@@ -453,8 +508,10 @@ def __init__(self, config, height=600, theme='auto', uid=None, port=None, proxy=
453508 :param str js_package_version: The version of the NPM package ('vitessce' if not js_dev_mode else '@vitessce/dev').
454509 :param bool js_dev_mode: Should @vitessce/dev be used (typically for debugging purposes)? By default, False.
455510 :param str custom_js_url: A URL to a JavaScript file to use (instead of 'vitessce' or '@vitessce/dev' NPM package).
456- :param list[WidgetPlugin ] plugins: A list of subclasses of VitesscePlugin. Optional.
511+ :param list[VitesscePlugin ] plugins: A list of subclasses of VitesscePlugin. Optional.
457512 :param bool remount_on_uid_change: Passed to the remountOnUidChange prop of the <Vitessce/> React component. By default, True.
513+ :param bool page_mode: Whether to render the <Vitessce/> component in grid-mode or page-mode. By default, False.
514+ :param str page_esm: The ES module string for the page component creation function. Optional.
458515
459516 .. code-block:: python
460517 :emphasize-lines: 4
@@ -487,6 +544,7 @@ def __init__(self, config, height=600, theme='auto', uid=None, port=None, proxy=
487544 config = config_dict , height = height , theme = theme , proxy = proxy ,
488545 js_package_version = js_package_version , js_dev_mode = js_dev_mode , custom_js_url = custom_js_url ,
489546 plugin_esm = plugin_esm , remount_on_uid_change = remount_on_uid_change ,
547+ page_mode = page_mode , page_esm = ('' if page_esm is None else page_esm ),
490548 uid = uid_str , store_urls = list (self ._stores .keys ())
491549 )
492550
@@ -550,9 +608,7 @@ def _plugin_command(self, params, buffers):
550608 return command_func (command_params , buffers )
551609
552610# Launch Vitessce using plain HTML representation (no ipywidgets)
553-
554-
555- def ipython_display (config , height = 600 , theme = 'auto' , base_url = None , host_name = None , uid = None , port = None , proxy = False , js_package_version = '3.3.12' , js_dev_mode = False , custom_js_url = '' , plugin_esm = DEFAULT_PLUGIN_ESM , remount_on_uid_change = True ):
611+ def ipython_display (config , height = 600 , theme = 'auto' , base_url = None , host_name = None , uid = None , port = None , proxy = False , js_package_version = '3.3.12' , js_dev_mode = False , custom_js_url = '' , plugins = None , remount_on_uid_change = True ):
556612 from IPython .display import display , HTML
557613 uid_str = "vitessce" + get_uid_str (uid )
558614
@@ -562,6 +618,9 @@ def ipython_display(config, height=600, theme='auto', base_url=None, host_name=N
562618 routes = config .get_routes ()
563619 serve_routes (config , routes , use_port )
564620
621+ plugins = plugins or []
622+ plugin_esm = [p .plugin_esm for p in plugins ]
623+
565624 model_vals = {
566625 "uid" : uid_str ,
567626 "js_package_version" : js_package_version ,
0 commit comments