Skip to content

Commit

Permalink
wip implement dynamic navs
Browse files Browse the repository at this point in the history
  • Loading branch information
cpsievert committed Feb 18, 2022
1 parent 940ae7d commit 75581bd
Show file tree
Hide file tree
Showing 10 changed files with 639 additions and 806 deletions.
1 change: 1 addition & 0 deletions shiny/ui/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
from ._insert import *
from ._modal import *
from ._navs import *
from ._navs_dynamic import *
from ._notification import *
from ._output import *
from ._page import *
Expand Down
3 changes: 2 additions & 1 deletion shiny/ui/_navs.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@

from .._docstring import add_example
from ._html_dependencies import nav_deps
from .._utils import drop_none


@add_example()
Expand Down Expand Up @@ -672,4 +673,4 @@ def navs_bar(

def _nav_tag(name: str, *args: TagChildArg, **kwargs: JSXTagAttrArg) -> JSXTag:
tag = jsx_tag_create("bslib." + name)
return tag(nav_deps(), *args, **kwargs)
return tag(nav_deps(), *args, **drop_none(kwargs))
173 changes: 173 additions & 0 deletions shiny/ui/_navs_dynamic.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
__all__ = (
"nav_append",
"nav_prepend",
"nav_insert",
"nav_remove",
"nav_hide",
"nav_show",
)

import sys
from typing import Optional

if sys.version_info >= (3, 8):
from typing import Literal
else:
from typing_extensions import Literal

from htmltools import JSXTag

from ._input_update import update_navs
from ._navs import navs_hidden
from ..session import Session, require_active_session
from .._utils import run_coro_sync


def nav_append(
id: str,
nav: JSXTag,
menu_title: Optional[str] = None,
select: bool = False,
session: Optional[Session] = None,
) -> None:

session = require_active_session(session)
# TODO: do we need to namespace the id?
# id = session.ns(id)

# The currrent JSX implementation of nav items is not smart enough to
# to render without a navs container (maybe it could?), so we need to
# wrap in one and also notify the JSX logic to not select the nav
# (shiny.js handles that part via the select parameter).
jsx_tag = navs_hidden(nav, selected=False)

msg = {
"inputId": id,
"menuName": menu_title,
"target": None,
"position": "after",
"select": select,
"jsxTag": session.process_ui(jsx_tag),
}

def callback() -> None:
run_coro_sync(session.send_message({"shiny-insert-tab": msg}))

session.on_flush(callback, once=True)


def nav_prepend(
id: str,
nav: JSXTag,
menu_title: Optional[str] = None,
select: bool = False,
session: Optional[Session] = None,
) -> None:

session = require_active_session(session)
# TODO: do we need to namespace the id?
# id = session.ns(id)

# The currrent JSX implementation of nav items is not smart enough to
# to render without a navs container (maybe it could?), so we need to
# wrap in one and also notify the JSX logic to not select the nav
# (shiny.js handles that part via the select parameter).
jsx_tag = navs_hidden(nav, selected=False)

msg = {
"inputId": id,
"menuName": menu_title,
"target": None,
"position": "before",
"select": select,
"jsxTag": session.process_ui(jsx_tag),
}

def callback() -> None:
run_coro_sync(session.send_message({"shiny-insert-tab": msg}))

session.on_flush(callback, once=True)


def nav_insert(
id: str,
nav: JSXTag,
target: Optional[str] = None,
position: Literal["after", "before"] = "after",
select: bool = False,
session: Optional[Session] = None,
) -> None:

session = require_active_session(session)
# TODO: do we need to namespace the id?
# id = session.ns(id)

# The currrent JSX implementation of nav items is not smart enough to
# to render without a navs container (maybe it could?), so we need to
# wrap in one and also notify the JSX logic to not select the nav
# (shiny.js handles that part via the select parameter).
jsx_tag = navs_hidden(nav, selected=False)

msg = {
"inputId": id,
"menuName": None,
"target": target,
"position": position,
"select": select,
"jsxTag": session.process_ui(jsx_tag),
}

def callback() -> None:
run_coro_sync(session.send_message({"shiny-insert-tab": msg}))

session.on_flush(callback, once=True)


def nav_remove(id: str, target: str, session: Optional[Session] = None) -> None:

session = require_active_session(session)
# TODO: do we need to namespace the id?
# id = session.ns(id)

msg = {"inputId": id, "target": target}

def callback() -> None:
run_coro_sync(session.send_message({"shiny-remove-tab": msg}))

session.on_flush(callback, once=True)


def nav_hide(id: str, target: str, session: Optional[Session] = None) -> None:

session = require_active_session(session)
# TODO: do we need to namespace the id?
# id = session.ns(id)

msg = {"inputId": id, "target": target, "type": "hide"}

def callback() -> None:
run_coro_sync(session.send_message({"shiny-change-tab-visibility": msg}))

session.on_flush(callback, once=True)


def nav_show(
id: str, target: str, select: bool = False, session: Optional[Session] = None
) -> None:
"""
Show a nav
"""

session = require_active_session(session)

if select:
update_navs(id, selected=target)

# TODO: do we need to namespace the id?
# id = session.ns(id)
msg = {"inputId": id, "target": target, "type": "show"}

def callback() -> None:
run_coro_sync(session.send_message({"shiny-change-tab-visibility": msg}))

session.on_flush(callback, once=True)
2 changes: 1 addition & 1 deletion shiny/www/shared/bslib/dist/navs.min.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion shiny/www/shared/bslib/dist/navs.min.js.map

Large diffs are not rendered by default.

0 comments on commit 75581bd

Please sign in to comment.