streamlit-plugins 0.7.16__tar.gz → 0.7.18__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of streamlit-plugins might be problematic. Click here for more details.

Files changed (114) hide show
  1. streamlit_plugins-0.7.18/MANIFEST.in +4 -0
  2. {streamlit_plugins-0.7.16/streamlit_plugins.egg-info → streamlit_plugins-0.7.18}/PKG-INFO +1 -1
  3. {streamlit_plugins-0.7.16 → streamlit_plugins-0.7.18}/streamlit_plugins/components/document_blocks/__init__.py +34 -12
  4. streamlit_plugins-0.7.18/streamlit_plugins/components/markdown_editor/__init__.py +206 -0
  5. streamlit_plugins-0.7.18/streamlit_plugins/components/navbar/__init__.py +11 -0
  6. streamlit_plugins-0.7.18/streamlit_plugins/components/navbar/pyproject.toml +36 -0
  7. {streamlit_plugins-0.7.16/streamlit_plugins/components/navbar → streamlit_plugins-0.7.18/streamlit_plugins/components/navbar/v1}/__init__.py +56 -30
  8. streamlit_plugins-0.7.18/streamlit_plugins/components/navbar/v1/frontend/build/asset-manifest.json +10 -0
  9. streamlit_plugins-0.7.18/streamlit_plugins/components/navbar/v1/frontend/build/index.html +1 -0
  10. streamlit_plugins-0.7.18/streamlit_plugins/components/navbar/v1/frontend/build/material-fonts.css +23 -0
  11. {streamlit_plugins-0.7.16/streamlit_plugins/components/navbar → streamlit_plugins-0.7.18/streamlit_plugins/components/navbar/v1}/frontend/build/st-styles.css +29 -29
  12. streamlit_plugins-0.7.18/streamlit_plugins/components/navbar/v1/frontend/build/static/js/main.8e1dc380.js +3 -0
  13. streamlit_plugins-0.7.18/streamlit_plugins/components/navbar/v1/frontend/build/static/js/main.8e1dc380.js.map +1 -0
  14. streamlit_plugins-0.7.18/streamlit_plugins/components/navbar/v2/__init__.py +684 -0
  15. streamlit_plugins-0.7.18/streamlit_plugins/components/navbar/v2/frontend/build/CrossOriginInterface.js +623 -0
  16. streamlit_plugins-0.7.18/streamlit_plugins/components/navbar/v2/frontend/build/bootstrap.min.css +7 -0
  17. streamlit_plugins-0.7.18/streamlit_plugins/components/navbar/v2/frontend/build/bootstrap.min.css.map +1 -0
  18. streamlit_plugins-0.7.18/streamlit_plugins/components/navbar/v2/frontend/build/index-_hash_.css +40 -0
  19. streamlit_plugins-0.7.18/streamlit_plugins/components/navbar/v2/frontend/build/index.html +24 -0
  20. streamlit_plugins-0.7.18/streamlit_plugins/components/navbar/v2/frontend/build/material.woff2 +0 -0
  21. streamlit_plugins-0.7.18/streamlit_plugins/components/navbar/v2/frontend/build/st-styles.css +411 -0
  22. streamlit_plugins-0.7.18/streamlit_plugins/components/navbar/v2/frontend/build/style.css +536 -0
  23. streamlit_plugins-0.7.18/streamlit_plugins/components/navbar/v2/pyproject.toml +8 -0
  24. streamlit_plugins-0.7.18/streamlit_plugins/components/navbar/v2/utils.py +28 -0
  25. {streamlit_plugins-0.7.16 → streamlit_plugins-0.7.18}/streamlit_plugins/framework/multilit/multilit.py +8 -8
  26. {streamlit_plugins-0.7.16 → streamlit_plugins-0.7.18/streamlit_plugins.egg-info}/PKG-INFO +1 -1
  27. {streamlit_plugins-0.7.16 → streamlit_plugins-0.7.18}/streamlit_plugins.egg-info/SOURCES.txt +30 -14
  28. streamlit_plugins-0.7.16/streamlit_plugins/components/navbar/frontend/build/asset-manifest.json +0 -10
  29. streamlit_plugins-0.7.16/streamlit_plugins/components/navbar/frontend/build/index.html +0 -1
  30. streamlit_plugins-0.7.16/streamlit_plugins/components/navbar/frontend/build/static/js/main.8bc23bfa.js +0 -3
  31. streamlit_plugins-0.7.16/streamlit_plugins/components/navbar/frontend/build/static/js/main.8bc23bfa.js.map +0 -1
  32. {streamlit_plugins-0.7.16 → streamlit_plugins-0.7.18}/LICENSE +0 -0
  33. {streamlit_plugins-0.7.16 → streamlit_plugins-0.7.18}/README.md +0 -0
  34. {streamlit_plugins-0.7.16 → streamlit_plugins-0.7.18}/setup.cfg +0 -0
  35. {streamlit_plugins-0.7.16 → streamlit_plugins-0.7.18}/setup.py +0 -0
  36. {streamlit_plugins-0.7.16 → streamlit_plugins-0.7.18}/streamlit_plugins/__init__.py +0 -0
  37. {streamlit_plugins-0.7.16 → streamlit_plugins-0.7.18}/streamlit_plugins/components/__init__.py +0 -0
  38. {streamlit_plugins-0.7.16 → streamlit_plugins-0.7.18}/streamlit_plugins/components/annotated_text/__init__.py +0 -0
  39. {streamlit_plugins-0.7.16 → streamlit_plugins-0.7.18}/streamlit_plugins/components/input_chat_advance/__init__.py +0 -0
  40. {streamlit_plugins-0.7.16 → streamlit_plugins-0.7.18}/streamlit_plugins/components/label_studio/__init__.py +0 -0
  41. {streamlit_plugins-0.7.16 → streamlit_plugins-0.7.18}/streamlit_plugins/components/label_studio/frontend/build/asset-manifest.json +0 -0
  42. {streamlit_plugins-0.7.16 → streamlit_plugins-0.7.18}/streamlit_plugins/components/label_studio/frontend/build/bootstrap.min.css +0 -0
  43. {streamlit_plugins-0.7.16 → streamlit_plugins-0.7.18}/streamlit_plugins/components/label_studio/frontend/build/custom.css +0 -0
  44. {streamlit_plugins-0.7.16 → streamlit_plugins-0.7.18}/streamlit_plugins/components/label_studio/frontend/build/index.html +0 -0
  45. {streamlit_plugins-0.7.16 → streamlit_plugins-0.7.18}/streamlit_plugins/components/label_studio/frontend/build/static/css/2.4f758a59.chunk.css +0 -0
  46. {streamlit_plugins-0.7.16 → streamlit_plugins-0.7.18}/streamlit_plugins/components/label_studio/frontend/build/static/css/2.4f758a59.chunk.css.map +0 -0
  47. {streamlit_plugins-0.7.16 → streamlit_plugins-0.7.18}/streamlit_plugins/components/label_studio/frontend/build/static/js/2.524324ba.chunk.js +0 -0
  48. {streamlit_plugins-0.7.16 → streamlit_plugins-0.7.18}/streamlit_plugins/components/label_studio/frontend/build/static/js/2.524324ba.chunk.js.LICENSE.txt +0 -0
  49. {streamlit_plugins-0.7.16 → streamlit_plugins-0.7.18}/streamlit_plugins/components/label_studio/frontend/build/static/js/2.524324ba.chunk.js.map +0 -0
  50. {streamlit_plugins-0.7.16 → streamlit_plugins-0.7.18}/streamlit_plugins/components/label_studio/frontend/build/static/js/main.34b82d10.chunk.js +0 -0
  51. {streamlit_plugins-0.7.16 → streamlit_plugins-0.7.18}/streamlit_plugins/components/label_studio/frontend/build/static/js/main.34b82d10.chunk.js.map +0 -0
  52. {streamlit_plugins-0.7.16 → streamlit_plugins-0.7.18}/streamlit_plugins/components/label_studio/frontend/build/static/js/runtime-main.65660c44.js +0 -0
  53. {streamlit_plugins-0.7.16 → streamlit_plugins-0.7.18}/streamlit_plugins/components/label_studio/frontend/build/static/js/runtime-main.65660c44.js.map +0 -0
  54. {streamlit_plugins-0.7.16 → streamlit_plugins-0.7.18}/streamlit_plugins/components/loader/__init__.py +0 -0
  55. {streamlit_plugins-0.7.16/streamlit_plugins/components/navbar → streamlit_plugins-0.7.18/streamlit_plugins/components/navbar/v1}/config.py +0 -0
  56. {streamlit_plugins-0.7.16/streamlit_plugins/components/navbar → streamlit_plugins-0.7.18/streamlit_plugins/components/navbar/v1}/frontend/build/CrossOriginInterface.js +0 -0
  57. {streamlit_plugins-0.7.16/streamlit_plugins/components/navbar → streamlit_plugins-0.7.18/streamlit_plugins/components/navbar/v1}/frontend/build/bootstrap.min.css +0 -0
  58. {streamlit_plugins-0.7.16/streamlit_plugins/components/navbar → streamlit_plugins-0.7.18/streamlit_plugins/components/navbar/v1}/frontend/build/bootstrap.min.css.map +0 -0
  59. {streamlit_plugins-0.7.16/streamlit_plugins/components/navbar → streamlit_plugins-0.7.18/streamlit_plugins/components/navbar/v1}/frontend/build/material.woff2 +0 -0
  60. /streamlit_plugins-0.7.16/streamlit_plugins/components/navbar/frontend/build/static/js/main.8bc23bfa.js.LICENSE.txt → /streamlit_plugins-0.7.18/streamlit_plugins/components/navbar/v1/frontend/build/static/js/main.8e1dc380.js.LICENSE.txt +0 -0
  61. {streamlit_plugins-0.7.16/streamlit_plugins/components/navbar → streamlit_plugins-0.7.18/streamlit_plugins/components/navbar/v1}/frontend/build/style.css +0 -0
  62. {streamlit_plugins-0.7.16/streamlit_plugins/components/navbar → streamlit_plugins-0.7.18/streamlit_plugins/components/navbar/v1}/inject_script.py +0 -0
  63. {streamlit_plugins-0.7.16/streamlit_plugins/components/navbar → streamlit_plugins-0.7.18/streamlit_plugins/components/navbar/v2}/frontend/build/material-fonts.css +0 -0
  64. {streamlit_plugins-0.7.16 → streamlit_plugins-0.7.18}/streamlit_plugins/components/sankey_input/__init__.py +0 -0
  65. {streamlit_plugins-0.7.16 → streamlit_plugins-0.7.18}/streamlit_plugins/components/selectbox_enrich/__init__.py +0 -0
  66. {streamlit_plugins-0.7.16 → streamlit_plugins-0.7.18}/streamlit_plugins/components/skeleton/__init__.py +0 -0
  67. {streamlit_plugins-0.7.16 → streamlit_plugins-0.7.18}/streamlit_plugins/components/skeleton/template_builder.py +0 -0
  68. {streamlit_plugins-0.7.16 → streamlit_plugins-0.7.18}/streamlit_plugins/components/snakeviz/__init__.py +0 -0
  69. {streamlit_plugins-0.7.16 → streamlit_plugins-0.7.18}/streamlit_plugins/components/snakeviz/frontend/build/asset-manifest.json +0 -0
  70. {streamlit_plugins-0.7.16 → streamlit_plugins-0.7.18}/streamlit_plugins/components/snakeviz/frontend/build/index.html +0 -0
  71. {streamlit_plugins-0.7.16 → streamlit_plugins-0.7.18}/streamlit_plugins/components/snakeviz/frontend/build/static/drawsvg.js +0 -0
  72. {streamlit_plugins-0.7.16 → streamlit_plugins-0.7.18}/streamlit_plugins/components/snakeviz/frontend/build/static/drawsvg.v7.js +0 -0
  73. {streamlit_plugins-0.7.16 → streamlit_plugins-0.7.18}/streamlit_plugins/components/snakeviz/frontend/build/static/favicon.ico +0 -0
  74. {streamlit_plugins-0.7.16 → streamlit_plugins-0.7.18}/streamlit_plugins/components/snakeviz/frontend/build/static/images/sort_asc.png +0 -0
  75. {streamlit_plugins-0.7.16 → streamlit_plugins-0.7.18}/streamlit_plugins/components/snakeviz/frontend/build/static/images/sort_both.png +0 -0
  76. {streamlit_plugins-0.7.16 → streamlit_plugins-0.7.18}/streamlit_plugins/components/snakeviz/frontend/build/static/images/sort_desc.png +0 -0
  77. {streamlit_plugins-0.7.16 → streamlit_plugins-0.7.18}/streamlit_plugins/components/snakeviz/frontend/build/static/js/2.9cedfdc4.chunk.js +0 -0
  78. {streamlit_plugins-0.7.16 → streamlit_plugins-0.7.18}/streamlit_plugins/components/snakeviz/frontend/build/static/js/2.9cedfdc4.chunk.js.LICENSE.txt +0 -0
  79. {streamlit_plugins-0.7.16 → streamlit_plugins-0.7.18}/streamlit_plugins/components/snakeviz/frontend/build/static/js/2.9cedfdc4.chunk.js.map +0 -0
  80. {streamlit_plugins-0.7.16 → streamlit_plugins-0.7.18}/streamlit_plugins/components/snakeviz/frontend/build/static/js/main.1dfd8582.chunk.js +0 -0
  81. {streamlit_plugins-0.7.16 → streamlit_plugins-0.7.18}/streamlit_plugins/components/snakeviz/frontend/build/static/js/main.1dfd8582.chunk.js.map +0 -0
  82. {streamlit_plugins-0.7.16 → streamlit_plugins-0.7.18}/streamlit_plugins/components/snakeviz/frontend/build/static/js/runtime-main.8efd821a.js +0 -0
  83. {streamlit_plugins-0.7.16 → streamlit_plugins-0.7.18}/streamlit_plugins/components/snakeviz/frontend/build/static/js/runtime-main.8efd821a.js.map +0 -0
  84. {streamlit_plugins-0.7.16 → streamlit_plugins-0.7.18}/streamlit_plugins/components/snakeviz/frontend/build/static/snakeviz.css +0 -0
  85. {streamlit_plugins-0.7.16 → streamlit_plugins-0.7.18}/streamlit_plugins/components/snakeviz/frontend/build/static/snakeviz.js +0 -0
  86. {streamlit_plugins-0.7.16 → streamlit_plugins-0.7.18}/streamlit_plugins/components/snakeviz/frontend/build/static/vendor/d3.v3.min.js +0 -0
  87. {streamlit_plugins-0.7.16 → streamlit_plugins-0.7.18}/streamlit_plugins/components/snakeviz/frontend/build/static/vendor/immutable.min.js +0 -0
  88. {streamlit_plugins-0.7.16 → streamlit_plugins-0.7.18}/streamlit_plugins/components/snakeviz/frontend/build/static/vendor/jquery-3.2.1.min.js +0 -0
  89. {streamlit_plugins-0.7.16 → streamlit_plugins-0.7.18}/streamlit_plugins/components/snakeviz/frontend/build/static/vendor/jquery.dataTables.min.css +0 -0
  90. {streamlit_plugins-0.7.16 → streamlit_plugins-0.7.18}/streamlit_plugins/components/snakeviz/frontend/build/static/vendor/jquery.dataTables.min.js +0 -0
  91. {streamlit_plugins-0.7.16 → streamlit_plugins-0.7.18}/streamlit_plugins/components/snakeviz/frontend/build/static/vendor/lodash.min.js +0 -0
  92. {streamlit_plugins-0.7.16 → streamlit_plugins-0.7.18}/streamlit_plugins/components/snakeviz/frontend/build/templates/dir.html +0 -0
  93. {streamlit_plugins-0.7.16 → streamlit_plugins-0.7.18}/streamlit_plugins/components/snakeviz/frontend/build/templates/viz.html +0 -0
  94. {streamlit_plugins-0.7.16 → streamlit_plugins-0.7.18}/streamlit_plugins/components/theme_changer/__init__.py +0 -0
  95. {streamlit_plugins-0.7.16 → streamlit_plugins-0.7.18}/streamlit_plugins/components/theme_changer/config.py +0 -0
  96. {streamlit_plugins-0.7.16 → streamlit_plugins-0.7.18}/streamlit_plugins/components/theme_changer/entity.py +0 -0
  97. {streamlit_plugins-0.7.16 → streamlit_plugins-0.7.18}/streamlit_plugins/components/theme_changer/frontend/build/CrossOriginInterface.js +0 -0
  98. {streamlit_plugins-0.7.16 → streamlit_plugins-0.7.18}/streamlit_plugins/components/theme_changer/inject_script.py +0 -0
  99. {streamlit_plugins-0.7.16 → streamlit_plugins-0.7.18}/streamlit_plugins/extension/__init__.py +0 -0
  100. {streamlit_plugins-0.7.16 → streamlit_plugins-0.7.18}/streamlit_plugins/extension/button_group/__init__.py +0 -0
  101. {streamlit_plugins-0.7.16 → streamlit_plugins-0.7.18}/streamlit_plugins/extension/dynamic_container/__init__.py +0 -0
  102. {streamlit_plugins-0.7.16 → streamlit_plugins-0.7.18}/streamlit_plugins/framework/__init__.py +0 -0
  103. {streamlit_plugins-0.7.16 → streamlit_plugins-0.7.18}/streamlit_plugins/framework/multilit/__init__.py +0 -0
  104. {streamlit_plugins-0.7.16 → streamlit_plugins-0.7.18}/streamlit_plugins/framework/multilit/app_wrapper.py +0 -0
  105. {streamlit_plugins-0.7.16 → streamlit_plugins-0.7.18}/streamlit_plugins/framework/multilit/loading_engine.py +0 -0
  106. {streamlit_plugins-0.7.16 → streamlit_plugins-0.7.18}/streamlit_plugins/framework/reactlit/__init__.py +0 -0
  107. {streamlit_plugins-0.7.16 → streamlit_plugins-0.7.18}/streamlit_plugins/framework/reactlit/advanced_patterns.py +0 -0
  108. {streamlit_plugins-0.7.16 → streamlit_plugins-0.7.18}/streamlit_plugins/framework/reactlit/lab.py +0 -0
  109. {streamlit_plugins-0.7.16 → streamlit_plugins-0.7.18}/streamlit_plugins/framework/reactlit/reactive.py +0 -0
  110. {streamlit_plugins-0.7.16 → streamlit_plugins-0.7.18}/streamlit_plugins/framework/reactlit/reactlit.py +0 -0
  111. {streamlit_plugins-0.7.16 → streamlit_plugins-0.7.18}/streamlit_plugins/framework/reactlit/test_reactive.py +0 -0
  112. {streamlit_plugins-0.7.16 → streamlit_plugins-0.7.18}/streamlit_plugins.egg-info/dependency_links.txt +0 -0
  113. {streamlit_plugins-0.7.16 → streamlit_plugins-0.7.18}/streamlit_plugins.egg-info/requires.txt +0 -0
  114. {streamlit_plugins-0.7.16 → streamlit_plugins-0.7.18}/streamlit_plugins.egg-info/top_level.txt +0 -0
@@ -0,0 +1,4 @@
1
+ recursive-include streamlit_plugins/components/navbar/v1/frontend/build *
2
+ recursive-include streamlit_plugins/components/navbar/v2/frontend/build *
3
+ include streamlit_plugins/components/navbar/pyproject.toml
4
+ include streamlit_plugins/components/navbar/v2/pyproject.toml
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: streamlit-plugins
3
- Version: 0.7.16
3
+ Version: 0.7.18
4
4
  Summary: Components and Frameworks to give new features to streamlit
5
5
  Home-page: https://github.com/quiradev/streamlit-plugins
6
6
  Author: Victor Quilon Ranera
@@ -64,7 +64,7 @@ __CSS = """
64
64
  flex: 1;
65
65
  max-width: 550px;
66
66
  background: #fff;
67
- padding: 10px;
67
+ padding: 0;
68
68
  border-radius: 8px;
69
69
  box-shadow: 0 4px 12px rgba(0,0,0,0.1);
70
70
  }
@@ -952,8 +952,31 @@ def st_documents_blocks_info(
952
952
  tab_order: Optional[list[Literal["Blocks", "JSON", "HTML", "Markdown"] | str]] = None,
953
953
  custom_tabs: Optional[list[str]] = None,
954
954
  format_raw_code: bool = False,
955
+ set_state_on: Literal["hover", "click"] = "hover",
956
+ right_col_width: int | str = "100%",
955
957
  ) -> Generator[tuple[list[dict], list[TabContainer]], Any, None]:
956
- main_container = st.container(horizontal=True)
958
+ st.write(
959
+ f"""
960
+ <style>
961
+ .st-key-documents_blocks_container {{
962
+ display: flex;
963
+ flex-direction: row;
964
+ flex-wrap: nowrap;
965
+ }}
966
+ .st-key-documents_blocks_container > div:first-child {{
967
+ flex: 0 0 fit-content;
968
+ }}
969
+ .st-key-documents_blocks_container > div:last-child {{
970
+ width: {right_col_width};
971
+ flex: 1 1 auto;
972
+ max-width: 100%;
973
+ overflow: auto;
974
+ }}
975
+ </style>
976
+ """,
977
+ unsafe_allow_html=True
978
+ )
979
+ main_container = st.container(horizontal=True, key="documents_blocks_container", gap="xxsmall")
957
980
  page_selected = 1
958
981
  if document.pages > 1:
959
982
  with st.container(horizontal_alignment="right"):
@@ -988,7 +1011,7 @@ def st_documents_blocks_info(
988
1011
  reading_order=reading_order,
989
1012
  custom_styles=custom_styles,
990
1013
  default_selected=dynamic_selected_block_id,
991
- set_state_on="hover",
1014
+ set_state_on=set_state_on,
992
1015
  width="content",
993
1016
  height=600,
994
1017
  key="document_blocks"
@@ -1135,22 +1158,21 @@ def st_documents_blocks_info(
1135
1158
  elif json_col and json_col.open:
1136
1159
  with json_col:
1137
1160
  with st_dynamic_container(
1138
- container_source_key="document_blocks",
1139
- key="view-container", mimic_vertical=True, border=True
1161
+ container_source_key="document_blocks",
1162
+ key="view-container", border=True
1140
1163
  ):
1141
1164
  st.json(blocks_page)
1142
1165
 
1143
1166
  elif html_col and html_col.open:
1144
1167
  with html_col:
1145
- render_col, raw_col = st.tabs(
1146
- ["Renderer", "Raw"],
1147
- on_change=on_tab_change
1148
- )
1149
1168
  with st_dynamic_container(
1150
1169
  container_source_key="document_blocks",
1151
- key="view-container", mimic_vertical=True, border=True
1170
+ key="view-container", border=True
1152
1171
  ):
1153
-
1172
+ render_col, raw_col = st.tabs(
1173
+ ["Renderer", "Raw"],
1174
+ on_change=on_tab_change
1175
+ )
1154
1176
  html_content = _concat_content(blocks_normalized, content_type="html", parent_content_has_children=parent_content_has_children)
1155
1177
  if not html_content:
1156
1178
  st.warning("HTML content is empty. Please ensure that the blocks contain valid HTML content.")
@@ -1167,7 +1189,7 @@ def st_documents_blocks_info(
1167
1189
  with markdown_col:
1168
1190
  with st_dynamic_container(
1169
1191
  container_source_key="document_blocks",
1170
- key="view-container", mimic_vertical=True, border=True
1192
+ key="view-container", border=True
1171
1193
  ):
1172
1194
  render_col, raw_col = st.tabs(
1173
1195
  ["Renderer", "Raw"],
@@ -0,0 +1,206 @@
1
+ from collections.abc import Mapping, Sequence
2
+ from pathlib import Path
3
+ from typing import Any
4
+
5
+ from streamlit.components.v2 import component as create_component
6
+ from streamlit.elements.lib.layout_utils import Height
7
+
8
+ _ASSET_DIR = Path(__file__).with_name("frontend")
9
+
10
+
11
+ def _normalize_blocks(
12
+ blocks: Sequence[Mapping[str, Any]], *, for_review: bool = False
13
+ ) -> list[dict[str, str]]:
14
+ normalized: list[dict[str, str]] = []
15
+ seen_ids: set[str] = set()
16
+ for index, block in enumerate(blocks):
17
+ if not isinstance(block, Mapping):
18
+ raise TypeError(f"El bloque {index} debe ser un mapping")
19
+ markdown = block.get("markdown", block.get("text"))
20
+ if not isinstance(markdown, str):
21
+ raise TypeError(f"El bloque {index} debe incluir markdown de tipo str")
22
+ block_id = block.get("id") if for_review else block.get("id", f"block-{index}")
23
+ block_id = str(block_id) if block_id is not None or not for_review else None
24
+ if block_id is not None and block_id in seen_ids:
25
+ raise ValueError(f"ID de bloque duplicado: {block_id}")
26
+ item = {"markdown": markdown}
27
+ if block_id is not None:
28
+ seen_ids.add(block_id)
29
+ item["id"] = block_id
30
+ normalized.append(item)
31
+ if not normalized and not for_review:
32
+ normalized.append({"id": "block-0", "markdown": ""})
33
+ return normalized
34
+
35
+
36
+ def _normalize_diff(diff: Mapping[str, Any] | None) -> dict[str, Any] | None:
37
+ if diff is None:
38
+ return None
39
+ if not isinstance(diff, Mapping):
40
+ raise TypeError("diff debe ser un mapping con before y after o sus bloques")
41
+ has_blocks = "before_blocks" in diff or "after_blocks" in diff
42
+ if has_blocks and not ("before_blocks" in diff and "after_blocks" in diff):
43
+ raise ValueError("diff debe incluir before_blocks y after_blocks juntos")
44
+ normalized: dict[str, Any] = {}
45
+ for version in ("before", "after"):
46
+ source = diff.get(version)
47
+ if has_blocks:
48
+ blocks = diff[f"{version}_blocks"]
49
+ if not isinstance(blocks, Sequence) or isinstance(blocks, (str, bytes)):
50
+ raise TypeError(f"{version}_blocks debe ser una secuencia de bloques")
51
+ blocks = _normalize_blocks(blocks, for_review=True)
52
+ normalized[f"{version}_blocks"] = blocks
53
+ markdown = "\n\n".join(block["markdown"] for block in blocks)
54
+ if source is None:
55
+ source = markdown
56
+ elif source != markdown:
57
+ raise ValueError(f"{version} debe coincidir con el Markdown de {version}_blocks")
58
+ if not isinstance(source, str):
59
+ raise ValueError("diff debe incluir before y after de tipo str o sus bloques")
60
+ normalized[version] = source
61
+ return normalized
62
+
63
+
64
+ def _document_from_state(
65
+ state: Any,
66
+ initial_blocks: list[dict[str, str]],
67
+ *,
68
+ mode: str,
69
+ save_mode: str,
70
+ ) -> dict[str, Any]:
71
+ if state is None:
72
+ blocks = initial_blocks
73
+ return {
74
+ "blocks": blocks,
75
+ "markdown": "\n\n".join(block["markdown"] for block in blocks),
76
+ "mode": mode,
77
+ "save_mode": save_mode,
78
+ }
79
+ if not isinstance(state, Mapping):
80
+ raise TypeError("El estado devuelto por el editor debe ser un mapping")
81
+ state_blocks = state.get("blocks")
82
+ state_markdown = state.get("markdown")
83
+ if not isinstance(state_blocks, list) or not isinstance(state_markdown, str):
84
+ raise ValueError("El editor devolvió un estado incompleto")
85
+ state_mode = state.get("mode", mode)
86
+ if state_mode not in {"raw_visual", "visual"}:
87
+ raise ValueError("El editor devolvió un modo desconocido")
88
+ return {
89
+ "blocks": state_blocks,
90
+ "markdown": state_markdown,
91
+ "mode": state_mode,
92
+ "save_mode": save_mode,
93
+ }
94
+
95
+
96
+ def st_markdown_block_editor(
97
+ initial_blocks: Sequence[Mapping[str, Any]],
98
+ *,
99
+ key: str,
100
+ revision: int = 0,
101
+ height: Height | None = "stretch",
102
+ mode: str = "raw_visual",
103
+ save_mode: str = "auto",
104
+ only_view: bool = False,
105
+ debug_blocks: bool = False,
106
+ diff: Mapping[str, Any] | None = None,
107
+ editor_modes: Sequence[str] = ("raw_visual", "visual"),
108
+ review_modes: Sequence[str] = ("visual", "markdown"),
109
+ review_layouts: Sequence[str] = ("before", "after", "split", "blocks"),
110
+ block_diff_style: str = "content",
111
+ placeholder: str = "Escribe aquí…",
112
+ show_copy_button: bool = True,
113
+ toolbar_sections: Sequence[str] = ("view", "format", "block", "history", "changes"),
114
+ ) -> dict[str, Any]:
115
+ """Edit Markdown blocks or review visual, source and block-level changes.
116
+
117
+ With button saving, review compares the saved document with the local draft.
118
+ External diffs accept before/after strings or paired before_blocks/after_blocks.
119
+ Stable block IDs improve movement and content-change identification.
120
+ toolbar_sections controls header visibility, not editing permissions.
121
+ """
122
+ if not key:
123
+ raise ValueError("key no puede estar vacía")
124
+ if revision < 0:
125
+ raise ValueError("revision no puede ser negativa")
126
+ if height is not None and (isinstance(height, bool) or not isinstance(height, (int, str))):
127
+ raise TypeError("height debe ser un entero, 'stretch', 'content' o None")
128
+ if isinstance(height, int) and height < 240:
129
+ raise ValueError("height debe ser al menos 240 px")
130
+ if isinstance(height, str) and height not in {"stretch", "content"}:
131
+ raise ValueError("height debe ser 'stretch' o 'content'")
132
+ if mode not in {"raw_visual", "visual"}:
133
+ raise ValueError("mode debe ser 'raw_visual' o 'visual'")
134
+ if save_mode not in {"auto", "button"}:
135
+ raise ValueError("save_mode debe ser 'auto' o 'button'")
136
+ if not isinstance(only_view, bool):
137
+ raise TypeError("only_view debe ser bool")
138
+ if not isinstance(debug_blocks, bool):
139
+ raise TypeError("debug_blocks debe ser bool")
140
+ choices = {
141
+ "editor_modes": (editor_modes, {"raw_visual", "visual"}, True),
142
+ "review_modes": (review_modes, {"visual", "markdown"}, True),
143
+ "review_layouts": (review_layouts, {"before", "after", "split", "blocks"}, True),
144
+ "toolbar_sections": (toolbar_sections, {"view", "format", "block", "history", "changes"}, False),
145
+ }
146
+ for name, (values, allowed, required) in choices.items():
147
+ if not isinstance(values, Sequence) or isinstance(values, (str, bytes)):
148
+ raise TypeError(f"{name} debe ser una secuencia de opciones")
149
+ if (required and not values) or any(not isinstance(value, str) or value not in allowed for value in values):
150
+ raise ValueError(f"{name}: opciones válidas {sorted(allowed)}" + ("; elige al menos una" if required else ""))
151
+ if len(set(values)) != len(values):
152
+ raise ValueError(f"{name} no puede incluir opciones duplicadas")
153
+ if mode not in editor_modes:
154
+ raise ValueError("mode debe estar incluido en editor_modes")
155
+ if block_diff_style not in {"content", "inline"}:
156
+ raise ValueError("block_diff_style debe ser 'content' o 'inline'")
157
+ if not isinstance(placeholder, str):
158
+ raise TypeError("placeholder debe ser str")
159
+ if not isinstance(show_copy_button, bool):
160
+ raise TypeError("show_copy_button debe ser bool")
161
+ normalized_diff = _normalize_diff(diff)
162
+
163
+ blocks = _normalize_blocks(initial_blocks)
164
+ renderer_bundle = _ASSET_DIR / "renderers.bundle.js"
165
+ if not renderer_bundle.is_file():
166
+ raise RuntimeError(
167
+ "Falta el bundle de renderizadores: ejecuta npm install y npm run build "
168
+ "en isc\\markdown_editor\\frontend"
169
+ )
170
+ editor = create_component(
171
+ name="indra_markdown_block_editor",
172
+ html=(_ASSET_DIR / "editor.html").read_text(encoding="utf-8"),
173
+ css=(_ASSET_DIR / "editor.css").read_text(encoding="utf-8"),
174
+ js=(
175
+ renderer_bundle.read_text(encoding="utf-8")
176
+ + "\n"
177
+ + (_ASSET_DIR / "editor.js").read_text(encoding="utf-8")
178
+ ),
179
+ isolate_styles=False,
180
+ )
181
+ state = editor(
182
+ key=key,
183
+ data={
184
+ "blocks": blocks,
185
+ "revision": revision,
186
+ "mode": mode,
187
+ "save_mode": save_mode,
188
+ "only_view": only_view,
189
+ "debug_blocks": debug_blocks,
190
+ "height": height,
191
+ "diff": normalized_diff,
192
+ "editor_modes": list(editor_modes),
193
+ "review_modes": list(review_modes),
194
+ "review_layouts": list(review_layouts),
195
+ "block_diff_style": block_diff_style,
196
+ "placeholder": placeholder,
197
+ "show_copy_button": show_copy_button,
198
+ "toolbar_sections": list(toolbar_sections),
199
+ },
200
+ width="stretch",
201
+ height=height if height is not None else 760,
202
+ ).get("value")
203
+ return _document_from_state(state, blocks, mode=mode, save_mode=save_mode)
204
+
205
+
206
+ __all__ = ["st_markdown_block_editor"]
@@ -0,0 +1,11 @@
1
+ from importlib import import_module as _import_module
2
+ from typing import Any as _Any
3
+
4
+ from . import v1
5
+ from .v1 import *
6
+
7
+ st_navbar_v1 = v1.st_navbar
8
+
9
+
10
+ def st_navbar_v2(*args: _Any, **kwargs: _Any) -> str:
11
+ return _import_module(f"{__name__}.v2").st_navbar(*args, **kwargs)
@@ -0,0 +1,36 @@
1
+ [build-system]
2
+ requires = ["setuptools>=77.0.3", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "streamlit-component-navbar"
7
+ version = "0.7.17"
8
+ dynamic = ["dependencies"]
9
+ description = "Streamlit navbar component"
10
+ readme = "README.md"
11
+ requires-python = ">=3.10"
12
+
13
+ [[tool.streamlit.component.components]]
14
+ name = "nav_bar"
15
+ asset_dir = "v2/frontend/build"
16
+
17
+ [tool.setuptools]
18
+ package-dir = { "" = "../../../" }
19
+ include-package-data = true
20
+
21
+ [tool.setuptools.dynamic]
22
+ dependencies = { file = ["packaging/requirements.txt"] }
23
+
24
+ [tool.setuptools.packages.find]
25
+ where = ["../../../"]
26
+ include = [
27
+ "streamlit_plugins.extension",
28
+ "streamlit_plugins.extension.*",
29
+ "streamlit_plugins.components.navbar",
30
+ "streamlit_plugins.components.navbar.*",
31
+ ]
32
+
33
+ [tool.setuptools.package-data]
34
+ "streamlit_plugins.components.navbar" = ["pyproject.toml"]
35
+ "streamlit_plugins.components.navbar.v1" = ["frontend/build/**/*"]
36
+ "streamlit_plugins.components.navbar.v2" = ["frontend/build/**/*", "pyproject.toml"]
@@ -1,6 +1,6 @@
1
1
  import inspect
2
2
  import time
3
- from typing import Literal
3
+ from typing import Literal, Optional, cast
4
4
  import warnings
5
5
  import logging
6
6
  from urllib.parse import urlparse
@@ -624,6 +624,7 @@ def st_navbar(
624
624
  option_menu=False,
625
625
  default_page_selected_id=None,
626
626
  override_page_selected_id=None,
627
+ override_first_page_load_id=None,
627
628
  reclick_load=True,
628
629
  input_styles: str | None = None,
629
630
  themes_data: list[dict]| None = None,
@@ -633,7 +634,7 @@ def st_navbar(
633
634
  prefix_url: str = "",
634
635
  # url_navigation: bool = False,
635
636
  key="NavBarComponent",
636
- ):
637
+ ) -> str:
637
638
  if home_definition is None:
638
639
  home_definition = menu_definition.pop(0)
639
640
 
@@ -748,12 +749,13 @@ def st_navbar(
748
749
  st.session_state[f"{NAVBAR_KEY_PREFIX}_coi_instance"] = True
749
750
 
750
751
  with navbar_view:
751
- component_value = _component_func(
752
+ component_value: Optional[str] = _component_func(
752
753
  menu_definition=menu_definition, home=home_data or None, login=login_data or None,
753
754
  override_theme=override_theme,
754
755
  position_mode=position_mode, is_sticky=sticky_nav,
755
756
  default_page_selected_id=default_page_selected_id,
756
757
  override_page_selected_id=override_page_selected_id,
758
+ override_first_page_load_id=override_first_page_load_id,
757
759
  reclick_load=reclick_load,
758
760
  styles=styles, custom_styles=input_styles,
759
761
  is_navigation=is_navigation,
@@ -762,7 +764,7 @@ def st_navbar(
762
764
  collapsible=collapsible,
763
765
  prefix_url=prefix_url,
764
766
  # url_navigation=url_navigation and is_navigation,
765
- default=default_page_selected_id,
767
+ default=None,
766
768
  is_visible=True,
767
769
  key=key, fvalue=force_value,
768
770
  )
@@ -774,14 +776,17 @@ def st_navbar(
774
776
  # print(f"FROM Navbar: {component_value}")
775
777
 
776
778
  if component_value is None:
777
- component_value = default_page_selected_id
779
+ if not is_navigation:
780
+ component_value = default_page_selected_id
781
+ else:
782
+ component_value = override_first_page_load_id or default_page_selected_id
778
783
 
779
784
  if override_page_selected_id:
780
785
  component_value = override_page_selected_id
781
786
 
782
787
  # print(f"FROM Navbar FINAL: {component_value}")
783
788
  # print()
784
- return component_value
789
+ return cast(str, component_value)
785
790
 
786
791
  def st_which_page() -> str:
787
792
  return st.session_state[f"{NAVIGATION_KEY_PREFIX}_page_id"]
@@ -805,6 +810,9 @@ def st_navigation(
805
810
  page_id_key = f"{NAVIGATION_KEY_PREFIX}_page_id"
806
811
  force_page_id_key = f"{NAVIGATION_KEY_PREFIX}_force_page_id"
807
812
  history_key = f"{NAVIGATION_KEY_PREFIX}_history"
813
+ default_page_id_key = f"{NAVIGATION_KEY_PREFIX}_default_page_id"
814
+
815
+ first_load = False
808
816
 
809
817
  if prev_url_page_id_key not in st.session_state:
810
818
  st.session_state[prev_url_page_id_key] = None
@@ -814,6 +822,7 @@ def st_navigation(
814
822
 
815
823
  if page_id_key not in st.session_state:
816
824
  st.session_state[page_id_key] = None
825
+ first_load = True
817
826
 
818
827
  if force_page_id_key not in st.session_state:
819
828
  st.session_state[force_page_id_key] = None
@@ -903,7 +912,7 @@ def st_navigation(
903
912
 
904
913
  st.session_state[f"{NAVIGATION_KEY_PREFIX}_menu_pages"] = menu_pages
905
914
  st.session_state[f"{NAVIGATION_KEY_PREFIX}_menu_account_pages"] = menu_account_pages
906
- st.session_state[f"{NAVIGATION_KEY_PREFIX}_default_page_id"] = default_page._script_hash
915
+ st.session_state[default_page_id_key] = default_page._script_hash
907
916
 
908
917
  logout_page_id, login_page_id = None, None
909
918
  if login_page:
@@ -927,15 +936,34 @@ def st_navigation(
927
936
 
928
937
 
929
938
  if st.session_state[page_id_key] is None:
930
- st.session_state[page_id_key] = st.session_state[f"{NAVIGATION_KEY_PREFIX}_default_page_id"]
939
+ st.session_state[page_id_key] = st.session_state[default_page_id_key]
940
+
941
+ initial_force_page_id = st.session_state[force_page_id_key]
931
942
 
932
- next_page_id = st_navbar(
943
+ if native_way:
944
+ # Si la url es el path igual al que devuelve el `next_page_id` quiere decir que la navegacion es por url
945
+ # En este punto el navigation de streamlit siempre devolvera la pagina actual
946
+ # ya que no se usara su navegacion frontal para seleccionar una pagina
947
+ # if url_navigation:
948
+ url_page_id = get_page_id_by_url_path(
949
+ pages_map, st.context.url, prefix_url=prefix_url
950
+ )
951
+ # print("URL PAGE", pages_map[url_page_id].title)
952
+ if url_page_id != st.session_state[prev_url_page_id_key]:
953
+ # Navegacion por url
954
+ st.session_state[prev_url_page_id_key] = url_page_id
955
+ # Solo si es la primera pagina, no hay variables de estado previas o se ha limpiado
956
+ if first_load:
957
+ initial_force_page_id = url_page_id
958
+
959
+ navbar_page_id = st_navbar(
933
960
  menu_definition=menu_pages, # if st.session_state.logged_in else [],
934
961
  home_definition=home_definition,
935
962
  login_definition=menu_account_pages,
936
963
  hide_streamlit_markers=False,
937
- default_page_selected_id=st.session_state[page_id_key] or st.session_state[f"{NAVIGATION_KEY_PREFIX}_default_page_id"],
964
+ default_page_selected_id=st.session_state[page_id_key] or st.session_state[default_page_id_key],
938
965
  override_page_selected_id=st.session_state[force_page_id_key],
966
+ override_first_page_load_id=initial_force_page_id,
939
967
  position_mode=position_mode,
940
968
  sticky_nav=sticky_nav,
941
969
  input_styles=input_styles,
@@ -947,42 +975,40 @@ def st_navigation(
947
975
  hide_skeleton=True,
948
976
  )
949
977
  st.session_state[force_page_id_key] = None
950
- prev_page_id = st.session_state[page_id_key]
951
- st.session_state[page_id_key] = next_page_id # Added to fix login/logout issue
978
+ streamlit_page_id = st.session_state[page_id_key]
979
+ st.session_state[page_id_key] = navbar_page_id or initial_force_page_id # Added to fix login/logout issue
952
980
  # print("CUSTOM COMPONENT", pages_map[next_page_id].title)
953
981
  if native_way:
954
982
  # Si la url es el path igual al que devuelve el `next_page_id` quiere decir que la navegacion es por url
955
983
  # En este punto el navigation de streamlit siempre devolvera la pagina actual
956
984
  # ya que no se usara su navegacion frontal para seleccionar una pagina
957
985
  # if url_navigation:
958
- # url_page_id = get_page_id_by_url_path(
959
- # pages_map, st.context.url, prefix_url=prefix_url
960
- # )
961
- # # print("URL PAGE", pages_map[url_page_id].title)
962
- # if url_page_id != st.session_state[f"{NAVIGATION_KEY_PREFIX}_prev_url_page_id"]:
963
- # # Navegacion por url
964
- # # Give enough time to the custom component to update
965
- # time.sleep(0.1)
966
- # st.session_state[f"{NAVIGATION_KEY_PREFIX}_prev_url_page_id"] = url_page_id
967
- # next_page_id = url_page_id
986
+ url_page_id = get_page_id_by_url_path(
987
+ pages_map, st.context.url, prefix_url=prefix_url
988
+ )
989
+ # print("URL PAGE", pages_map[url_page_id].title)
990
+ if url_page_id != st.session_state[prev_url_page_id_key]:
991
+ # Navegacion por url
992
+ st.session_state[prev_url_page_id_key] = url_page_id
993
+ navbar_page_id = url_page_id
968
994
 
969
995
  page = st.navigation(
970
996
  st_pages,
971
997
  position="hidden"
972
998
  )
973
999
  # print("ST PAGE", page.title)
974
- prev_page_id = page._script_hash
1000
+ streamlit_page_id = page._script_hash
975
1001
  else:
976
- page = pages_map.get(next_page_id, default_page)
1002
+ page = pages_map.get(navbar_page_id, default_page)
977
1003
 
978
1004
  # print("PAGE", pages_map[next_page_id].title)
979
1005
 
980
- # Solo si se cambia de pagina
981
- if prev_page_id != next_page_id:
982
- st.session_state[page_id_key] = next_page_id
983
- if prev_page_id not in [logout_page_id, login_page_id]:
984
- st.session_state[prev_page_id_key] = prev_page_id
985
- st_switch_page(next_page_id, native_way=native_way)
1006
+ # Solo si se cambia de pagina desde el componente custom
1007
+ if streamlit_page_id != navbar_page_id:
1008
+ st.session_state[page_id_key] = navbar_page_id
1009
+ if streamlit_page_id not in [logout_page_id, login_page_id]:
1010
+ st.session_state[prev_page_id_key] = streamlit_page_id
1011
+ st_switch_page(navbar_page_id, native_way=native_way)
986
1012
 
987
1013
  page._can_be_called = True
988
1014
  add_page_to_history(page._script_hash)
@@ -0,0 +1,10 @@
1
+ {
2
+ "files": {
3
+ "main.js": "./static/js/main.8e1dc380.js",
4
+ "index.html": "./index.html",
5
+ "main.8e1dc380.js.map": "./static/js/main.8e1dc380.js.map"
6
+ },
7
+ "entrypoints": [
8
+ "static/js/main.8e1dc380.js"
9
+ ]
10
+ }
@@ -0,0 +1 @@
1
+ <!doctype html><html lang="en"><head><title>Streamlit Component NavBar</title><meta charset="UTF-8"/><meta name="viewport" content="width=device-width,initial-scale=1"/><meta name="theme-color" content="#000000"/><meta name="description" content="Streamlit Component NavBar"/><link rel="stylesheet" href="bootstrap.min.css"/><link rel="stylesheet" href="material-fonts.css"/><script defer="defer" src="static/js/main.8e1dc380.js"></script></head><body><link rel="stylesheet" href="style.css"/><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div></body></html>
@@ -0,0 +1,23 @@
1
+ /* fallback */
2
+ @font-face {
3
+ font-family: 'Material Symbols Rounded';
4
+ font-style: normal;
5
+ font-weight: 100 700;
6
+ src: url(material.woff2) format('woff2');
7
+ }
8
+
9
+ .material-symbols-rounded {
10
+ font-family: 'Material Symbols Rounded';
11
+ font-weight: normal;
12
+ font-style: normal;
13
+ font-size: 24px;
14
+ line-height: 1;
15
+ letter-spacing: normal;
16
+ text-transform: none;
17
+ display: inline-block;
18
+ white-space: nowrap;
19
+ word-wrap: normal;
20
+ direction: ltr;
21
+ -webkit-font-feature-settings: 'liga';
22
+ -webkit-font-smoothing: antialiased;
23
+ }