docstr: Display a chat input widget.
  
  .. warning::
      Chat input can only be used once per app page and inside the main area of the app.
      It cannot be used in the sidebar, columns, expanders, forms or tabs.
      We plan to support this in the future.
  
  Parameters
  ----------
  placeholder : str
      A placeholder text shown when the chat input is empty. Defaults to
      "Your message". For accessibility reasons, you should not use an
      empty string.
  
  key : str or int
      An optional string or integer to use as the unique key for the widget.
      If this is omitted, a key will be generated for the widget based on
      its content. Multiple widgets of the same type may not share the same key.
  
  max_chars : int or None
      The maximum number of characters that can be entered. If None
      (default), there will be no maximum.
  
  disabled : bool
      Whether the chat input should be disabled. Defaults to False.
  
  on_submit : callable
      An optional callback invoked when the chat input's value is submitted.
  
  args : tuple
      An optional tuple of args to pass to the callback.
  
  kwargs : dict
      An optional dict of kwargs to pass to the callback.
  
  Returns
  -------
  str or None
      The current (non-empty) value of the text input widget on the last
      run of the app, None otherwise.
  
  Examples
  --------
  >>> import streamlit as st
  >>>
  >>> prompt = st.chat_input("Say something")
  >>> if prompt:
  ...     st.write(f"User has sent the following prompt: {prompt}")
  
  .. output ::
      https://doc-chat-input.streamlit.app/
      height: 350px
docstr_tok: ["Display","a","chat","input","widget",".","..","warning",":",":","Chat","input","can","only","be","used","once","per","app","page","and","inside","the","main","area","of","the","app",".","It","can","not","be","used","in","the","sidebar",",","columns",",","expanders",",","forms","or","tabs",".","We","plan","to","support","this","in","the","future",".","Parameters","--","--","--","--","--","placeholder",":","str","A","placeholder","text","shown","when","the","chat","input","is","empty",".","Defaults","to","``","Your","message","''",".","For","accessibility","reasons",",","you","should","not","use","an","empty","string",".","key",":","str","or","int","An","optional","string","or","integer","to","use","as","the","unique","key","for","the","widget",".","If","this","is","omitted",",","a","key","will","be","generated","for","the","widget","based","on","its","content",".","Multiple","widgets","of","the","same","type","may","not","share","the","same","key",".","max_chars",":","int","or","None","The","maximum","number","of","characters","that","can","be","entered",".","If","None","(","default",")",",","there","will","be","no","maximum",".","disabled",":","bool","Whether","the","chat","input","should","be","disabled",".","Defaults","to","False",".","on_submit",":","callable","An","optional","callback","invoked","when","the","chat","input","'s","value","is","submitted",".","args",":","tuple","An","optional","tuple","of","args","to","pass","to","the","callback",".","kwargs",":","dict","An","optional","dict","of","kwargs","to","pass","to","the","callback",".","Returns","--","--","--","-","str","or","None","The","current","(","non-empty",")","value","of","the","text","input","widget","on","the","last","run","of","the","app",",","None","otherwise",".","Examples","--","--","--","--",">",">",">","import","streamlit","as","st",">",">",">",">",">",">","prompt","=","st.chat_input","(","``","Say","something","''",")",">",">",">","if","prompt",":","...","st.write","(","f","''","User","has","sent","the","following","prompt",":","{","prompt","}","''",")","..","output",":",":","https",":","\/\/doc-chat-input.streamlit.app\/","height",":","350px"]
code: def chat_input(
      self,
      placeholder: str = "Your message",
      *,
      key: Key | None = None,
      max_chars: int | None = None,
      disabled: bool = False,
      on_submit: WidgetCallback | None = None,
      args: WidgetArgs | None = None,
      kwargs: WidgetKwargs | None = None,
  ) -> str | None:
      """Display a chat input widget.
  
      .. warning::
          Chat input can only be used once per app page and inside the main area of the app.
          It cannot be used in the sidebar, columns, expanders, forms or tabs.
          We plan to support this in the future.
  
      Parameters
      ----------
      placeholder : str
          A placeholder text shown when the chat input is empty. Defaults to
          "Your message". For accessibility reasons, you should not use an
          empty string.
  
      key : str or int
          An optional string or integer to use as the unique key for the widget.
          If this is omitted, a key will be generated for the widget based on
          its content. Multiple widgets of the same type may not share the same key.
  
      max_chars : int or None
          The maximum number of characters that can be entered. If None
          (default), there will be no maximum.
  
      disabled : bool
          Whether the chat input should be disabled. Defaults to False.
  
      on_submit : callable
          An optional callback invoked when the chat input's value is submitted.
  
      args : tuple
          An optional tuple of args to pass to the callback.
  
      kwargs : dict
          An optional dict of kwargs to pass to the callback.
  
      Returns
      -------
      str or None
          The current (non-empty) value of the text input widget on the last
          run of the app, None otherwise.
  
      Examples
      --------
      >>> import streamlit as st
      >>>
      >>> prompt = st.chat_input("Say something")
      >>> if prompt:
      ...     st.write(f"User has sent the following prompt: {prompt}")
  
      .. output ::
          https://doc-chat-input.streamlit.app/
          height: 350px
  
      """
      # We default to an empty string here and disallow user choice intentionally
      default = ""
      key = to_key(key)
      check_callback_rules(self.dg, on_submit)
      check_session_state_rules(
          default_value=default, key=key, writes_allowed=False
      )
  
      ctx = get_script_run_ctx()
      id = compute_widget_id(
          "chat_input",
          user_key=key,
          key=key,
          placeholder=placeholder,
          max_chars=max_chars,
          page=ctx.page_script_hash if ctx else None,
      )
  
      # We omit this check for scripts running outside streamlit, because
      # they will have no script_run_ctx.
      if runtime.exists():
          if (
              len(list(self.dg._active_dg._parent_block_types)) > 0
              or self.dg._active_dg._root_container
              == RootContainer.SIDEBAR
          ):
              # TODO: This allows the user to create a chat_input inside a
              # container but it still cannot be in other containers. This is
              # a result of the Vertical field not being set in Blocks by
              # default and seems like a "bug", but one that is not producing
              # major issues. We should look into what's the correct behavior
              # to implement.
              raise StreamlitAPIException(
                  DISALLOWED_CONTAINERS_ERROR_TEXT
              )
  
      chat_input_proto = ChatInputProto()
      chat_input_proto.id = id
      chat_input_proto.placeholder = str(placeholder)
  
      if max_chars is not None:
          chat_input_proto.max_chars = max_chars
  
      chat_input_proto.default = default
      chat_input_proto.position = ChatInputProto.Position.BOTTOM
  
      serde = ChatInputSerde()
      widget_state = register_widget(
          "chat_input",
          chat_input_proto,
          user_key=key,
          on_change_handler=on_submit,
          args=args,
          kwargs=kwargs,
          deserializer=serde.deserialize,
          serializer=serde.serialize,
          ctx=ctx,
      )
  
      chat_input_proto.disabled = disabled
      if widget_state.value_changed and widget_state.value is not None:
          chat_input_proto.value = widget_state.value
          chat_input_proto.set_value = True
  
      self.dg._enqueue("chat_input", chat_input_proto)
      return (
          widget_state.value if not widget_state.value_changed else None
      )
  
imports: from __future__ import annotations
  from dataclasses import dataclass
  from enum import Enum
  from typing import TYPE_CHECKING, Optional, Tuple, cast
  from typing_extensions import Literal
  from streamlit import runtime
  from streamlit.elements.image import AtomicImage, WidthBehaviour, image_to_url
  from streamlit.elements.utils import check_callback_rules, check_session_state_rules
  from streamlit.errors import StreamlitAPIException
  from streamlit.proto.Block_pb2 import Block
  from streamlit.proto.ChatInput_pb2 import ChatInput
  from streamlit.proto.Common_pb2 import StringTriggerValue
  from streamlit.proto.RootContainer_pb2 import RootContainer
  from streamlit.runtime.metrics_util import gather_metrics
  from streamlit.runtime.scriptrunner import get_script_run_ctx
  from streamlit.runtime.state import WidgetArgs, WidgetCallback, WidgetKwargs, register_widget
  from streamlit.runtime.state.common import compute_widget_id
  from streamlit.string_util import is_emoji
  from streamlit.type_util import Key, to_key
label_desc: Use image node_id 2 for calling the ChatMixin obj's underlying member method code with example usage: obj.chat_input(placeholder) and returns: unknown