streamlit-sortable-multiselect 0.7.1__tar.gz → 0.7.2__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 (16) hide show
  1. {streamlit_sortable_multiselect-0.7.1/streamlit_sortable_multiselect.egg-info → streamlit_sortable_multiselect-0.7.2}/PKG-INFO +3 -1
  2. {streamlit_sortable_multiselect-0.7.1 → streamlit_sortable_multiselect-0.7.2}/README.md +2 -0
  3. {streamlit_sortable_multiselect-0.7.1 → streamlit_sortable_multiselect-0.7.2}/pyproject.toml +1 -1
  4. {streamlit_sortable_multiselect-0.7.1 → streamlit_sortable_multiselect-0.7.2}/streamlit_sortable_multiselect/__init__.py +14 -1
  5. streamlit_sortable_multiselect-0.7.1/streamlit_sortable_multiselect/frontend/build/assets/index-BKFJvHHF.css → streamlit_sortable_multiselect-0.7.2/streamlit_sortable_multiselect/frontend/build/assets/index-CaQVcw7i.css +1 -1
  6. streamlit_sortable_multiselect-0.7.1/streamlit_sortable_multiselect/frontend/build/assets/index-ACSWLoJh.js → streamlit_sortable_multiselect-0.7.2/streamlit_sortable_multiselect/frontend/build/assets/index-WpiGmimF.js +13 -13
  7. {streamlit_sortable_multiselect-0.7.1 → streamlit_sortable_multiselect-0.7.2}/streamlit_sortable_multiselect/frontend/build/index.html +2 -2
  8. {streamlit_sortable_multiselect-0.7.1 → streamlit_sortable_multiselect-0.7.2/streamlit_sortable_multiselect.egg-info}/PKG-INFO +3 -1
  9. {streamlit_sortable_multiselect-0.7.1 → streamlit_sortable_multiselect-0.7.2}/streamlit_sortable_multiselect.egg-info/SOURCES.txt +2 -2
  10. {streamlit_sortable_multiselect-0.7.1 → streamlit_sortable_multiselect-0.7.2}/tests/test_wrapper.py +6 -0
  11. {streamlit_sortable_multiselect-0.7.1 → streamlit_sortable_multiselect-0.7.2}/LICENSE +0 -0
  12. {streamlit_sortable_multiselect-0.7.1 → streamlit_sortable_multiselect-0.7.2}/MANIFEST.in +0 -0
  13. {streamlit_sortable_multiselect-0.7.1 → streamlit_sortable_multiselect-0.7.2}/setup.cfg +0 -0
  14. {streamlit_sortable_multiselect-0.7.1 → streamlit_sortable_multiselect-0.7.2}/streamlit_sortable_multiselect.egg-info/dependency_links.txt +0 -0
  15. {streamlit_sortable_multiselect-0.7.1 → streamlit_sortable_multiselect-0.7.2}/streamlit_sortable_multiselect.egg-info/requires.txt +0 -0
  16. {streamlit_sortable_multiselect-0.7.1 → streamlit_sortable_multiselect-0.7.2}/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.1
3
+ Version: 0.7.2
4
4
  Summary: A Streamlit custom component for selecting and reordering multiple string values.
5
5
  Author: Kentaro Aoki
6
6
  License-Expression: MIT
@@ -75,6 +75,7 @@ selected = sortable_multiselect(
75
75
  empty_message="No frameworks selected",
76
76
  no_options_placeholder="All frameworks selected",
77
77
  selected_position="top",
78
+ icon_size=24,
78
79
  )
79
80
 
80
81
  st.write(selected)
@@ -100,6 +101,7 @@ st.write(selected)
100
101
  | `empty_message` | `str` | `"No items selected"` | Message shown where the selected list appears when no items are selected. |
101
102
  | `no_options_placeholder` | `str` | `"No more options"` | Placeholder shown when every option is already selected and there are no more options to add. |
102
103
  | `selected_position` | `str` | `"bottom"` | Position of the selected item list relative to the search/add input. Use `"bottom"` or `"top"`. |
104
+ | `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. |
103
105
  | `key` | `str \| None` | `None` | Optional Streamlit component key. Use this when rendering multiple sortable multiselects. |
104
106
 
105
107
  Option dictionaries use this shape:
@@ -47,6 +47,7 @@ selected = sortable_multiselect(
47
47
  empty_message="No frameworks selected",
48
48
  no_options_placeholder="All frameworks selected",
49
49
  selected_position="top",
50
+ icon_size=24,
50
51
  )
51
52
 
52
53
  st.write(selected)
@@ -72,6 +73,7 @@ st.write(selected)
72
73
  | `empty_message` | `str` | `"No items selected"` | Message shown where the selected list appears when no items are selected. |
73
74
  | `no_options_placeholder` | `str` | `"No more options"` | Placeholder shown when every option is already selected and there are no more options to add. |
74
75
  | `selected_position` | `str` | `"bottom"` | Position of the selected item list relative to the search/add input. Use `"bottom"` or `"top"`. |
76
+ | `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. |
75
77
  | `key` | `str \| None` | `None` | Optional Streamlit component key. Use this when rendering multiple sortable multiselects. |
76
78
 
77
79
  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.1"
7
+ version = "0.7.2"
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.1"
11
+ __version__ = "0.7.2"
12
12
  __all__ = ["sortable_multiselect"]
13
13
 
14
14
  _COMPONENT_NAME = "streamlit_sortable_multiselect"
@@ -95,6 +95,14 @@ def _validate_max_selections(max_selections: int | None) -> int | None:
95
95
  return max_selections
96
96
 
97
97
 
98
+ def _validate_icon_size(icon_size: int) -> int:
99
+ if isinstance(icon_size, bool) or not isinstance(icon_size, int):
100
+ raise TypeError("icon_size must be an integer.")
101
+ if icon_size < 1:
102
+ raise ValueError("icon_size must be 1 or greater.")
103
+ return icon_size
104
+
105
+
98
106
  def sortable_multiselect(
99
107
  label: str,
100
108
  options: Sequence[str | Mapping[str, Any]],
@@ -110,6 +118,7 @@ def sortable_multiselect(
110
118
  empty_message: str = "No items selected",
111
119
  no_options_placeholder: str = "No more options",
112
120
  selected_position: str = "bottom",
121
+ icon_size: int = 20,
113
122
  key: str | None = None,
114
123
  ) -> list[str]:
115
124
  """Select multiple string values and return them in user-defined order.
@@ -144,6 +153,8 @@ def sortable_multiselect(
144
153
  Placeholder text shown when there are no more options to add.
145
154
  selected_position:
146
155
  Position of selected items relative to the select control. Use "bottom" or "top".
156
+ icon_size:
157
+ Icon display size in pixels. Images keep their aspect ratio within this square size.
147
158
  key:
148
159
  Optional Streamlit component key.
149
160
  """
@@ -175,6 +186,7 @@ def sortable_multiselect(
175
186
  default_values = _validate_string_sequence("default", default)
176
187
  order_color_values = _validate_order_colors(order_colors)
177
188
  max_selection_count = _validate_max_selections(max_selections)
189
+ icon_size_value = _validate_icon_size(icon_size)
178
190
 
179
191
  duplicate_options = sorted({value for value in option_values if option_values.count(value) > 1})
180
192
  if duplicate_options:
@@ -207,6 +219,7 @@ def sortable_multiselect(
207
219
  empty_message=empty_message,
208
220
  no_options_placeholder=no_options_placeholder,
209
221
  selected_position=selected_position,
222
+ icon_size=icon_size_value,
210
223
  key=key,
211
224
  default=default_values,
212
225
  )
@@ -1 +1 @@
1
- :root{font-family:system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,sans-serif;color:#111827}body{margin:0}button,input{font:inherit}.sortable-multiselect{box-sizing:border-box;width:100%;padding:2px 0 6px}.component-label{display:block;margin:0 0 6px;color:#31333f;font-size:14px;font-weight:400}.search-combobox{position:relative}.search-input{box-sizing:border-box;width:100%;min-height:38px;border:1px solid #d1d5db;border-radius:6px;background:#fff;color:#111827;padding:6px 10px}.search-input:focus{border-color:#ff4b4b;box-shadow:0 0 0 1px #ff4b4b;outline:none}.search-input:disabled{background:#f9fafb;color:#6b7280}.options-list{background:#fff;border:1px solid #d1d5db;border-radius:6px;box-shadow:0 6px 18px #31333f24;box-sizing:border-box;left:0;list-style:none;margin:4px 0 0;max-height:190px;overflow-y:auto;padding:4px;position:absolute;right:0;top:100%;z-index:10}.option-item,.option-empty{align-items:center;border-radius:4px;box-sizing:border-box;color:#111827;display:flex;gap:8px;min-height:32px;padding:7px 9px}.option-item{cursor:pointer}.option-item.highlighted,.option-item:hover{background:#f3f4f6}.option-empty{color:#6b7280}.selected-list{display:flex;flex-direction:column;gap:6px;list-style:none;margin:8px 0 0;padding:0}.sortable-item{align-items:center;background:var(--item-bg, #ffffff);border:1px solid #d1d5db;border-radius:6px;box-sizing:border-box;color:var(--item-fg, #111827);display:grid;gap:8px;grid-template-columns:34px minmax(0,1fr) auto;min-height:40px;padding:4px}.sortable-item.with-number{grid-template-columns:34px 30px minmax(0,1fr) auto}.sortable-item.dragging{border-color:#ff4b4b;box-shadow:0 4px 12px #31333f24}.drag-handle,.item-actions button{align-items:center;background:transparent;border:1px solid transparent;border-radius:4px;color:var(--item-muted-fg, #374151);cursor:pointer;display:inline-flex;height:30px;justify-content:center;min-width:30px;padding:0 7px}.drag-handle:hover,.item-actions button:hover{background:#f3f4f6}.drag-handle:focus,.item-actions button:focus{border-color:#ff4b4b;outline:none}.drag-handle:disabled,.item-actions button:disabled{color:color-mix(in srgb,var(--item-muted-fg, #374151) 45%,transparent);cursor:not-allowed}.item-content{align-items:center;display:inline-flex;gap:8px;min-width:0}.item-label{min-width:0;overflow-wrap:anywhere}.item-icon,.option-icon{border-radius:4px;flex:0 0 auto;height:20px;object-fit:contain;width:20px}.item-number{align-items:center;background:color-mix(in srgb,var(--item-bg, #f3f4f6) 72%,#ffffff);border-radius:999px;color:var(--item-fg, #4b5563);display:inline-flex;font-size:12px;font-weight:600;height:24px;justify-content:center;line-height:1;min-width:24px;padding:0 6px}.item-actions{display:inline-flex;gap:2px}.empty-state{border:1px dashed #d1d5db;border-radius:6px;color:#6b7280;margin-top:8px;padding:10px;text-align:center}.selected-position-top .selected-list,.selected-position-top .empty-state{margin:0 0 8px}
1
+ :root{font-family:system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,sans-serif;color:#111827}body{margin:0}button,input{font:inherit}.sortable-multiselect{box-sizing:border-box;width:100%;padding:2px 0 6px}.component-label{display:block;margin:0 0 6px;color:#31333f;font-size:14px;font-weight:400}.search-combobox{position:relative}.search-input{box-sizing:border-box;width:100%;min-height:38px;border:1px solid #d1d5db;border-radius:6px;background:#fff;color:#111827;padding:6px 10px}.search-input:focus{border-color:#ff4b4b;box-shadow:0 0 0 1px #ff4b4b;outline:none}.search-input:disabled{background:#f9fafb;color:#6b7280}.options-list{background:#fff;border:1px solid #d1d5db;border-radius:6px;box-shadow:0 6px 18px #31333f24;box-sizing:border-box;left:0;list-style:none;margin:4px 0 0;max-height:190px;overflow-y:auto;padding:4px;position:absolute;right:0;top:100%;z-index:10}.option-item,.option-empty{align-items:center;border-radius:4px;box-sizing:border-box;color:#111827;display:flex;gap:8px;min-height:32px;padding:7px 9px}.option-item{cursor:pointer}.option-item.highlighted,.option-item:hover{background:#f3f4f6}.option-empty{color:#6b7280}.selected-list{display:flex;flex-direction:column;gap:6px;list-style:none;margin:8px 0 0;padding:0}.sortable-item{align-items:center;background:var(--item-bg, #ffffff);border:1px solid #d1d5db;border-radius:6px;box-sizing:border-box;color:var(--item-fg, #111827);display:grid;gap:8px;grid-template-columns:34px minmax(0,1fr) auto;min-height:40px;padding:4px}.sortable-item.with-number{grid-template-columns:34px 30px minmax(0,1fr) auto}.sortable-item.dragging{border-color:#ff4b4b;box-shadow:0 4px 12px #31333f24}.drag-handle,.item-actions button{align-items:center;background:transparent;border:1px solid transparent;border-radius:4px;color:var(--item-muted-fg, #374151);cursor:pointer;display:inline-flex;height:30px;justify-content:center;min-width:30px;padding:0 7px}.drag-handle:hover,.item-actions button:hover{background:#f3f4f6}.drag-handle:focus,.item-actions button:focus{border-color:#ff4b4b;outline:none}.drag-handle:disabled,.item-actions button:disabled{color:color-mix(in srgb,var(--item-muted-fg, #374151) 45%,transparent);cursor:not-allowed}.item-content{align-items:center;display:inline-flex;gap:8px;min-width:0}.item-label{min-width:0;overflow-wrap:anywhere}.item-icon,.option-icon{border-radius:4px;flex:0 0 auto;height:var(--icon-size, 20px);object-fit:contain;width:var(--icon-size, 20px)}.item-number{align-items:center;background:color-mix(in srgb,var(--item-bg, #f3f4f6) 72%,#ffffff);border-radius:999px;color:var(--item-fg, #4b5563);display:inline-flex;font-size:12px;font-weight:600;height:24px;justify-content:center;line-height:1;min-width:24px;padding:0 6px}.item-actions{display:inline-flex;gap:2px}.empty-state{border:1px dashed #d1d5db;border-radius:6px;color:#6b7280;margin-top:8px;padding:10px;text-align:center}.selected-position-top .selected-list,.selected-position-top .empty-state{margin:0 0 8px}