streamlit-nightly 1.38.1.dev20240916__py2.py3-none-any.whl → 1.38.1.dev20240918__py2.py3-none-any.whl

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 (44) hide show
  1. streamlit/commands/navigation.py +9 -0
  2. streamlit/components/v1/custom_component.py +2 -6
  3. streamlit/elements/arrow.py +1 -3
  4. streamlit/elements/form.py +10 -1
  5. streamlit/elements/layouts.py +6 -1
  6. streamlit/elements/lib/utils.py +52 -6
  7. streamlit/elements/media.py +16 -5
  8. streamlit/elements/plotly_chart.py +1 -3
  9. streamlit/elements/vega_charts.py +1 -3
  10. streamlit/elements/widgets/button.py +7 -5
  11. streamlit/elements/widgets/button_group.py +1 -3
  12. streamlit/elements/widgets/camera_input.py +1 -3
  13. streamlit/elements/widgets/chat.py +2 -2
  14. streamlit/elements/widgets/checkbox.py +1 -3
  15. streamlit/elements/widgets/color_picker.py +1 -3
  16. streamlit/elements/widgets/data_editor.py +1 -3
  17. streamlit/elements/widgets/file_uploader.py +1 -3
  18. streamlit/elements/widgets/multiselect.py +1 -3
  19. streamlit/elements/widgets/number_input.py +1 -3
  20. streamlit/elements/widgets/radio.py +1 -3
  21. streamlit/elements/widgets/select_slider.py +1 -3
  22. streamlit/elements/widgets/selectbox.py +1 -3
  23. streamlit/elements/widgets/slider.py +1 -3
  24. streamlit/elements/widgets/text_widgets.py +2 -6
  25. streamlit/elements/widgets/time_widgets.py +2 -6
  26. streamlit/proto/Block_pb2.py +13 -13
  27. streamlit/proto/Block_pb2.pyi +4 -1
  28. streamlit/proto/Navigation_pb2.py +4 -4
  29. streamlit/proto/Navigation_pb2.pyi +4 -1
  30. streamlit/runtime/state/session_state.py +62 -17
  31. streamlit/static/asset-manifest.json +6 -6
  32. streamlit/static/index.html +1 -1
  33. streamlit/static/static/js/{1086.b7ec1344.chunk.js → 1086.464de8f9.chunk.js} +1 -1
  34. streamlit/static/static/js/{1260.eaaa4e75.chunk.js → 1260.e6289cc2.chunk.js} +1 -1
  35. streamlit/static/static/js/{5618.f7838309.chunk.js → 5618.0a42d599.chunk.js} +1 -1
  36. streamlit/static/static/js/{954.88cae675.chunk.js → 954.1da91b19.chunk.js} +2 -2
  37. streamlit/static/static/js/{main.50e02474.js → main.e8447cae.js} +5 -5
  38. {streamlit_nightly-1.38.1.dev20240916.dist-info → streamlit_nightly-1.38.1.dev20240918.dist-info}/METADATA +1 -1
  39. {streamlit_nightly-1.38.1.dev20240916.dist-info → streamlit_nightly-1.38.1.dev20240918.dist-info}/RECORD +44 -44
  40. /streamlit/static/static/js/{main.50e02474.js.LICENSE.txt → main.e8447cae.js.LICENSE.txt} +0 -0
  41. {streamlit_nightly-1.38.1.dev20240916.data → streamlit_nightly-1.38.1.dev20240918.data}/scripts/streamlit.cmd +0 -0
  42. {streamlit_nightly-1.38.1.dev20240916.dist-info → streamlit_nightly-1.38.1.dev20240918.dist-info}/WHEEL +0 -0
  43. {streamlit_nightly-1.38.1.dev20240916.dist-info → streamlit_nightly-1.38.1.dev20240918.dist-info}/entry_points.txt +0 -0
  44. {streamlit_nightly-1.38.1.dev20240916.dist-info → streamlit_nightly-1.38.1.dev20240918.dist-info}/top_level.txt +0 -0
@@ -57,6 +57,7 @@ def navigation(
57
57
  pages: list[StreamlitPage] | dict[SectionHeader, list[StreamlitPage]],
58
58
  *,
59
59
  position: Literal["sidebar", "hidden"] = "sidebar",
60
+ expanded: bool = False,
60
61
  ) -> StreamlitPage:
61
62
  """
62
63
  Configure the available pages in a multipage app.
@@ -102,6 +103,12 @@ def navigation(
102
103
  If there is only one page in ``pages``, the navigation will be hidden
103
104
  for any value of ``position``.
104
105
 
106
+ expanded: bool
107
+ Whether the navigation menu should be expanded. If ``True``,
108
+ the navigation menu will always be expanded. If ``False``, the
109
+ navigation menu will be collapsed and will include a button
110
+ to view more options.
111
+
105
112
  Returns
106
113
  -------
107
114
  StreamlitPage
@@ -215,6 +222,8 @@ def navigation(
215
222
  msg.navigation.position = NavigationProto.Position.HIDDEN
216
223
  else:
217
224
  msg.navigation.position = NavigationProto.Position.SIDEBAR
225
+
226
+ msg.navigation.expanded = expanded
218
227
  msg.navigation.sections[:] = nav_sections.keys()
219
228
  for section_header in nav_sections:
220
229
  for page in nav_sections[section_header]:
@@ -173,23 +173,19 @@ And if you're using Streamlit Cloud, add "pyarrow" to your requirements.txt."""
173
173
  computed_id = compute_and_register_element_id(
174
174
  "component_instance",
175
175
  user_key=key,
176
- name=self.name,
177
176
  form_id=current_form_id(dg),
177
+ name=self.name,
178
178
  url=self.url,
179
- key=key,
180
179
  json_args=serialized_json_args,
181
180
  special_args=special_args,
182
- page=ctx.active_script_hash if ctx else None,
183
181
  )
184
182
  else:
185
183
  computed_id = compute_and_register_element_id(
186
184
  "component_instance",
187
185
  user_key=key,
188
- name=self.name,
189
186
  form_id=current_form_id(dg),
187
+ name=self.name,
190
188
  url=self.url,
191
- key=key,
192
- page=ctx.active_script_hash if ctx else None,
193
189
  )
194
190
  element.component_instance.id = computed_id
195
191
 
@@ -568,17 +568,15 @@ class ArrowMixin:
568
568
  proto.id = compute_and_register_element_id(
569
569
  "dataframe",
570
570
  user_key=key,
571
+ form_id=proto.form_id,
571
572
  data=proto.data,
572
573
  width=width,
573
574
  height=height,
574
575
  use_container_width=use_container_width,
575
576
  column_order=proto.column_order,
576
577
  column_config=proto.columns,
577
- key=key,
578
578
  selection_mode=selection_mode,
579
579
  is_selection_activated=is_selection_activated,
580
- form_id=proto.form_id,
581
- page=ctx.active_script_hash if ctx else None,
582
580
  )
583
581
 
584
582
  serde = DataframeSelectionSerde()
@@ -61,7 +61,12 @@ def _build_duplicate_form_message(user_key: str | None = None) -> str:
61
61
  class FormMixin:
62
62
  @gather_metrics("form")
63
63
  def form(
64
- self, key: str, clear_on_submit: bool = False, *, border: bool = True
64
+ self,
65
+ key: str,
66
+ clear_on_submit: bool = False,
67
+ *,
68
+ enter_to_submit: bool = True,
69
+ border: bool = True,
65
70
  ) -> DeltaGenerator:
66
71
  """Create a form that batches elements together with a "Submit" button.
67
72
 
@@ -93,6 +98,9 @@ class FormMixin:
93
98
  values after the user presses the Submit button. Defaults to False.
94
99
  (Note that Custom Components are unaffected by this flag, and
95
100
  will not be reset to their defaults on form submission.)
101
+ enter_to_submit : bool
102
+ Whether to submit the form when a user presses Enter while
103
+ interacting with a widget inside the form. Defaults to True.
96
104
  border : bool
97
105
  Whether to show a border around the form. Defaults to True.
98
106
 
@@ -159,6 +167,7 @@ class FormMixin:
159
167
  block_proto = Block_pb2.Block()
160
168
  block_proto.form.form_id = form_id
161
169
  block_proto.form.clear_on_submit = clear_on_submit
170
+ block_proto.form.enter_to_submit = enter_to_submit
162
171
  block_proto.form.border = border
163
172
  block_dg = self.dg._block(block_proto)
164
173
 
@@ -162,8 +162,13 @@ class LayoutsMixin:
162
162
  block_proto.vertical.border = True
163
163
 
164
164
  if key:
165
+ # At the moment, the ID is only used for extracting the
166
+ # key on the frontend and setting it as CSS class.
167
+ # There are plans to use the ID for other container features
168
+ # in the future. This might require including more container
169
+ # parameters in the ID calculation.
165
170
  block_proto.id = compute_and_register_element_id(
166
- "container", user_key=key, height=height, border=border
171
+ "container", user_key=key, form_id=None
167
172
  )
168
173
 
169
174
  return self.dg._block(block_proto)
@@ -90,7 +90,9 @@ def to_key(key: Key | None) -> str | None:
90
90
  return None if key is None else str(key)
91
91
 
92
92
 
93
- def _register_element_id(element_type: str, element_id: str) -> None:
93
+ def _register_element_id(
94
+ ctx: ScriptRunContext, element_type: str, element_id: str
95
+ ) -> None:
94
96
  """Register the element ID and key for the given element.
95
97
 
96
98
  If the element ID or key is not unique, an error is raised.
@@ -114,8 +116,8 @@ def _register_element_id(element_type: str, element_id: str) -> None:
114
116
  If the element ID is not unique.
115
117
 
116
118
  """
117
- ctx = get_script_run_ctx()
118
- if ctx is None or not element_id:
119
+
120
+ if not element_id:
119
121
  return
120
122
 
121
123
  if user_key := user_key_from_element_id(element_id):
@@ -148,6 +150,12 @@ def _compute_element_id(
148
150
  """
149
151
  h = hashlib.new("md5", **HASHLIB_KWARGS)
150
152
  h.update(element_type.encode("utf-8"))
153
+ if user_key:
154
+ # Adding this to the hash isn't necessary for uniqueness since the
155
+ # key is also appended to the ID as raw text. But since the hash and
156
+ # the appending of the key are two slightly different aspects, it
157
+ # still gets put into the hash.
158
+ h.update(user_key.encode("utf-8"))
151
159
  # This will iterate in a consistent order when the provided arguments have
152
160
  # consistent order; dicts are always in insertion order.
153
161
  for k, v in kwargs.items():
@@ -158,7 +166,9 @@ def _compute_element_id(
158
166
 
159
167
  def compute_and_register_element_id(
160
168
  element_type: str,
161
- user_key: str | None = None,
169
+ *,
170
+ user_key: str | None,
171
+ form_id: str | None,
162
172
  **kwargs: SAFE_VALUES | Iterable[SAFE_VALUES],
163
173
  ) -> str:
164
174
  """Compute and register the ID for the given element.
@@ -175,9 +185,45 @@ def compute_and_register_element_id(
175
185
  The element ID gets registered to make sure that only one ID and user-specified
176
186
  key exists at the same time. If there are duplicated IDs or keys, an error
177
187
  is raised.
188
+
189
+ Parameters
190
+ ----------
191
+ element_type : str
192
+ The type (command name) of the element to register.
193
+
194
+ user_key : str | None
195
+ The user-specified key for the element. `None` if no key is provided
196
+ or if the element doesn't support a specifying a key.
197
+
198
+ form_id : str | None
199
+ The ID of the form that the element belongs to. `None` or empty string
200
+ if the element doesn't belong to a form or doesn't support forms.
201
+
202
+ kwargs : SAFE_VALUES | Iterable[SAFE_VALUES]
203
+ The arguments to use to compute the element ID.
204
+ The arguments must be stable, deterministic values.
205
+ Some common parameters like key, disabled,
206
+ format_func, label_visibility, args, kwargs, on_change, and
207
+ the active_script_hash are not supposed to be added here
178
208
  """
179
- element_id = _compute_element_id(element_type, user_key, **kwargs)
180
- _register_element_id(element_type, element_id)
209
+ ctx = get_script_run_ctx()
210
+
211
+ # If form_id is provided, add it to the kwargs.
212
+ kwargs_to_use = {"form_id": form_id, **kwargs} if form_id else kwargs
213
+
214
+ if ctx:
215
+ # Add the active script hash to give elements on different
216
+ # pages unique IDs.
217
+ kwargs_to_use["active_script_hash"] = ctx.active_script_hash
218
+
219
+ element_id = _compute_element_id(
220
+ element_type,
221
+ user_key,
222
+ **kwargs_to_use,
223
+ )
224
+
225
+ if ctx:
226
+ _register_element_id(ctx, element_type, element_id)
181
227
  return element_id
182
228
 
183
229
 
@@ -23,6 +23,7 @@ from typing import TYPE_CHECKING, Dict, Final, Union, cast
23
23
  from typing_extensions import TypeAlias
24
24
 
25
25
  from streamlit import runtime, type_util, url_util
26
+ from streamlit.elements.lib.form_utils import current_form_id
26
27
  from streamlit.elements.lib.subtitle_utils import process_subtitle_data
27
28
  from streamlit.elements.lib.utils import compute_and_register_element_id
28
29
  from streamlit.errors import StreamlitAPIException
@@ -30,7 +31,6 @@ from streamlit.proto.Audio_pb2 import Audio as AudioProto
30
31
  from streamlit.proto.Video_pb2 import Video as VideoProto
31
32
  from streamlit.runtime import caching
32
33
  from streamlit.runtime.metrics_util import gather_metrics
33
- from streamlit.runtime.scriptrunner_utils.script_run_context import get_script_run_ctx
34
34
  from streamlit.time_util import time_to_seconds
35
35
  from streamlit.type_util import NumpyShape
36
36
 
@@ -191,6 +191,7 @@ class MediaMixin:
191
191
  end_time,
192
192
  loop,
193
193
  autoplay,
194
+ form_id=current_form_id(self.dg),
194
195
  )
195
196
  return self.dg._enqueue("audio", audio_proto)
196
197
 
@@ -349,6 +350,7 @@ class MediaMixin:
349
350
  loop,
350
351
  autoplay,
351
352
  muted,
353
+ form_id=current_form_id(self.dg),
352
354
  )
353
355
  return self.dg._enqueue("video", video_proto)
354
356
 
@@ -457,6 +459,7 @@ def marshall_video(
457
459
  loop: bool = False,
458
460
  autoplay: bool = False,
459
461
  muted: bool = False,
462
+ form_id: str | None = None,
460
463
  ) -> None:
461
464
  """Marshalls a video proto, using url processors as needed.
462
465
 
@@ -499,6 +502,9 @@ def marshall_video(
499
502
  muted: bool
500
503
  Whether the video should play with the audio silenced. This can be used to
501
504
  enable autoplay without user interaction. Defaults to False.
505
+ form_id: str | None
506
+ The ID of the form that this element is placed in. Provide None if
507
+ the element is not placed in a form.
502
508
  """
503
509
 
504
510
  if start_time < 0 or (end_time is not None and end_time <= start_time):
@@ -565,10 +571,12 @@ def marshall_video(
565
571
  ) from original_err
566
572
 
567
573
  if autoplay:
568
- ctx = get_script_run_ctx()
569
574
  proto.autoplay = autoplay
570
575
  proto.id = compute_and_register_element_id(
571
576
  "video",
577
+ # video does not yet allow setting a user-defined key
578
+ user_key=None,
579
+ form_id=form_id,
572
580
  url=proto.url,
573
581
  mimetype=mimetype,
574
582
  start_time=start_time,
@@ -576,7 +584,6 @@ def marshall_video(
576
584
  loop=loop,
577
585
  autoplay=autoplay,
578
586
  muted=muted,
579
- page=ctx.active_script_hash if ctx else None,
580
587
  )
581
588
 
582
589
 
@@ -696,6 +703,7 @@ def marshall_audio(
696
703
  end_time: int | None = None,
697
704
  loop: bool = False,
698
705
  autoplay: bool = False,
706
+ form_id: str | None = None,
699
707
  ) -> None:
700
708
  """Marshalls an audio proto, using data and url processors as needed.
701
709
 
@@ -722,6 +730,9 @@ def marshall_audio(
722
730
  autoplay : bool
723
731
  Whether the audio should start playing automatically.
724
732
  Browsers will not autoplay audio files if the user has not interacted with the page yet.
733
+ form_id: str | None
734
+ The ID of the form that this element is placed in. Provide None if
735
+ the element is not placed in a form.
725
736
  """
726
737
 
727
738
  proto.start_time = start_time
@@ -739,10 +750,11 @@ def marshall_audio(
739
750
  _marshall_av_media(coordinates, proto, data, mimetype)
740
751
 
741
752
  if autoplay:
742
- ctx = get_script_run_ctx()
743
753
  proto.autoplay = autoplay
744
754
  proto.id = compute_and_register_element_id(
745
755
  "audio",
756
+ user_key=None,
757
+ form_id=form_id,
746
758
  url=proto.url,
747
759
  mimetype=mimetype,
748
760
  start_time=start_time,
@@ -750,5 +762,4 @@ def marshall_audio(
750
762
  end_time=end_time,
751
763
  loop=loop,
752
764
  autoplay=autoplay,
753
- page=ctx.active_script_hash if ctx else None,
754
765
  )
@@ -506,15 +506,13 @@ class PlotlyMixin:
506
506
  plotly_chart_proto.id = compute_and_register_element_id(
507
507
  "plotly_chart",
508
508
  user_key=key,
509
- key=key,
509
+ form_id=plotly_chart_proto.form_id,
510
510
  plotly_spec=plotly_chart_proto.spec,
511
511
  plotly_config=plotly_chart_proto.config,
512
512
  selection_mode=selection_mode,
513
513
  is_selection_activated=is_selection_activated,
514
514
  theme=theme,
515
- form_id=plotly_chart_proto.form_id,
516
515
  use_container_width=use_container_width,
517
- page=ctx.active_script_hash if ctx else None,
518
516
  )
519
517
 
520
518
  if is_selection_activated:
@@ -1894,7 +1894,7 @@ class VegaChartsMixin:
1894
1894
  vega_lite_proto.id = compute_and_register_element_id(
1895
1895
  "arrow_vega_lite_chart",
1896
1896
  user_key=key,
1897
- key=key,
1897
+ form_id=vega_lite_proto.form_id,
1898
1898
  vega_lite_spec=vega_lite_proto.spec,
1899
1899
  # The data is either in vega_lite_proto.data.data
1900
1900
  # or in a named dataset in vega_lite_proto.datasets
@@ -1905,8 +1905,6 @@ class VegaChartsMixin:
1905
1905
  theme=theme,
1906
1906
  use_container_width=use_container_width,
1907
1907
  selection_mode=parsed_selection_modes,
1908
- form_id=vega_lite_proto.form_id,
1909
- page=ctx.active_script_hash if ctx else None,
1910
1908
  )
1911
1909
 
1912
1910
  serde = VegaLiteStateSerde(parsed_selection_modes)
@@ -673,15 +673,15 @@ class ButtonMixin:
673
673
  element_id = compute_and_register_element_id(
674
674
  "download_button",
675
675
  user_key=key,
676
+ # download_button is not allowed to be used in a form.
677
+ form_id=None,
676
678
  label=label,
677
679
  icon=icon,
678
680
  file_name=file_name,
679
681
  mime=mime,
680
- key=key,
681
682
  help=help,
682
683
  type=type,
683
684
  use_container_width=use_container_width,
684
- page=ctx.active_script_hash if ctx else None,
685
685
  )
686
686
 
687
687
  if is_in_form(self.dg):
@@ -853,17 +853,19 @@ class ButtonMixin:
853
853
  enable_check_callback_rules=not is_form_submitter,
854
854
  )
855
855
 
856
+ # Only the form submitter button needs a form ID at the moment.
857
+ form_id = current_form_id(self.dg) if is_form_submitter else ""
856
858
  element_id = compute_and_register_element_id(
857
859
  "button",
858
860
  user_key=key,
861
+ # Only the
862
+ form_id=form_id,
859
863
  label=label,
860
864
  icon=icon,
861
- key=key,
862
865
  help=help,
863
866
  is_form_submitter=is_form_submitter,
864
867
  type=type,
865
868
  use_container_width=use_container_width,
866
- page=ctx.active_script_hash if ctx else None,
867
869
  )
868
870
 
869
871
  # It doesn't make sense to create a button inside a form (except
@@ -886,7 +888,7 @@ class ButtonMixin:
886
888
  button_proto.label = label
887
889
  button_proto.default = False
888
890
  button_proto.is_form_submitter = is_form_submitter
889
- button_proto.form_id = current_form_id(self.dg)
891
+ button_proto.form_id = form_id
890
892
  button_proto.type = type
891
893
  button_proto.use_container_width = use_container_width
892
894
  button_proto.disabled = disabled
@@ -399,12 +399,10 @@ class ButtonGroupMixin:
399
399
  element_id = compute_and_register_element_id(
400
400
  widget_name,
401
401
  user_key=key,
402
- key=key,
402
+ form_id=form_id,
403
403
  options=formatted_options,
404
404
  default=default,
405
- form_id=form_id,
406
405
  click_mode=click_mode,
407
- page=ctx.active_script_hash if ctx else None,
408
406
  )
409
407
 
410
408
  proto = _build_proto(
@@ -206,11 +206,9 @@ class CameraInputMixin:
206
206
  element_id = compute_and_register_element_id(
207
207
  "camera_input",
208
208
  user_key=key,
209
+ form_id=current_form_id(self.dg),
209
210
  label=label,
210
- key=key,
211
211
  help=help,
212
- form_id=current_form_id(self.dg),
213
- page=ctx.active_script_hash if ctx else None,
214
212
  )
215
213
 
216
214
  camera_input_proto = CameraInputProto()
@@ -330,10 +330,10 @@ class ChatMixin:
330
330
  element_id = compute_and_register_element_id(
331
331
  "chat_input",
332
332
  user_key=key,
333
- key=key,
333
+ # chat_input is not allowed to be used in a form.
334
+ form_id=None,
334
335
  placeholder=placeholder,
335
336
  max_chars=max_chars,
336
- page=ctx.active_script_hash if ctx else None,
337
337
  )
338
338
 
339
339
  # It doesn't make sense to create a chat input inside a form.
@@ -294,12 +294,10 @@ class CheckboxMixin:
294
294
  element_id = compute_and_register_element_id(
295
295
  "toggle" if type == CheckboxProto.StyleType.TOGGLE else "checkbox",
296
296
  user_key=key,
297
+ form_id=current_form_id(self.dg),
297
298
  label=label,
298
299
  value=bool(value),
299
- key=key,
300
300
  help=help,
301
- form_id=current_form_id(self.dg),
302
- page=ctx.active_script_hash if ctx else None,
303
301
  )
304
302
 
305
303
  checkbox_proto = CheckboxProto()
@@ -189,12 +189,10 @@ class ColorPickerMixin:
189
189
  element_id = compute_and_register_element_id(
190
190
  "color_picker",
191
191
  user_key=key,
192
+ form_id=current_form_id(self.dg),
192
193
  label=label,
193
194
  value=str(value),
194
- key=key,
195
195
  help=help,
196
- form_id=current_form_id(self.dg),
197
- page=ctx.active_script_hash if ctx else None,
198
196
  )
199
197
 
200
198
  # set value default
@@ -887,6 +887,7 @@ class DataEditorMixin:
887
887
  element_id = compute_and_register_element_id(
888
888
  "data_editor",
889
889
  user_key=key,
890
+ form_id=current_form_id(self.dg),
890
891
  data=arrow_bytes,
891
892
  width=width,
892
893
  height=height,
@@ -894,9 +895,6 @@ class DataEditorMixin:
894
895
  column_order=column_order,
895
896
  column_config_mapping=str(column_config_mapping),
896
897
  num_rows=num_rows,
897
- key=key,
898
- form_id=current_form_id(self.dg),
899
- page=ctx.active_script_hash if ctx else None,
900
898
  )
901
899
 
902
900
  proto = ArrowProto()
@@ -408,13 +408,11 @@ class FileUploaderMixin:
408
408
  element_id = compute_and_register_element_id(
409
409
  "file_uploader",
410
410
  user_key=key,
411
+ form_id=current_form_id(self.dg),
411
412
  label=label,
412
413
  type=type,
413
414
  accept_multiple_files=accept_multiple_files,
414
- key=key,
415
415
  help=help,
416
- form_id=current_form_id(self.dg),
417
- page=ctx.active_script_hash if ctx else None,
418
416
  )
419
417
 
420
418
  if type:
@@ -274,15 +274,13 @@ class MultiSelectMixin:
274
274
  element_id = compute_and_register_element_id(
275
275
  widget_name,
276
276
  user_key=key,
277
+ form_id=form_id,
277
278
  label=label,
278
279
  options=formatted_options,
279
280
  default=default_values,
280
- key=key,
281
281
  help=help,
282
282
  max_selections=max_selections,
283
283
  placeholder=placeholder,
284
- form_id=form_id,
285
- page=ctx.active_script_hash if ctx else None,
286
284
  )
287
285
 
288
286
  proto = MultiSelectProto()
@@ -359,17 +359,15 @@ class NumberInputMixin:
359
359
  element_id = compute_and_register_element_id(
360
360
  "number_input",
361
361
  user_key=key,
362
+ form_id=current_form_id(self.dg),
362
363
  label=label,
363
364
  min_value=min_value,
364
365
  max_value=max_value,
365
366
  value=value,
366
367
  step=step,
367
368
  format=format,
368
- key=key,
369
369
  help=help,
370
370
  placeholder=None if placeholder is None else str(placeholder),
371
- form_id=current_form_id(self.dg),
372
- page=ctx.active_script_hash if ctx else None,
373
371
  )
374
372
 
375
373
  # Ensure that all arguments are of the same type.
@@ -315,15 +315,13 @@ class RadioMixin:
315
315
  element_id = compute_and_register_element_id(
316
316
  "radio",
317
317
  user_key=key,
318
+ form_id=current_form_id(self.dg),
318
319
  label=label,
319
320
  options=[str(format_func(option)) for option in opt],
320
321
  index=index,
321
- key=key,
322
322
  help=help,
323
323
  horizontal=horizontal,
324
324
  captions=captions,
325
- form_id=current_form_id(self.dg),
326
- page=ctx.active_script_hash if ctx else None,
327
325
  )
328
326
 
329
327
  if not isinstance(index, int) and index is not None:
@@ -370,13 +370,11 @@ class SelectSliderMixin:
370
370
  element_id = compute_and_register_element_id(
371
371
  "select_slider",
372
372
  user_key=key,
373
+ form_id=current_form_id(self.dg),
373
374
  label=label,
374
375
  options=[str(format_func(option)) for option in opt],
375
376
  value=slider_value,
376
- key=key,
377
377
  help=help,
378
- form_id=current_form_id(self.dg),
379
- page=ctx.active_script_hash if ctx else None,
380
378
  )
381
379
 
382
380
  slider_proto = SliderProto()
@@ -287,14 +287,12 @@ class SelectboxMixin:
287
287
  element_id = compute_and_register_element_id(
288
288
  "selectbox",
289
289
  user_key=key,
290
+ form_id=current_form_id(self.dg),
290
291
  label=label,
291
292
  options=[str(format_func(option)) for option in opt],
292
293
  index=index,
293
- key=key,
294
294
  help=help,
295
295
  placeholder=placeholder,
296
- form_id=current_form_id(self.dg),
297
- page=ctx.active_script_hash if ctx else None,
298
296
  )
299
297
 
300
298
  if not isinstance(index, int) and index is not None:
@@ -545,16 +545,14 @@ class SliderMixin:
545
545
  element_id = compute_and_register_element_id(
546
546
  "slider",
547
547
  user_key=key,
548
+ form_id=current_form_id(self.dg),
548
549
  label=label,
549
550
  min_value=min_value,
550
551
  max_value=max_value,
551
552
  value=value,
552
553
  step=step,
553
554
  format=format,
554
- key=key,
555
555
  help=help,
556
- form_id=current_form_id(self.dg),
557
- page=ctx.active_script_hash if ctx else None,
558
556
  )
559
557
 
560
558
  SUPPORTED_TYPES = {
@@ -278,16 +278,14 @@ class TextWidgetsMixin:
278
278
  element_id = compute_and_register_element_id(
279
279
  "text_input",
280
280
  user_key=key,
281
+ form_id=current_form_id(self.dg),
281
282
  label=label,
282
283
  value=value,
283
284
  max_chars=max_chars,
284
- key=key,
285
285
  type=type,
286
286
  help=help,
287
287
  autocomplete=autocomplete,
288
288
  placeholder=str(placeholder),
289
- form_id=current_form_id(self.dg),
290
- page=ctx.active_script_hash if ctx else None,
291
289
  )
292
290
 
293
291
  session_state = get_session_state().filtered_state
@@ -550,15 +548,13 @@ class TextWidgetsMixin:
550
548
  element_id = compute_and_register_element_id(
551
549
  "text_area",
552
550
  user_key=key,
551
+ form_id=current_form_id(self.dg),
553
552
  label=label,
554
553
  value=value,
555
554
  height=height,
556
555
  max_chars=max_chars,
557
- key=key,
558
556
  help=help,
559
557
  placeholder=str(placeholder),
560
- form_id=current_form_id(self.dg),
561
- page=ctx.active_script_hash if ctx else None,
562
558
  )
563
559
 
564
560
  session_state = get_session_state().filtered_state