streamlit-sortable-multiselect 0.7.2__tar.gz → 0.7.4__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.
Files changed (18) hide show
  1. {streamlit_sortable_multiselect-0.7.2/streamlit_sortable_multiselect.egg-info → streamlit_sortable_multiselect-0.7.4}/PKG-INFO +3 -1
  2. {streamlit_sortable_multiselect-0.7.2 → streamlit_sortable_multiselect-0.7.4}/README.md +2 -0
  3. {streamlit_sortable_multiselect-0.7.2 → streamlit_sortable_multiselect-0.7.4}/pyproject.toml +1 -1
  4. {streamlit_sortable_multiselect-0.7.2 → streamlit_sortable_multiselect-0.7.4}/streamlit_sortable_multiselect/__init__.py +34 -7
  5. streamlit_sortable_multiselect-0.7.4/streamlit_sortable_multiselect/frontend/build/assets/index-BxYP2Xl8.js +67 -0
  6. streamlit_sortable_multiselect-0.7.4/streamlit_sortable_multiselect/frontend/build/assets/index-DFEJzS1A.css +1 -0
  7. {streamlit_sortable_multiselect-0.7.2 → streamlit_sortable_multiselect-0.7.4}/streamlit_sortable_multiselect/frontend/build/index.html +2 -2
  8. {streamlit_sortable_multiselect-0.7.2 → streamlit_sortable_multiselect-0.7.4/streamlit_sortable_multiselect.egg-info}/PKG-INFO +3 -1
  9. {streamlit_sortable_multiselect-0.7.2 → streamlit_sortable_multiselect-0.7.4}/streamlit_sortable_multiselect.egg-info/SOURCES.txt +2 -2
  10. {streamlit_sortable_multiselect-0.7.2 → streamlit_sortable_multiselect-0.7.4}/tests/test_wrapper.py +6 -0
  11. streamlit_sortable_multiselect-0.7.2/streamlit_sortable_multiselect/frontend/build/assets/index-CaQVcw7i.css +0 -1
  12. streamlit_sortable_multiselect-0.7.2/streamlit_sortable_multiselect/frontend/build/assets/index-WpiGmimF.js +0 -67
  13. {streamlit_sortable_multiselect-0.7.2 → streamlit_sortable_multiselect-0.7.4}/LICENSE +0 -0
  14. {streamlit_sortable_multiselect-0.7.2 → streamlit_sortable_multiselect-0.7.4}/MANIFEST.in +0 -0
  15. {streamlit_sortable_multiselect-0.7.2 → streamlit_sortable_multiselect-0.7.4}/setup.cfg +0 -0
  16. {streamlit_sortable_multiselect-0.7.2 → streamlit_sortable_multiselect-0.7.4}/streamlit_sortable_multiselect.egg-info/dependency_links.txt +0 -0
  17. {streamlit_sortable_multiselect-0.7.2 → streamlit_sortable_multiselect-0.7.4}/streamlit_sortable_multiselect.egg-info/requires.txt +0 -0
  18. {streamlit_sortable_multiselect-0.7.2 → streamlit_sortable_multiselect-0.7.4}/streamlit_sortable_multiselect.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: streamlit-sortable-multiselect
3
- Version: 0.7.2
3
+ Version: 0.7.4
4
4
  Summary: A Streamlit custom component for selecting and reordering multiple string values.
5
5
  Author: Kentaro Aoki
6
6
  License-Expression: MIT
@@ -76,6 +76,7 @@ selected = sortable_multiselect(
76
76
  no_options_placeholder="All frameworks selected",
77
77
  selected_position="top",
78
78
  icon_size=24,
79
+ options_max_height=260,
79
80
  )
80
81
 
81
82
  st.write(selected)
@@ -102,6 +103,7 @@ st.write(selected)
102
103
  | `no_options_placeholder` | `str` | `"No more options"` | Placeholder shown when every option is already selected and there are no more options to add. |
103
104
  | `selected_position` | `str` | `"bottom"` | Position of the selected item list relative to the search/add input. Use `"bottom"` or `"top"`. |
104
105
  | `icon_size` | `int` | `20` | Icon display size in pixels for `icon_url` images. Images are displayed inside a square area while preserving their aspect ratio. |
106
+ | `options_max_height` | `int` | `190` | Maximum height in pixels for the available options dropdown. |
105
107
  | `key` | `str \| None` | `None` | Optional Streamlit component key. Use this when rendering multiple sortable multiselects. |
106
108
 
107
109
  Option dictionaries use this shape:
@@ -48,6 +48,7 @@ selected = sortable_multiselect(
48
48
  no_options_placeholder="All frameworks selected",
49
49
  selected_position="top",
50
50
  icon_size=24,
51
+ options_max_height=260,
51
52
  )
52
53
 
53
54
  st.write(selected)
@@ -74,6 +75,7 @@ st.write(selected)
74
75
  | `no_options_placeholder` | `str` | `"No more options"` | Placeholder shown when every option is already selected and there are no more options to add. |
75
76
  | `selected_position` | `str` | `"bottom"` | Position of the selected item list relative to the search/add input. Use `"bottom"` or `"top"`. |
76
77
  | `icon_size` | `int` | `20` | Icon display size in pixels for `icon_url` images. Images are displayed inside a square area while preserving their aspect ratio. |
78
+ | `options_max_height` | `int` | `190` | Maximum height in pixels for the available options dropdown. |
77
79
  | `key` | `str \| None` | `None` | Optional Streamlit component key. Use this when rendering multiple sortable multiselects. |
78
80
 
79
81
  Option dictionaries use this shape:
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "streamlit-sortable-multiselect"
7
- version = "0.7.2"
7
+ version = "0.7.4"
8
8
  description = "A Streamlit custom component for selecting and reordering multiple string values."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.9"
@@ -8,7 +8,7 @@ from typing import Any, Iterable, Mapping, Sequence, cast
8
8
 
9
9
  import streamlit.components.v1 as components
10
10
 
11
- __version__ = "0.7.2"
11
+ __version__ = "0.7.4"
12
12
  __all__ = ["sortable_multiselect"]
13
13
 
14
14
  _COMPONENT_NAME = "streamlit_sortable_multiselect"
@@ -103,6 +103,14 @@ def _validate_icon_size(icon_size: int) -> int:
103
103
  return icon_size
104
104
 
105
105
 
106
+ def _validate_options_max_height(options_max_height: int) -> int:
107
+ if isinstance(options_max_height, bool) or not isinstance(options_max_height, int):
108
+ raise TypeError("options_max_height must be an integer.")
109
+ if options_max_height < 1:
110
+ raise ValueError("options_max_height must be 1 or greater.")
111
+ return options_max_height
112
+
113
+
106
114
  def sortable_multiselect(
107
115
  label: str,
108
116
  options: Sequence[str | Mapping[str, Any]],
@@ -119,6 +127,7 @@ def sortable_multiselect(
119
127
  no_options_placeholder: str = "No more options",
120
128
  selected_position: str = "bottom",
121
129
  icon_size: int = 20,
130
+ options_max_height: int = 190,
122
131
  key: str | None = None,
123
132
  ) -> list[str]:
124
133
  """Select multiple string values and return them in user-defined order.
@@ -155,6 +164,8 @@ def sortable_multiselect(
155
164
  Position of selected items relative to the select control. Use "bottom" or "top".
156
165
  icon_size:
157
166
  Icon display size in pixels. Images keep their aspect ratio within this square size.
167
+ options_max_height:
168
+ Maximum height in pixels for the available options dropdown.
158
169
  key:
159
170
  Optional Streamlit component key.
160
171
  """
@@ -187,18 +198,33 @@ def sortable_multiselect(
187
198
  order_color_values = _validate_order_colors(order_colors)
188
199
  max_selection_count = _validate_max_selections(max_selections)
189
200
  icon_size_value = _validate_icon_size(icon_size)
190
-
191
- duplicate_options = sorted({value for value in option_values if option_values.count(value) > 1})
192
- if duplicate_options:
201
+ options_max_height_value = _validate_options_max_height(options_max_height)
202
+
203
+ # Set membership keeps these checks O(n); list.count / `in list` here are
204
+ # O(n**2) and hang the rerun once options reaches tens of thousands.
205
+ seen_option_values: set[str] = set()
206
+ has_duplicate_options = False
207
+ for value in option_values:
208
+ if value in seen_option_values:
209
+ has_duplicate_options = True
210
+ break
211
+ seen_option_values.add(value)
212
+ if has_duplicate_options:
193
213
  raise ValueError("options must not contain duplicate values.")
194
214
 
195
- missing_defaults = [value for value in default_values if value not in option_values]
215
+ missing_defaults = [value for value in default_values if value not in seen_option_values]
196
216
  if missing_defaults:
197
217
  missing = ", ".join(repr(value) for value in missing_defaults)
198
218
  raise ValueError(f"default contains values not present in options: {missing}.")
199
219
 
200
- duplicate_defaults = sorted({value for value in default_values if default_values.count(value) > 1})
201
- if duplicate_defaults:
220
+ seen_default_values: set[str] = set()
221
+ has_duplicate_defaults = False
222
+ for value in default_values:
223
+ if value in seen_default_values:
224
+ has_duplicate_defaults = True
225
+ break
226
+ seen_default_values.add(value)
227
+ if has_duplicate_defaults:
202
228
  raise ValueError("default must not contain duplicate values.")
203
229
 
204
230
  if max_selection_count is not None and len(default_values) > max_selection_count:
@@ -220,6 +246,7 @@ def sortable_multiselect(
220
246
  no_options_placeholder=no_options_placeholder,
221
247
  selected_position=selected_position,
222
248
  icon_size=icon_size_value,
249
+ options_max_height=options_max_height_value,
223
250
  key=key,
224
251
  default=default_values,
225
252
  )